Mercurial > cortex
diff 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 diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/org/sense-util.org Fri Feb 03 05:52:18 2012 -0700 1.3 @@ -0,0 +1,174 @@ 1.4 +#+title: General sense/effector utilities 1.5 +#+author: Robert McIntyre 1.6 +#+email: rlm@mit.edu 1.7 +#+description: sensory utilities 1.8 +#+keywords: simulation, jMonkeyEngine3, clojure, simulated senses 1.9 +#+SETUPFILE: ../../aurellem/org/setup.org 1.10 +#+INCLUDE: ../../aurellem/org/level-0.org 1.11 + 1.12 + 1.13 +#+name: sense-util 1.14 +#+begin_src clojure 1.15 +(ns cortex.sense) 1.16 +(cortex.import/mega-import-jme3) 1.17 +(import ij.process.ImageProcessor) 1.18 +(import java.awt.image.BufferedImage) 1.19 + 1.20 + 1.21 +(defn meta-data [blender-node key] 1.22 + (if-let [data (.getUserData blender-node "properties")] 1.23 + (.findValue data key) 1.24 + nil)) 1.25 + 1.26 +(defn closest-node 1.27 + "Return the object in creature which is closest to the given node." 1.28 + ;;dylan"The closest object in creature to the given node." 1.29 + [#^Node creature #^Node eye] 1.30 + (loop [radius (float 0.01)] 1.31 + (let [results (CollisionResults.)] 1.32 + (.collideWith 1.33 + creature 1.34 + (BoundingBox. (.getWorldTranslation eye) 1.35 + radius radius radius) 1.36 + results) 1.37 + (if-let [target (first results)] 1.38 + (.getGeometry target) 1.39 + (recur (float (* 2 radius))))))) 1.40 + 1.41 +(defn bind-sense 1.42 + "Bind the sense to the Spatial such that it will maintain its 1.43 + current position relative to the Spatial no matter how the spatial 1.44 + moves. 'sense can be either a Camera or Listener object." 1.45 + [#^Spatial obj sense] 1.46 + (let [sense-offset (.subtract (.getLocation sense) 1.47 + (.getWorldTranslation obj)) 1.48 + initial-sense-rotation (Quaternion. (.getRotation sense)) 1.49 + base-anti-rotation (.inverse (.getWorldRotation obj))] 1.50 + (.addControl 1.51 + obj 1.52 + (proxy [AbstractControl] [] 1.53 + (controlUpdate [tpf] 1.54 + (let [total-rotation 1.55 + (.mult base-anti-rotation (.getWorldRotation obj))] 1.56 + (.setLocation sense 1.57 + (.add 1.58 + (.mult total-rotation sense-offset) 1.59 + (.getWorldTranslation obj))) 1.60 + (.setRotation sense 1.61 + (.mult total-rotation initial-sense-rotation)))) 1.62 + (controlRender [_ _]))))) 1.63 + 1.64 +(def white -1) 1.65 + 1.66 +(defn filter-pixels 1.67 + "List the coordinates of all pixels matching pred, within the bounds 1.68 + provided. Bounds -> [x0 y0 width height]" 1.69 + {:author "Dylan Holmes"} 1.70 + ([pred #^BufferedImage image] 1.71 + (filter-pixels pred image [0 0 (.getWidth image) (.getHeight image)])) 1.72 + ([pred #^BufferedImage image [x0 y0 width height]] 1.73 + ((fn accumulate [x y matches] 1.74 + (cond 1.75 + (>= y (+ height y0)) matches 1.76 + (>= x (+ width x0)) (recur 0 (inc y) matches) 1.77 + (pred (.getRGB image x y)) 1.78 + (recur (inc x) y (conj matches [x y])) 1.79 + :else (recur (inc x) y matches))) 1.80 + x0 y0 []))) 1.81 + 1.82 +(defn white-coordinates 1.83 + "Coordinates of all the white pixels in a subset of the image." 1.84 + ([#^BufferedImage image bounds] 1.85 + (filter-pixels #(= % white) image bounds)) 1.86 + ([#^BufferedImage image] 1.87 + (filter-pixels #(= % white) image))) 1.88 + 1.89 +(defn points->image 1.90 + "Take a sparse collection of points and visuliaze it as a 1.91 + BufferedImage." 1.92 + 1.93 + ;; TODO maybe parallelize this since it's easy 1.94 + 1.95 + [points] 1.96 + (if (empty? points) 1.97 + (BufferedImage. 1 1 BufferedImage/TYPE_BYTE_BINARY) 1.98 + (let [xs (vec (map first points)) 1.99 + ys (vec (map second points)) 1.100 + x0 (apply min xs) 1.101 + y0 (apply min ys) 1.102 + width (- (apply max xs) x0) 1.103 + height (- (apply max ys) y0) 1.104 + image (BufferedImage. (inc width) (inc height) 1.105 + BufferedImage/TYPE_INT_RGB)] 1.106 + (dorun 1.107 + (for [x (range (.getWidth image)) 1.108 + y (range (.getHeight image))] 1.109 + (.setRGB image x y 0xFF0000))) 1.110 + (dorun 1.111 + (for [index (range (count points))] 1.112 + (.setRGB image (- (xs index) x0) (- (ys index) y0) -1))) 1.113 + 1.114 + image))) 1.115 + 1.116 +(defn average [coll] 1.117 + (/ (reduce + coll) (count coll))) 1.118 + 1.119 +(defn collapse-1d 1.120 + "One dimensional analogue of collapse" 1.121 + [center line] 1.122 + (let [length (count line) 1.123 + num-above (count (filter (partial < center) line)) 1.124 + num-below (- length num-above)] 1.125 + (range (- center num-below) 1.126 + (+ center num-above)))) 1.127 + 1.128 +(defn collapse 1.129 + "Take a set of pairs of integers and collapse them into a 1.130 + contigous bitmap." 1.131 + [points] 1.132 + (if (empty? points) [] 1.133 + (let 1.134 + [num-points (count points) 1.135 + center (vector 1.136 + (int (average (map first points))) 1.137 + (int (average (map first points)))) 1.138 + flattened 1.139 + (reduce 1.140 + concat 1.141 + (map 1.142 + (fn [column] 1.143 + (map vector 1.144 + (map first column) 1.145 + (collapse-1d (second center) 1.146 + (map second column)))) 1.147 + (partition-by first (sort-by first points)))) 1.148 + squeezed 1.149 + (reduce 1.150 + concat 1.151 + (map 1.152 + (fn [row] 1.153 + (map vector 1.154 + (collapse-1d (first center) 1.155 + (map first row)) 1.156 + (map second row))) 1.157 + (partition-by second (sort-by second flattened)))) 1.158 + relocate 1.159 + (let [min-x (apply min (map first squeezed)) 1.160 + min-y (apply min (map second squeezed))] 1.161 + (map (fn [[x y]] 1.162 + [(- x min-x) 1.163 + (- y min-y)]) 1.164 + squeezed))] 1.165 + relocate))) 1.166 + 1.167 +#+end_src 1.168 + 1.169 +#+results: sense-util 1.170 +: #'cortex.sense/meta-data 1.171 + 1.172 + 1.173 + 1.174 +* COMMENT generate source 1.175 +#+begin_src clojure :tangle ../src/cortex/sense.clj 1.176 +<<sense-util>> 1.177 +#+end_src