annotate src/clojureDemo/Xuggle.clj @ 19:3b255dcd6c50

getting closer
author Robert McIntyre <rlm@mit.edu>
date Mon, 30 Aug 2010 00:09:06 -0400
parents 6d9bdaf919f7
children
rev   line source
rlm@1 1 (ns clojureDemo.Xuggle)
rlm@1 2
rlm@1 3 (import '(ij ImagePlus IJ))
rlm@1 4 (import '(java.awt Rectangle Robot Toolkit) )
rlm@1 5 (import '(java.awt.image BufferedImage) )
rlm@1 6 (import '(java.awt Graphics2D Panel))
rlm@1 7 (import '(java.io File) )
rlm@1 8 (import '(javax.imageio ImageIO) )
rlm@1 9 (import '(com.xuggle.mediatool ToolFactory))
rlm@1 10 (import '(com.xuggle.mediatool IMediaDebugListener IMediaDebugListener$Event))
rlm@1 11 (import '(com.xuggle.mediatool MediaToolAdapter MediaListenerAdapter))
rlm@1 12 (import '(com.xuggle.xuggler IContainer IContainer$Type IPacket))
rlm@1 13 (import '(javax.swing JFrame))
rlm@1 14 (import '(com.xuggle.mediatool IMediaWriter))
rlm@1 15 (import '(org.apache.commons.io FileUtils))
rlm@1 16 (import '(javax.imageio.stream FileImageOutputStream))
rlm@1 17 (import '(javax.imageio ImageWriteParam IIOImage))
rlm@1 18 (import '(com.xuggle.xuggler IRational))
rlm@1 19 (import '(java.util.concurrent TimeUnit))
rlm@1 20 (import '(com.xuggle.xuggler ICodec))
rlm@1 21
rlm@1 22 (use 'clojureDemo.Defines)
rlm@1 23 ;(use '[clojureDemo.OpenCv :only (video-data)])
rlm@1 24
rlm@1 25
rlm@1 26
rlm@1 27 (import '(java.io File))
rlm@1 28 (import '(org.apache.commons.io FileUtils))
rlm@1 29 (import '(javax.imageio ImageIO) )
rlm@1 30
rlm@1 31 (import '(ij.plugin PlugIn))
rlm@1 32 (import '(ij ImagePlus IJ))
rlm@1 33
rlm@1 34
rlm@1 35 (use 'clojure.contrib.repl-utils)
rlm@1 36 (use ['clojureDemo.Defines
rlm@1 37 :only '(
rlm@1 38 lian look getto human0 blow base app0 app1 app2 app3 app4 app5
rlm@1 39 bounce0 bounce1 bounce2 bounce3 bounce4 bounce5 bounce6
rlm@1 40 collide0 collide1 collide2 collide3 collide4
rlm@1 41 give0 give1 give2 give3 give4 target default)])
rlm@1 42
rlm@1 43
rlm@1 44 ;(def hamster (ImagePlus. "lklk" (first (video-seq look))))
rlm@1 45
rlm@1 46
rlm@1 47
rlm@1 48
rlm@1 49
rlm@1 50 (defn- makePanel [image] (proxy [Panel] [] (paint [g] (.drawImage g image 0 0 nil))))
rlm@1 51
rlm@1 52
rlm@1 53 (defmulti display "Creates a JFrame and displays a buffered image" class)
rlm@1 54
rlm@1 55 (defmethod display
rlm@1 56 BufferedImage [image]
rlm@1 57 (let [panel (makePanel image)
rlm@1 58 frame (JFrame. "Oh Yeah!")]
rlm@1 59 (.add frame panel)
rlm@1 60 (.pack frame)
rlm@1 61 (.setVisible frame true )
rlm@1 62 (.setSize frame(.getWidth image) (.getHeight image))))
rlm@1 63
rlm@1 64 (defmethod display
rlm@1 65 ImagePlus [image]
rlm@1 66 (display (.getBufferedImage image)))
rlm@1 67
rlm@1 68
rlm@1 69
rlm@1 70
rlm@1 71 (defn flash
rlm@1 72 [image]
rlm@1 73
rlm@1 74 (.start (Thread. (fn []
rlm@1 75 (do
rlm@1 76 (.show image)
rlm@1 77 (.updateAndRepaintWindow image)
rlm@1 78 (Thread/sleep 4000)
rlm@1 79 (.hide image))))))
rlm@1 80
rlm@1 81
rlm@1 82 (defn readerRecurse
rlm@1 83 "calls .readPacket until there's nothing left to do"
rlm@1 84 [reader]
rlm@1 85 (if (not (nil? (.readPacket reader))) ; here .readPacket actually does the processing as a side-effect.
rlm@1 86 nil ; it returns null when it has MORE to process, and signals an error when done...
rlm@1 87 (recur reader)))
rlm@1 88
rlm@1 89
rlm@1 90 (def *cache-directory* (File. "/home/r/Desktop/vision-cache"))
rlm@1 91 (def *ext* "jpg")
rlm@1 92
rlm@1 93
rlm@1 94
rlm@1 95
rlm@1 96 (defn writeJpg
rlm@1 97 "WTF is this shit?!"
rlm@1 98 [image target quality]
rlm@1 99 (let [jpgWriter (.next (ImageIO/getImageWritersByFormatName *ext*))]
rlm@1 100 (doto (.getDefaultWriteParam jpgWriter)
rlm@1 101 (.setCompressionMode ImageWriteParam/MODE_EXPLICIT)
rlm@1 102 (.setCompressionQuality quality))
rlm@1 103 (doto jpgWriter
rlm@1 104 (.setOutput (FileImageOutputStream. target))
rlm@1 105 (.write (IIOImage. image nil nil))
rlm@1 106 (.dispose))))
rlm@1 107
rlm@1 108
rlm@1 109
rlm@1 110 (defn cache-path
rlm@1 111 [video]
rlm@1 112 (File. *cache-directory* (.getName video)))
rlm@1 113
rlm@1 114 (defn video-frame-path
rlm@1 115 [video n]
rlm@1 116 (File. (cache-path video) (str n "." *ext*)))
rlm@1 117
rlm@1 118
rlm@1 119 (defn already-cached
rlm@1 120 "this is the simplest and most retarded way to do it"
rlm@1 121 [video]
rlm@1 122 (.exists (cache-path video)))
rlm@1 123
rlm@1 124
rlm@1 125
rlm@1 126
rlm@1 127
rlm@1 128
rlm@1 129 (defn make-incrementer [start increment] (let [a (ref (- start increment))] (fn [] (dosync (ref-set a (+ @a increment))))))
rlm@1 130
rlm@1 131 (defn make-frame-writer
rlm@1 132 [video]
rlm@1 133 (let [incrementer (make-incrementer 0 1)]
rlm@1 134 (proxy [MediaListenerAdapter] []
rlm@1 135
rlm@1 136 (onVideoPicture
rlm@1 137 [event]
rlm@1 138 ;(println (.getImage event))
rlm@1 139 ;(println (File. (cache-path video) (str (incrementer) "." *ext* ) ))
rlm@1 140
rlm@1 141 (let [target (File. (cache-path video) (str (incrementer) "." *ext* ))]
rlm@1 142 (if (= *ext* "jpg")
rlm@1 143 (writeJpg (.getImage event) target 1)
rlm@1 144 (ImageIO/write (.getImage event) *ext* target )))))))
rlm@1 145
rlm@1 146
rlm@1 147
rlm@1 148 (defn cache
rlm@1 149 "caching of frames without opencv"
rlm@1 150 [video]
rlm@1 151
rlm@1 152 (if (already-cached video)
rlm@1 153 nil
rlm@1 154 (time
rlm@1 155 (let [reader (ToolFactory/makeReader (str video))]
rlm@1 156 (println "slow cache!")
rlm@1 157 (FileUtils/forceMkdir (cache-path video))
rlm@1 158 (doto reader
rlm@1 159 (.setBufferedImageTypeToGenerate BufferedImage/TYPE_3BYTE_BGR)
rlm@1 160 (.addListener (make-frame-writer video))
rlm@1 161 (.addListener (ToolFactory/makeDebugListener (into-array [IMediaDebugListener$Event/META_DATA]))))
rlm@1 162 (readerRecurse reader)))))
rlm@1 163
rlm@1 164
rlm@1 165 (defn video-data
rlm@1 166 "get video data without opencv"
rlm@1 167 [video] (cache video)
rlm@1 168
rlm@1 169
rlm@1 170 {:length (- (count (file-seq (cache-path video))) 1)
rlm@1 171 :width (.getWidth (ImagePlus. (str (video-frame-path video 0))))
rlm@1 172 :height (.getHeight (ImagePlus. (str (video-frame-path video 0))))
rlm@1 173 :fps 30}) ; yeah --- I'll figure this out later.
rlm@1 174 (def video-data (memoize video-data))
rlm@1 175
rlm@1 176
rlm@1 177
rlm@1 178 (defn convert
rlm@1 179 "takes video and converts it to a new type of video"
rlm@1 180 [videoInput videoOutput]
rlm@1 181 (let [reader (ToolFactory/makeReader (str videoInput))]
rlm@1 182 (doto reader
rlm@1 183 (.addListener (ToolFactory/makeWriter (str videoOutput) reader))
rlm@1 184 (.addListener (ToolFactory/makeDebugListener (into-array [IMediaDebugListener$Event/META_DATA]))))
rlm@1 185 (readerRecurse reader)))
rlm@1 186
rlm@1 187
rlm@1 188 (import '(com.xuggle.xuggler.video ConverterFactory))
rlm@1 189
rlm@1 190
rlm@1 191 (defn trans-save
rlm@1 192 "this is a transitive way to save a stream to an avi file.
rlm@1 193 It uses meta data to determine what fps to use to encode."
rlm@1 194 [destination video-seq]
rlm@1 195 (let [data (meta video-seq)
rlm@1 196 writer (ToolFactory/makeWriter (str destination))
rlm@1 197 incrementer (make-incrementer 0 (/ 1 30))]
rlm@1 198 (.addVideoStream writer 0 0 (ICodec/findEncodingCodecByName "mpeg4")
rlm@1 199 (IRational/make (double (:fps data)))
rlm@1 200 (int (:width data)) (int (:height data)))
rlm@1 201 (dorun (map #(.encodeVideo writer 0
rlm@1 202 (ConverterFactory/convertToType (.getBufferedImage %) BufferedImage/TYPE_3BYTE_BGR)
rlm@1 203 (long (* 1000000000 (incrementer))) TimeUnit/NANOSECONDS) video-seq))
rlm@1 204 (.close writer))
rlm@1 205 video-seq)
rlm@1 206
rlm@1 207
rlm@1 208 (defn video-seq
rlm@1 209 "let's use ImagePlus stuff!"
rlm@1 210 ([video] (cache video)
rlm@1 211 (with-meta (map #(ImagePlus. (str (video-frame-path video %))) (range (:length (video-data video))) ) (video-data video))))
rlm@1 212
rlm@1 213
rlm@1 214
rlm@1 215
rlm@1 216
rlm@1 217
rlm@1 218 (comment
rlm@1 219 (do (use :reload-all 'clojureDemo.Xuggle) (in-ns 'clojureDemo.Xuggle))
rlm@1 220 )
rlm@1 221