diff src/clojureDemo/VideoParse.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/VideoParse.clj	Fri Aug 20 00:32:44 2010 -0400
     1.3 @@ -0,0 +1,230 @@
     1.4 +(ns clojureDemo.VideoParse)
     1.5 +  
     1.6 + 
     1.7 +
     1.8 +;this file is not used anymore, except for the (display %) function.
     1.9 +
    1.10 +
    1.11 +
    1.12 +(import '(java.awt Rectangle Robot Toolkit) )
    1.13 +(import '(java.awt.image BufferedImage) )
    1.14 +(import '(java.awt Graphics2D Panel))
    1.15 +(import '(java.io File) )
    1.16 +(import '(javax.imageio ImageIO) )
    1.17 +(import '(com.xuggle.mediatool ToolFactory))
    1.18 +(import '(com.xuggle.mediatool IMediaDebugListener IMediaDebugListener$Event))
    1.19 +(import '(com.xuggle.mediatool MediaToolAdapter))
    1.20 +(import '(com.xuggle.xuggler IContainer IContainer$Type IPacket))
    1.21 +(import '(javax.swing JFrame))
    1.22 +
    1.23 +(import clojure.lang.LazySeq)
    1.24 +
    1.25 +(import '(name.audet.samuel.javacv.jna highgui cv cxcore))
    1.26 +
    1.27 +(import '(name.audet.samuel.javacv CanvasFrame))
    1.28 +
    1.29 +(import '(name.audet.samuel.javacv.jna cxcore$IplImage))
    1.30 +
    1.31 +(import '(name.audet.samuel.javacv.jna highgui$CvCapture$PointerByReference))
    1.32 +(import '(name.audet.samuel.javacv.jna highgui$CvVideoWriter$PointerByReference))
    1.33 +
    1.34 +;definitions
    1.35 +
    1.36 +(def -inf Double/NEGATIVE_INFINITY)
    1.37 +(def inf  Double/POSITIVE_INFINITY)
    1.38 +
    1.39 +(use 'clojure.contrib.repl-utils)
    1.40 +
    1.41 +
    1.42 +;minor functions
    1.43 +
    1.44 +(defn converge
    1.45 +  "recursively runs update until prior passes accept, then returns"
    1.46 +  [prior update accept]
    1.47 +  (if (accept prior) prior (recur (update prior) update accept)))
    1.48 +
    1.49 +(defn interval-width [interval] (- (last interval) (first interval)))
    1.50 +
    1.51 +(defn midpoint [interval] 
    1.52 +  (let [a (first interval) b (last interval)]
    1.53 +    (if (and (= a -inf) (= b inf)) 0
    1.54 +    (if (= a -inf) (midpoint [(- b 200000) b])
    1.55 +	(if (= b inf) (midpoint [a (+ a 200000)])
    1.56 +	    (int (/ (+ a b) 2)))))))
    1.57 +
    1.58 +(defn cart2
    1.59 +  "calculates the cartesian product in 2 dimensions"
    1.60 +  [point] 
    1.61 +  (let [[x y] point] (for [abscissa (range x) ordinate (range y)] [abscissa ordinate])))
    1.62 +
    1.63 +(defn closeCapture
    1.64 +  [capture]
    1.65 +  (highgui/cvReleaseCapture (highgui$CvCapture$PointerByReference. capture)))
    1.66 +
    1.67 +(defn- makePanel [image] (proxy [Panel] [] (paint [g]  (.drawImage g image 0 0 nil))))
    1.68 +
    1.69 +(defn screenshot "grab screenshot" [] 
    1.70 +  
    1.71 +  (ImageIO/write
    1.72 +   (.createScreenCapture (Robot.) (Rectangle. (.getScreenSize (Toolkit/getDefaultToolkit))))
    1.73 +   "JPG"
    1.74 +   (File. "/home/r/Desktop/screenie.jpg")))
    1.75 +
    1.76 +(defn- readerRecurse
    1.77 +  "calls .readPacket until there's nothing left to do"
    1.78 +  [reader]
    1.79 +  (if (not (nil? (.readPacket reader))) ; here .readPacket actually does the processing as a side-effect.
    1.80 +    nil                                   ; it returns null when it has MORE to process, and signals an error when done... 
    1.81 +    (recur reader)))
    1.82 +
    1.83 +(defmacro times
    1.84 +  "perform multiple timed tests on a form"
    1.85 +  [n form]
    1.86 +  `(dotimes [_# ~n] (time ~form)))
    1.87 +  
    1.88 +(defmacro me-1
    1.89 +  "does macroexpand-1 without having to quote the form"
    1.90 +  [form]
    1.91 +  (list 'macroexpand-1 (list 'quote form)))
    1.92 +
    1.93 +;Major Functions
    1.94 +
    1.95 +(defmulti  display "Creates a JFrame and displays a buffered image"  class)
    1.96 +
    1.97 +(defmethod display 
    1.98 +  BufferedImage  [image] 
    1.99 +  (let [panel (makePanel image)
   1.100 +	frame (JFrame. "Oh Yeah!")]
   1.101 +    (.add frame panel) 
   1.102 +    (.pack frame) 
   1.103 +    (.setVisible frame true ) 
   1.104 +    (.setSize frame(.getWidth image) (.getHeight image))))
   1.105 +
   1.106 +(defmethod display
   1.107 +  cxcore$IplImage [image]
   1.108 +  ( display (.getBufferedImage image)))
   1.109 +  
   1.110 +(defmethod display
   1.111 +  String [image]
   1.112 +  (display (highgui/cvLoadImage image highgui/CV_LOAD_IMAGE_COLOR)))
   1.113 +
   1.114 +(defmethod display
   1.115 +  LazySeq [s]
   1.116 +  (display (first s)))
   1.117 +
   1.118 +
   1.119 +(defn convert
   1.120 +  "takes video and converts it to a new type of video"
   1.121 +  [videoInput videoOutput]
   1.122 +  (let [reader (ToolFactory/makeReader videoInput)]
   1.123 +    (doto reader
   1.124 +      (.addListener (ToolFactory/makeWriter videoOutput reader))
   1.125 +      (.addListener (ToolFactory/makeDebugListener (into-array [IMediaDebugListener$Event/META_DATA]))))
   1.126 +    (readerRecurse reader)))
   1.127 +
   1.128 +
   1.129 +
   1.130 +(defn video-frame
   1.131 +  ":("
   1.132 +  [video frame]
   1.133 +  (lazy-seq
   1.134 +   (try 
   1.135 +    (let [capture (highgui/cvCreateFileCapture video)]
   1.136 +      (highgui/cvSetCaptureProperty capture highgui/CV_CAP_PROP_POS_FRAMES frame)
   1.137 +      (println (str "Wanted frame <" frame "> but went to keyFrame " (highgui/cvGetCaptureProperty capture highgui/CV_CAP_PROP_POS_FRAMES)))
   1.138 +      (let [out (highgui/cvQueryFrame capture)
   1.139 +	    image (.clone  out)]
   1.140 +	(highgui/cvReleaseCapture (highgui$CvCapture$PointerByReference. capture))
   1.141 +	[image]))
   1.142 +    (catch java.lang.NullPointerException _ nil))))
   1.143 +
   1.144 +
   1.145 +  
   1.146 +
   1.147 +(defn save-frame
   1.148 +  "takes an opencv image and saves it to disk"
   1.149 +  [frame filename]
   1.150 +  (highgui/cvSaveImage filename frame))
   1.151 +
   1.152 +
   1.153 +(defn video-len
   1.154 +  "finds out the real length of a video in log time."
   1.155 +  [video]
   1.156 +  (letfn
   1.157 +      [
   1.158 +       (accept [interval] (= 0 (interval-width interval)))
   1.159 +       (update [interval]
   1.160 +	       (let [[a b] interval]
   1.161 +		 (if (> (interval-width interval) 2)
   1.162 +		   (let [
   1.163 +			 middle (midpoint interval)
   1.164 +			 frame (first (video-frame video middle))
   1.165 +			 ]
   1.166 +		     (if (nil? frame) [a middle] [middle b]))
   1.167 +		   [a a])))
   1.168 +       ]
   1.169 +       
   1.170 +   (first (converge [-inf inf] update accept))))
   1.171 +(def video-len (memoize video-len))
   1.172 +
   1.173 +
   1.174 +
   1.175 +(defn getData
   1.176 +  "returns a bunch of stuff about a video"
   1.177 +  [video]
   1.178 +  (let
   1.179 +      [capture (highgui/cvCreateFileCapture video)
   1.180 +       info {:frames      (video-len video)
   1.181 +	     :width       (highgui/cvGetCaptureProperty capture highgui/CV_CAP_PROP_FRAME_WIDTH)
   1.182 +	     :height      (highgui/cvGetCaptureProperty capture highgui/CV_CAP_PROP_FRAME_HEIGHT)
   1.183 +	     :fps         (highgui/cvGetCaptureProperty capture highgui/CV_CAP_PROP_FPS)
   1.184 +	     :codec       (highgui/cvGetCaptureProperty capture highgui/CV_CAP_PROP_FOURCC)}]
   1.185 +      
   1.186 +    (closeCapture capture)
   1.187 +    info))
   1.188 +(def getData (memoize getData))
   1.189 +  
   1.190 +
   1.191 +(defn sajitify-linear
   1.192 +  "oh yeah!"
   1.193 +  [video string]
   1.194 +  (let [ capture (highgui/cvCreateFileCapture video)
   1.195 +	frames (:frames (getData video))]
   1.196 +       (dotimes [n frames]
   1.197 +	 (highgui/cvSaveImage (str string  (format "%06d" n) ".jpg") (highgui/cvQueryFrame capture)))
   1.198 +       (highgui/cvReleaseCapture (highgui$CvCapture$PointerByReference. capture))))
   1.199 +
   1.200 +(defn getFrame
   1.201 +  "gets the frame of a video at the specified time in seconds.
   1.202 +  this works with the simplest interpolation --- just piecewise steps"
   1.203 +  [video time]
   1.204 +  (lazy-seq
   1.205 +  [time  (video-frame video (int (* time (:fps (getData video)))))]))
   1.206 +
   1.207 +(defn video-seq-times
   1.208 +  "it's the new and improved version of videoSeq, now using OpenCv.
   1.209 +  we expect a sequence of times in seconds"
   1.210 +  [times video]
   1.211 +  (map #(getFrame video %) times))
   1.212 +
   1.213 +(defn video-seq
   1.214 +  "get's ALL the frames of a video as a lazy sequence of (IplImages)"
   1.215 +  [video] 
   1.216 +  (take (:frames (getData video))   (map #(video-frame video %) (iterate inc 0))))
   1.217 +
   1.218 +(defn trans-Writer
   1.219 +  "uses data about the video to make a writer"
   1.220 +  [video fileTarget]
   1.221 +  (let [data (getData video)]
   1.222 +  (highgui/cvCreateVideoWriter fileTarget (highgui/CV_FOURCC "F" "L" "V" "1") (:fps data) (cxcore/cvSize (:width data) (:height data)) 1)))
   1.223 +
   1.224 +(def naturals (iterate inc 0))
   1.225 +
   1.226 +(defn sajitify-seq
   1.227 +  [video string]
   1.228 +  (dorun (map #(highgui/cvSaveImage (str string  (format "%06d" %2) ".jpg") (first %1)) (video-seq video) naturals)))
   1.229 +
   1.230 +
   1.231 +
   1.232 +
   1.233 +