Mercurial > cortex
comparison 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 |
comparison
equal
deleted
inserted
replaced
150:e1232043656a | 151:aaacf087504c |
---|---|
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 | |
8 | |
9 | |
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) | |
16 | |
17 | |
18 (defn meta-data [blender-node key] | |
19 (if-let [data (.getUserData blender-node "properties")] | |
20 (.findValue data key) | |
21 nil)) | |
22 | |
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))))))) | |
37 | |
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 [_ _]))))) | |
60 | |
61 (def white -1) | |
62 | |
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 []))) | |
78 | |
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))) | |
85 | |
86 (defn points->image | |
87 "Take a sparse collection of points and visuliaze it as a | |
88 BufferedImage." | |
89 | |
90 ;; TODO maybe parallelize this since it's easy | |
91 | |
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))) | |
110 | |
111 image))) | |
112 | |
113 (defn average [coll] | |
114 (/ (reduce + coll) (count coll))) | |
115 | |
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)))) | |
124 | |
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))) | |
163 | |
164 #+end_src | |
165 | |
166 #+results: sense-util | |
167 : #'cortex.sense/meta-data | |
168 | |
169 | |
170 | |
171 * COMMENT generate source | |
172 #+begin_src clojure :tangle ../src/cortex/sense.clj | |
173 <<sense-util>> | |
174 #+end_src |