view org/eyes.org @ 112:128fa71ee188

working on retina design
author Robert McIntyre <rlm@mit.edu>
date Thu, 19 Jan 2012 11:29:46 -0700
parents b7a3ba5e879b
children a980462ebe76
line wrap: on
line source
1 #+title: Simulated Sense of Sight
2 #+author: Robert McIntyre
3 #+email: rlm@mit.edu
4 #+description: Simulated sight for AI research using JMonkeyEngine3 and clojure
5 #+keywords: computer vision, jMonkeyEngine3, clojure
6 #+SETUPFILE: ../../aurellem/org/setup.org
7 #+INCLUDE: ../../aurellem/org/level-0.org
8 #+babel: :mkdirp yes :noweb yes :exports both
10 * Vision
12 I want to make creatures with eyes. Each eye can be independely moved
13 and should see its own version of the world depending on where it is.
14 #+name: eyes
15 #+begin_src clojure
16 (ns cortex.vision
17 "Simulate the sense of vision in jMonkeyEngine3. Enables multiple
18 eyes from different positions to observe the same world, and pass
19 the observed data to any arbitray function."
20 {:author "Robert McIntyre"}
21 (:use cortex.world)
22 (:import com.jme3.post.SceneProcessor)
23 (:import (com.jme3.util BufferUtils))
24 (:import java.nio.ByteBuffer)
25 (:import java.awt.image.BufferedImage)
26 (:import com.jme3.renderer.ViewPort)
27 (:import com.jme3.math.ColorRGBA))
29 (defn scene-processor
30 "Create a SceneProcessor object which wraps a vision processing
31 continuation function. The SceneProcessor will take care of
32 converting the rendered frame to a BufferedImage and passing that
33 BufferedImage to the continuation. The continuation should be a
34 function that takes a ByteBuffer which represents the image."
35 [continuation]
36 (let [byte-buffer (atom nil)
37 renderer (atom nil)]
38 (proxy [SceneProcessor] []
39 (initialize
40 [renderManager viewPort]
41 (let [cam (.getCamera viewPort)
42 width (.getWidth cam)
43 height (.getHeight cam)]
44 (reset! renderer (.getRenderer renderManager))
45 (reset! byte-buffer
46 (BufferUtils/createByteBuffer
47 (* width height 4)))))
48 (isInitialized [] (not (nil? @byte-buffer)))
49 (reshape [_ _ _])
50 (preFrame [_])
51 (postQueue [_])
52 (postFrame
53 [#^FrameBuffer fb]
54 (.clear @byte-buffer)
55 ;;(.readFrameBuffer @renderer fb @byte-buffer)
56 (continuation @byte-buffer))
57 (cleanup []))))
59 (defn buffer->image! [width height]
60 (let [image (BufferedImage. width height
61 BufferedImage/TYPE_4BYTE_ABGR)]
62 (fn [byte-buffer]
63 (Screenshots/convertScreenShot byte-buffer image)
64 image)))
66 (defn add-eye
67 "Add an eye to the world, calling continuation on every frame
68 produced."
69 [world camera continuation]
70 (let [width (.getWidth camera)
71 height (.getHeight camera)
72 render-manager (.getRenderManager world)
73 viewport (.createMainView render-manager "eye-view" camera)]
74 (doto viewport
75 (.setClearFlags true true true)
76 (.setBackgroundColor ColorRGBA/Black)
77 (.addProcessor (scene-processor continuation))
78 (.attachScene (.getRootNode world)))))
79 #+end_src
81 #+results: eyes
82 : #'cortex.vision/add-eye
84 Note the use of continuation passing style for connecting the eye to a
85 function to process the output. You can create any number of eyes, and
86 each of them will see the world from their own =Camera=. Once every
87 frame, the rendered image is copied to a =BufferedImage=, and that
88 data is sent off to the continuation function. Moving the =Camera=
89 which was used to create the eye will change what the eye sees.
91 * Example
93 #+name: test-vision
94 #+begin_src clojure
95 (ns cortex.test.vision
96 (:use (cortex world util vision))
97 (:import java.awt.image.BufferedImage)
98 (:import javax.swing.JPanel)
99 (:import javax.swing.SwingUtilities)
100 (:import java.awt.Dimension)
101 (:import javax.swing.JFrame)
102 (:import com.jme3.math.ColorRGBA)
103 (:import com.jme3.scene.Node)
104 (:import com.jme3.math.Vector3f)
105 (:import (com.jme3.util Screenshots)))
107 (defn view-image
108 "Initailizes a JPanel on which you may draw a BufferedImage.
109 Returns a function that accepts a BufferedImage and draws it to the
110 JPanel."
111 []
112 (let [image
113 (atom
114 (BufferedImage. 1 1 BufferedImage/TYPE_4BYTE_ABGR))
115 panel
116 (proxy [JPanel] []
117 (paint
118 [graphics]
119 (proxy-super paintComponent graphics)
120 (.drawImage graphics @image 0 0 nil)))
121 frame (JFrame. "Display Image")]
122 (SwingUtilities/invokeLater
123 (fn []
124 (doto frame
125 (-> (.getContentPane) (.add panel))
126 (.pack)
127 (.setLocationRelativeTo nil)
128 (.setResizable true)
129 (.setVisible true))))
130 (fn [#^BufferedImage i]
131 (reset! image i)
132 (.setSize frame (+ 8 (.getWidth i)) (+ 28 (.getHeight i)))
133 (.repaint panel 0 0 (.getWidth i) (.getHeight i)))))
135 (defn test-two-eyes
136 "Testing vision:
137 Tests the vision system by creating two views of the same rotating
138 object from different angles and displaying both of those views in
139 JFrames.
141 You should see a rotating cube, and two windows,
142 each displaying a different view of the cube."
143 []
144 (let [candy
145 (box 1 1 1 :physical? false :color ColorRGBA/Blue)]
146 (world
147 (doto (Node.)
148 (.attachChild candy))
149 {}
150 (fn [world]
151 (let [cam (.clone (.getCamera world))
152 width (.getWidth cam)
153 height (.getHeight cam)]
154 (add-eye world cam
155 no-op
156 ;;(comp (view-image) (buffer->image! width height))
157 )
158 (add-eye world
159 (doto (.clone cam)
160 (.setLocation (Vector3f. -10 0 0))
161 (.lookAt Vector3f/ZERO Vector3f/UNIT_Y))
162 no-op
163 ;;(comp (view-image) (buffer->image! width height))
164 )
167 ;; This is here to restore the main view
168 ;; after the other views have completed processing
169 (add-eye world (.getCamera world) no-op)))
170 (fn [world tpf]
171 (.rotate candy (* tpf 0.2) 0 0)))))
172 #+end_src
174 #+results: test-vision
175 : #'cortex.test.vision/test-two-eyes
177 The example code will create two videos of the same rotating object
178 from different angles. It can be used both for stereoscopic vision
179 simulation or for simulating multiple creatures, each with their own
180 sense of vision.
182 - As a neat bonus, this idea behind simulated vision also enables one
183 to [[../../cortex/html/capture-video.html][capture live video feeds from jMonkeyEngine]].
186 * COMMENT code generation
187 #+begin_src clojure :tangle ../src/cortex/vision.clj
188 <<eyes>>
189 #+end_src
191 #+begin_src clojure :tangle ../src/cortex/test/vision.clj
192 <<test-vision>>
193 #+end_src