Mercurial > cortex
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 Sight2 #+author: Robert McIntyre3 #+email: rlm@mit.edu4 #+description: Simulated sight for AI research using JMonkeyEngine3 and clojure5 #+keywords: computer vision, jMonkeyEngine3, clojure6 #+SETUPFILE: ../../aurellem/org/setup.org7 #+INCLUDE: ../../aurellem/org/level-0.org8 #+babel: :mkdirp yes :noweb yes :exports both10 * Vision12 I want to make creatures with eyes. Each eye can be independely moved13 and should see its own version of the world depending on where it is.14 #+name: eyes15 #+begin_src clojure16 (ns cortex.vision17 "Simulate the sense of vision in jMonkeyEngine3. Enables multiple18 eyes from different positions to observe the same world, and pass19 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-processor30 "Create a SceneProcessor object which wraps a vision processing31 continuation function. The SceneProcessor will take care of32 converting the rendered frame to a BufferedImage and passing that33 BufferedImage to the continuation. The continuation should be a34 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 (initialize40 [renderManager viewPort]41 (let [cam (.getCamera viewPort)42 width (.getWidth cam)43 height (.getHeight cam)]44 (reset! renderer (.getRenderer renderManager))45 (reset! byte-buffer46 (BufferUtils/createByteBuffer47 (* width height 4)))))48 (isInitialized [] (not (nil? @byte-buffer)))49 (reshape [_ _ _])50 (preFrame [_])51 (postQueue [_])52 (postFrame53 [#^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 height61 BufferedImage/TYPE_4BYTE_ABGR)]62 (fn [byte-buffer]63 (Screenshots/convertScreenShot byte-buffer image)64 image)))66 (defn add-eye67 "Add an eye to the world, calling continuation on every frame68 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 viewport75 (.setClearFlags true true true)76 (.setBackgroundColor ColorRGBA/Black)77 (.addProcessor (scene-processor continuation))78 (.attachScene (.getRootNode world)))))79 #+end_src81 #+results: eyes82 : #'cortex.vision/add-eye84 Note the use of continuation passing style for connecting the eye to a85 function to process the output. You can create any number of eyes, and86 each of them will see the world from their own =Camera=. Once every87 frame, the rendered image is copied to a =BufferedImage=, and that88 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 * Example93 #+name: test-vision94 #+begin_src clojure95 (ns cortex.test.vision96 (: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-image108 "Initailizes a JPanel on which you may draw a BufferedImage.109 Returns a function that accepts a BufferedImage and draws it to the110 JPanel."111 []112 (let [image113 (atom114 (BufferedImage. 1 1 BufferedImage/TYPE_4BYTE_ABGR))115 panel116 (proxy [JPanel] []117 (paint118 [graphics]119 (proxy-super paintComponent graphics)120 (.drawImage graphics @image 0 0 nil)))121 frame (JFrame. "Display Image")]122 (SwingUtilities/invokeLater123 (fn []124 (doto frame125 (-> (.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-eyes136 "Testing vision:137 Tests the vision system by creating two views of the same rotating138 object from different angles and displaying both of those views in139 JFrames.141 You should see a rotating cube, and two windows,142 each displaying a different view of the cube."143 []144 (let [candy145 (box 1 1 1 :physical? false :color ColorRGBA/Blue)]146 (world147 (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 cam155 no-op156 ;;(comp (view-image) (buffer->image! width height))157 )158 (add-eye world159 (doto (.clone cam)160 (.setLocation (Vector3f. -10 0 0))161 (.lookAt Vector3f/ZERO Vector3f/UNIT_Y))162 no-op163 ;;(comp (view-image) (buffer->image! width height))164 )167 ;; This is here to restore the main view168 ;; after the other views have completed processing169 (add-eye world (.getCamera world) no-op)))170 (fn [world tpf]171 (.rotate candy (* tpf 0.2) 0 0)))))172 #+end_src174 #+results: test-vision175 : #'cortex.test.vision/test-two-eyes177 The example code will create two videos of the same rotating object178 from different angles. It can be used both for stereoscopic vision179 simulation or for simulating multiple creatures, each with their own180 sense of vision.182 - As a neat bonus, this idea behind simulated vision also enables one183 to [[../../cortex/html/capture-video.html][capture live video feeds from jMonkeyEngine]].186 * COMMENT code generation187 #+begin_src clojure :tangle ../src/cortex/vision.clj188 <<eyes>>189 #+end_src191 #+begin_src clojure :tangle ../src/cortex/test/vision.clj192 <<test-vision>>193 #+end_src