view org/sense-util.org @ 151:aaacf087504c

refactored vision code
author Robert McIntyre <rlm@mit.edu>
date Fri, 03 Feb 2012 05:52:18 -0700
parents
children e8df6e76c3e5
line wrap: on
line source
1 #+title: General sense/effector utilities
2 #+author: Robert McIntyre
3 #+email: rlm@mit.edu
4 #+description: sensory utilities
5 #+keywords: simulation, jMonkeyEngine3, clojure, simulated senses
6 #+SETUPFILE: ../../aurellem/org/setup.org
7 #+INCLUDE: ../../aurellem/org/level-0.org
10 #+name: sense-util
11 #+begin_src clojure
12 (ns cortex.sense)
13 (cortex.import/mega-import-jme3)
14 (import ij.process.ImageProcessor)
15 (import java.awt.image.BufferedImage)
18 (defn meta-data [blender-node key]
19 (if-let [data (.getUserData blender-node "properties")]
20 (.findValue data key)
21 nil))
23 (defn closest-node
24 "Return the object in creature which is closest to the given node."
25 ;;dylan"The closest object in creature to the given node."
26 [#^Node creature #^Node eye]
27 (loop [radius (float 0.01)]
28 (let [results (CollisionResults.)]
29 (.collideWith
30 creature
31 (BoundingBox. (.getWorldTranslation eye)
32 radius radius radius)
33 results)
34 (if-let [target (first results)]
35 (.getGeometry target)
36 (recur (float (* 2 radius)))))))
38 (defn bind-sense
39 "Bind the sense to the Spatial such that it will maintain its
40 current position relative to the Spatial no matter how the spatial
41 moves. 'sense can be either a Camera or Listener object."
42 [#^Spatial obj sense]
43 (let [sense-offset (.subtract (.getLocation sense)
44 (.getWorldTranslation obj))
45 initial-sense-rotation (Quaternion. (.getRotation sense))
46 base-anti-rotation (.inverse (.getWorldRotation obj))]
47 (.addControl
48 obj
49 (proxy [AbstractControl] []
50 (controlUpdate [tpf]
51 (let [total-rotation
52 (.mult base-anti-rotation (.getWorldRotation obj))]
53 (.setLocation sense
54 (.add
55 (.mult total-rotation sense-offset)
56 (.getWorldTranslation obj)))
57 (.setRotation sense
58 (.mult total-rotation initial-sense-rotation))))
59 (controlRender [_ _])))))
61 (def white -1)
63 (defn filter-pixels
64 "List the coordinates of all pixels matching pred, within the bounds
65 provided. Bounds -> [x0 y0 width height]"
66 {:author "Dylan Holmes"}
67 ([pred #^BufferedImage image]
68 (filter-pixels pred image [0 0 (.getWidth image) (.getHeight image)]))
69 ([pred #^BufferedImage image [x0 y0 width height]]
70 ((fn accumulate [x y matches]
71 (cond
72 (>= y (+ height y0)) matches
73 (>= x (+ width x0)) (recur 0 (inc y) matches)
74 (pred (.getRGB image x y))
75 (recur (inc x) y (conj matches [x y]))
76 :else (recur (inc x) y matches)))
77 x0 y0 [])))
79 (defn white-coordinates
80 "Coordinates of all the white pixels in a subset of the image."
81 ([#^BufferedImage image bounds]
82 (filter-pixels #(= % white) image bounds))
83 ([#^BufferedImage image]
84 (filter-pixels #(= % white) image)))
86 (defn points->image
87 "Take a sparse collection of points and visuliaze it as a
88 BufferedImage."
90 ;; TODO maybe parallelize this since it's easy
92 [points]
93 (if (empty? points)
94 (BufferedImage. 1 1 BufferedImage/TYPE_BYTE_BINARY)
95 (let [xs (vec (map first points))
96 ys (vec (map second points))
97 x0 (apply min xs)
98 y0 (apply min ys)
99 width (- (apply max xs) x0)
100 height (- (apply max ys) y0)
101 image (BufferedImage. (inc width) (inc height)
102 BufferedImage/TYPE_INT_RGB)]
103 (dorun
104 (for [x (range (.getWidth image))
105 y (range (.getHeight image))]
106 (.setRGB image x y 0xFF0000)))
107 (dorun
108 (for [index (range (count points))]
109 (.setRGB image (- (xs index) x0) (- (ys index) y0) -1)))
111 image)))
113 (defn average [coll]
114 (/ (reduce + coll) (count coll)))
116 (defn collapse-1d
117 "One dimensional analogue of collapse"
118 [center line]
119 (let [length (count line)
120 num-above (count (filter (partial < center) line))
121 num-below (- length num-above)]
122 (range (- center num-below)
123 (+ center num-above))))
125 (defn collapse
126 "Take a set of pairs of integers and collapse them into a
127 contigous bitmap."
128 [points]
129 (if (empty? points) []
130 (let
131 [num-points (count points)
132 center (vector
133 (int (average (map first points)))
134 (int (average (map first points))))
135 flattened
136 (reduce
137 concat
138 (map
139 (fn [column]
140 (map vector
141 (map first column)
142 (collapse-1d (second center)
143 (map second column))))
144 (partition-by first (sort-by first points))))
145 squeezed
146 (reduce
147 concat
148 (map
149 (fn [row]
150 (map vector
151 (collapse-1d (first center)
152 (map first row))
153 (map second row)))
154 (partition-by second (sort-by second flattened))))
155 relocate
156 (let [min-x (apply min (map first squeezed))
157 min-y (apply min (map second squeezed))]
158 (map (fn [[x y]]
159 [(- x min-x)
160 (- y min-y)])
161 squeezed))]
162 relocate)))
164 #+end_src
166 #+results: sense-util
167 : #'cortex.sense/meta-data
171 * COMMENT generate source
172 #+begin_src clojure :tangle ../src/cortex/sense.clj
173 <<sense-util>>
174 #+end_src