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