diff src/clojureDemo/Xuggle.clj @ 1:6d9bdaf919f7

added clojureDemo source
author Robert McIntyre <rlm@mit.edu>
date Fri, 20 Aug 2010 00:32:44 -0400
parents
children
line wrap: on
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/clojureDemo/Xuggle.clj	Fri Aug 20 00:32:44 2010 -0400
     1.3 @@ -0,0 +1,221 @@
     1.4 +(ns clojureDemo.Xuggle)
     1.5 +
     1.6 +(import '(ij ImagePlus IJ))
     1.7 +(import '(java.awt Rectangle Robot Toolkit) )
     1.8 +(import '(java.awt.image BufferedImage) )
     1.9 +(import '(java.awt Graphics2D Panel))
    1.10 +(import '(java.io File) )
    1.11 +(import '(javax.imageio ImageIO) )
    1.12 +(import '(com.xuggle.mediatool ToolFactory))
    1.13 +(import '(com.xuggle.mediatool IMediaDebugListener IMediaDebugListener$Event))
    1.14 +(import '(com.xuggle.mediatool MediaToolAdapter MediaListenerAdapter))
    1.15 +(import '(com.xuggle.xuggler IContainer IContainer$Type IPacket))
    1.16 +(import '(javax.swing JFrame))
    1.17 +(import '(com.xuggle.mediatool IMediaWriter))
    1.18 +(import '(org.apache.commons.io FileUtils))
    1.19 +(import '(javax.imageio.stream FileImageOutputStream))
    1.20 +(import '(javax.imageio ImageWriteParam IIOImage))
    1.21 +(import '(com.xuggle.xuggler IRational))
    1.22 +(import '(java.util.concurrent TimeUnit))
    1.23 +(import '(com.xuggle.xuggler ICodec))
    1.24 +
    1.25 +(use  'clojureDemo.Defines)
    1.26 +;(use '[clojureDemo.OpenCv :only (video-data)])
    1.27 +
    1.28 +
    1.29 +
    1.30 +(import '(java.io File))
    1.31 +(import '(org.apache.commons.io FileUtils))
    1.32 +(import '(javax.imageio ImageIO) )
    1.33 +
    1.34 +(import '(ij.plugin PlugIn))
    1.35 +(import '(ij ImagePlus IJ))
    1.36 +
    1.37 +
    1.38 +(use 'clojure.contrib.repl-utils)
    1.39 +(use ['clojureDemo.Defines 
    1.40 +      :only '(
    1.41 +	     lian look getto human0 blow base app0 app1 app2 app3 app4 app5 
    1.42 +		  bounce0 bounce1 bounce2 bounce3 bounce4 bounce5 bounce6
    1.43 +		  collide0 collide1 collide2 collide3 collide4  
    1.44 +		  give0 give1 give2 give3 give4 target default)])
    1.45 +
    1.46 +
    1.47 +;(def hamster (ImagePlus. "lklk" (first (video-seq look))))
    1.48 +
    1.49 +
    1.50 +
    1.51 +
    1.52 +
    1.53 +(defn- makePanel [image] (proxy [Panel] [] (paint [g]  (.drawImage g image 0 0 nil))))
    1.54 +
    1.55 +
    1.56 +(defmulti  display "Creates a JFrame and displays a buffered image"  class)
    1.57 +
    1.58 +(defmethod display 
    1.59 +  BufferedImage  [image] 
    1.60 +  (let [panel (makePanel image)
    1.61 +	frame (JFrame. "Oh Yeah!")]
    1.62 +    (.add frame panel) 
    1.63 +    (.pack frame) 
    1.64 +    (.setVisible frame true ) 
    1.65 +    (.setSize frame(.getWidth image) (.getHeight image))))
    1.66 + 
    1.67 +(defmethod display
    1.68 +  ImagePlus [image]
    1.69 +  (display (.getBufferedImage image)))
    1.70 +
    1.71 +
    1.72 +
    1.73 +
    1.74 +(defn flash
    1.75 +     [image]
    1.76 +     
    1.77 +     (.start (Thread. (fn [] 
    1.78 +			(do 
    1.79 +			  (.show image)
    1.80 +			  (.updateAndRepaintWindow image)
    1.81 +			  (Thread/sleep 4000)
    1.82 +			  (.hide image))))))
    1.83 +
    1.84 +
    1.85 +(defn readerRecurse
    1.86 +  "calls .readPacket until there's nothing left to do"
    1.87 +  [reader]
    1.88 +  (if (not (nil? (.readPacket reader))) ; here .readPacket actually does the processing as a side-effect.
    1.89 +    nil                                   ; it returns null when it has MORE to process, and signals an error when done... 
    1.90 +    (recur reader)))
    1.91 +
    1.92 +
    1.93 +(def *cache-directory* (File. "/home/r/Desktop/vision-cache"))
    1.94 +(def *ext* "jpg")
    1.95 +
    1.96 +
    1.97 +
    1.98 +
    1.99 +(defn writeJpg
   1.100 +  "WTF is this shit?!"
   1.101 +  [image target quality]
   1.102 +  (let [jpgWriter (.next (ImageIO/getImageWritersByFormatName *ext*))]
   1.103 +    (doto (.getDefaultWriteParam jpgWriter) 
   1.104 +      (.setCompressionMode ImageWriteParam/MODE_EXPLICIT)
   1.105 +      (.setCompressionQuality quality))
   1.106 +    (doto jpgWriter
   1.107 +      (.setOutput (FileImageOutputStream. target))
   1.108 +      (.write (IIOImage. image nil nil))
   1.109 +      (.dispose))))
   1.110 +    
   1.111 +
   1.112 +
   1.113 +(defn cache-path
   1.114 +  [video]
   1.115 +  (File. *cache-directory* (.getName video)))
   1.116 +
   1.117 +(defn video-frame-path
   1.118 +     [video n]
   1.119 +     (File. (cache-path video)  (str n "."  *ext*)))
   1.120 +
   1.121 +
   1.122 +(defn already-cached
   1.123 +  "this is the simplest and most retarded way to do it"
   1.124 +  [video]
   1.125 +  (.exists (cache-path video)))
   1.126 +
   1.127 +
   1.128 + 
   1.129 + 
   1.130 +
   1.131 +
   1.132 +(defn make-incrementer [start increment] (let [a (ref (- start increment))] (fn [] (dosync (ref-set a (+ @a increment))))))
   1.133 +
   1.134 +(defn make-frame-writer
   1.135 +  [video]
   1.136 +  (let [incrementer (make-incrementer 0 1)]
   1.137 +  (proxy [MediaListenerAdapter] [] 
   1.138 +    
   1.139 +    (onVideoPicture
   1.140 +     [event]
   1.141 +     ;(println (.getImage event))
   1.142 +     ;(println (File. (cache-path video) (str (incrementer) "." *ext* ) ))
   1.143 +     
   1.144 +     (let [target  (File. (cache-path video) (str (incrementer) "." *ext* ))]
   1.145 +       (if (= *ext* "jpg")
   1.146 +	 (writeJpg (.getImage event)  target  1)
   1.147 +	 (ImageIO/write (.getImage event) *ext* target )))))))
   1.148 +    
   1.149 +
   1.150 +
   1.151 +(defn cache 
   1.152 +  "caching of frames without opencv"
   1.153 +  [video]
   1.154 +  
   1.155 +  (if (already-cached video)
   1.156 +    nil 
   1.157 +    (time
   1.158 +    (let [reader (ToolFactory/makeReader (str video))]
   1.159 +      (println "slow cache!")
   1.160 +      (FileUtils/forceMkdir (cache-path video))
   1.161 +      (doto reader
   1.162 +	(.setBufferedImageTypeToGenerate BufferedImage/TYPE_3BYTE_BGR)
   1.163 +	(.addListener  (make-frame-writer video))
   1.164 +	(.addListener (ToolFactory/makeDebugListener (into-array [IMediaDebugListener$Event/META_DATA]))))
   1.165 +      (readerRecurse reader)))))
   1.166 +
   1.167 +
   1.168 +(defn video-data 
   1.169 +  "get video data without opencv"
   1.170 +  [video] (cache video)
   1.171 +
   1.172 +  
   1.173 +  {:length (- (count (file-seq (cache-path video))) 1)
   1.174 +   :width  (.getWidth (ImagePlus. (str (video-frame-path video 0))))
   1.175 +   :height (.getHeight (ImagePlus. (str (video-frame-path video 0))))
   1.176 +   :fps 30}) ; yeah --- I'll figure this out later.
   1.177 + (def video-data (memoize video-data))
   1.178 +
   1.179 +
   1.180 +
   1.181 +(defn convert
   1.182 +  "takes video and converts it to a new type of video"
   1.183 +  [videoInput videoOutput]
   1.184 +  (let [reader (ToolFactory/makeReader (str videoInput))]
   1.185 +    (doto reader
   1.186 +      (.addListener (ToolFactory/makeWriter (str videoOutput) reader))
   1.187 +      (.addListener (ToolFactory/makeDebugListener (into-array [IMediaDebugListener$Event/META_DATA]))))
   1.188 +    (readerRecurse reader)))
   1.189 +
   1.190 +
   1.191 +(import '(com.xuggle.xuggler.video ConverterFactory))
   1.192 +
   1.193 +
   1.194 +(defn trans-save
   1.195 +  "this is a transitive way to save a stream to an avi file.
   1.196 +   It uses meta data to determine what fps to use to encode."
   1.197 +  [destination video-seq]
   1.198 +  (let [data (meta video-seq)
   1.199 +	writer (ToolFactory/makeWriter (str destination))
   1.200 +	incrementer (make-incrementer 0 (/ 1 30))]
   1.201 +    (.addVideoStream writer 0 0 (ICodec/findEncodingCodecByName "mpeg4") 
   1.202 +		     (IRational/make (double (:fps data))) 
   1.203 +		     (int (:width data)) (int (:height data)))
   1.204 +    (dorun (map  #(.encodeVideo writer 0 
   1.205 +			 (ConverterFactory/convertToType (.getBufferedImage %) BufferedImage/TYPE_3BYTE_BGR) 
   1.206 +			(long (* 1000000000 (incrementer)))  TimeUnit/NANOSECONDS)  video-seq))
   1.207 +	(.close writer))
   1.208 +  video-seq)
   1.209 +
   1.210 +
   1.211 +(defn video-seq 
   1.212 +  "let's use ImagePlus stuff!"
   1.213 +  ([video] (cache video) 
   1.214 +    (with-meta (map #(ImagePlus. (str (video-frame-path video %))) (range (:length (video-data video))) ) (video-data video))))
   1.215 +
   1.216 +
   1.217 +
   1.218 +
   1.219 +
   1.220 +
   1.221 +(comment 
   1.222 +  (do (use :reload-all 'clojureDemo.Xuggle) (in-ns 'clojureDemo.Xuggle))
   1.223 +)
   1.224 +