rlm@1: (ns clojureDemo.VideoTransforms) rlm@1: rlm@1: (import '(java.awt Rectangle Robot Toolkit) ) rlm@1: (import '(java.awt.image BufferedImage) ) rlm@1: (import '(java.awt Graphics2D Panel)) rlm@1: (import '(java.io File) ) rlm@1: (import '(javax.imageio ImageIO) ) rlm@1: (import '(javax.swing JFrame)) rlm@1: (import '(org.apache.commons.io FileUtils)) rlm@1: (import clojure.lang.LazySeq) rlm@1: (import '(name.audet.samuel.javacv.jna highgui cv cxcore)) rlm@1: (import '(name.audet.samuel.javacv CanvasFrame)) rlm@1: (import '(name.audet.samuel.javacv.jna cxcore$IplImage)) rlm@1: (import '(name.audet.samuel.javacv.jna highgui$CvCapture$PointerByReference)) rlm@1: (import '(name.audet.samuel.javacv.jna highgui$CvVideoWriter$PointerByReference)) rlm@1: (import '(name.audet.samuel.javacv.jna cxcore$IplImage$PointerByReference)) rlm@1: (import '(name.audet.samuel.javacv.jna cxcore$IplImage)) rlm@1: (import '(name.audet.samuel.javacv JavaCvErrorCallback)) rlm@1: rlm@1: (.redirectError (JavaCvErrorCallback.));this enables the c errors to travel up to the JVM rlm@1: ;where they can be handled. rlm@1: rlm@1: rlm@1: (use '[clojureDemo.VisionCore :only (video-seq cache video-data close-writer)]) rlm@1: rlm@1: rlm@1: (use 'clojure.contrib.repl-utils) rlm@1: rlm@1: (def -inf Double/NEGATIVE_INFINITY) rlm@1: (def inf Double/POSITIVE_INFINITY) rlm@1: rlm@1: rlm@1: (def lian (File. "/home/r/Desktop/source-videos/lian1.mpeg")) rlm@1: (def look (File. "/home/r/Desktop/source-videos/dramatic_look.flv")) rlm@1: (def getto(File. "/home/r/Desktop/source-videos/Ghetto.flv")) rlm@1: (def human0(File. "/home/r/Desktop/source-videos/vsr1/human0.avi")) rlm@1: rlm@1: (def base (File. "/home/r/Desktop/source-videos/")) rlm@1: rlm@1: (def app0 (File. base "approach0v2.avi")) rlm@1: (def app1 (File. base "approach1v3.avi")) rlm@1: (def app2 (File. base "approach0v3.avi")) rlm@1: (def app3 (File. base "approach2v2.avi")) rlm@1: (def app4 (File. base "approach1v2.avi")) rlm@1: (def app5 (File. base "approach2v3.avi")) rlm@1: rlm@1: (def bounce0 (File. base "bounce0v2.avi")) rlm@1: (def bounce1 (File. base "bounce1v3.avi")) rlm@1: (def bounce2 (File. base "bounce3v2.avi")) rlm@1: (def bounce3 (File. base "bounce0v3.avi")) rlm@1: (def bounce4 (File. base "bounce2v2.avi")) rlm@1: (def bounce5 (File. base "bounce1v2.avi")) rlm@1: (def bounce6 (File. base "bounce2v3.avi")) rlm@1: rlm@1: (def collide0 (File. base "collide0v3.avi")) rlm@1: (def collide1 (File. base "collide2v3.avi")) rlm@1: (def collide2 (File. base "collide1v2.avi")) rlm@1: (def collide3 (File. base "collide0v2.avi")) rlm@1: (def collide4 (File. base "collide1v3.avi")) rlm@1: rlm@1: (def give0 (File. base "give0v3.avi")) rlm@1: (def give1 (File. base "give2v3.avi")) rlm@1: (def give2 (File. base "give1v2.avi")) rlm@1: (def give3 (File. base "give0v2.avi")) rlm@1: (def give4 (File. base "give1v3.avi")) rlm@1: rlm@1: rlm@1: (def target (File. "/home/r/Desktop/output-vision/")) rlm@1: (def default(File. target "default.avi")) rlm@1: (defn- makePanel [image] (proxy [Panel] [] (paint [g] (.drawImage g image 0 0 nil)))) rlm@1: rlm@1: (defmulti display "Creates a JFrame and displays a buffered image" class) rlm@1: rlm@1: (defmethod display rlm@1: BufferedImage [image] rlm@1: (let [panel (makePanel image) rlm@1: frame (JFrame. "Oh Yeah!")] rlm@1: (.add frame panel) rlm@1: (.pack frame) rlm@1: (.setVisible frame true ) rlm@1: (.setSize frame(.getWidth image) (.getHeight image)))) rlm@1: rlm@1: (defmethod display rlm@1: cxcore$IplImage [image] rlm@1: ( display (.getBufferedImage image))) rlm@1: rlm@1: (defmethod display rlm@1: String [image] rlm@1: (display (highgui/cvLoadImage image highgui/CV_LOAD_IMAGE_COLOR))) rlm@1: rlm@1: (defmethod display rlm@1: LazySeq [s] rlm@1: (display (first s))) rlm@1: rlm@1: rlm@1: (defn video-writer rlm@1: "uses data about the video to make a writer" rlm@1: [data fileTarget] rlm@1: (highgui/cvCreateVideoWriter rlm@1: (str fileTarget) rlm@1: rlm@1: ;(highgui/CV_FOURCC \P,\I,\M,\1) ;= MPEG-1 codec (112913.386195 msecs) (104 MB) rlm@1: ;(highgui/CV_FOURCC \M,\J,\P,\G) ;= motion-jpeg codec (crashed) rlm@1: ;(highgui/CV_FOURCC \M,\P,\4,\2) ;= MPEG-4.2 codec (107184.186774 msecs) (82 MB) rlm@1: ;(highgui/CV_FOURCC \D,\I,\V,\3) ;= MPEG-4.3 codec (118308.933328 msecs) (83 MB) rlm@1: ;;(highgui/CV_FOURCC \D,\I,\V,\X) ;= MPEG-4 codec (99037.738131 msecs) (85 MB) rlm@1: (highgui/CV_FOURCC \H,\D,\Y,\C) rlm@1: ;(highgui/CV_FOURCC \U,\2,\6,\3) ;= H263 codec (101141.993551 msecs) (89 MB) rlm@1: ;(highgui/CV_FOURCC \I,\2,\6,\3) ;= H263I codec (crashed) rlm@1: ;(highgui/CV_FOURCC \F,\L,\V,\1) ;= FLV1 codec (104307.567802 msecs) (93 MB) rlm@1: ;(:codec data) ;= whatever the movie originally had. (98278.694169 msecs) (1.9 GB) rlm@1: rlm@1: (:fps data) (cxcore/cvSize (:width data) (:height data)) rlm@1: 1; 1 here means that we're writing in color. rlm@1: ; you cannot change it to 0 to write in rlm@1: ; black and white. Everything just crashes instead. rlm@1: ; what a useful paramater. rlm@1: )) rlm@1: rlm@1: rlm@1: (defn naturals [] (iterate inc 0)) rlm@1: rlm@1: rlm@1: (defn write-frame rlm@1: [writer frame] rlm@1: (do rlm@1: (highgui/cvWriteFrame writer frame) rlm@1: frame)) rlm@1: rlm@1: (defn number-seq rlm@1: [video-seq] rlm@1: (map #(vector %1 %2) (naturals) video-seq)) rlm@1: rlm@1: (defn save-seq rlm@1: [writer video-seq] rlm@1: (map #(write-frame writer %) video-seq)) rlm@1: rlm@1: (defn create-runonce [function] rlm@1: (let [sentinel (Object.) rlm@1: result (atom sentinel)] rlm@1: (fn [& args] rlm@1: (locking sentinel rlm@1: (if (= @result sentinel) rlm@1: (reset! result (function)) rlm@1: @result))))) rlm@1: rlm@1: (defmacro oncer rlm@1: [video-seq-gen] rlm@1: `((create-runonce #(~@video-seq-gen)))) rlm@1: rlm@1: (defmacro trans-save rlm@1: "there's a small problem with trans-save --- it IS rlm@1: truly transitive, but it does too much work.... rlm@1: sometimes it writes files twice. rlm@1: this is functionally correct though." rlm@1: [target config video-seq] rlm@1: `(let [writer# (video-writer ~config ~target)] rlm@1: (do rlm@1: (dorun (save-seq writer# ~video-seq)) rlm@1: (close-writer writer#) rlm@1: ~video-seq))) rlm@1: rlm@1: (defn save-video rlm@1: [video target] rlm@1: (let [writer (video-writer (video-data video) target)] rlm@1: (do rlm@1: (dorun (map #(write-frame writer %) (video-seq video))) rlm@1: (close-writer writer)))) rlm@1: rlm@1: rlm@1: (comment (Examples of things you can try that will actually work) rlm@1: rlm@1: (def lazy-human (video-seq human0)) ;makes a lazy sequence of frames and returns instantly. rlm@1: (def target1 (File. "some/path/out1.avi")) ;just creates a normal Java File object. rlm@1: (def target2 (File. "some/other/path/out2.avi")) rlm@1: (def human0-data (video-data human0)) ;creates a map containing the fps, width, and height of the video. rlm@1: rlm@1: (trans-save target human0-data (video-seq human0)) rlm@1: ;saves a copy of human0 to disk. rlm@1: rlm@1: (trans-save target2 human0-data (video-seq-filter (trans-save target1 human0-data (video-seq human0)))) rlm@1: ;saves an unaltered copy of human0 to disk, filters the sequence of rlm@1: ;Intel Processing Library images by video-seq-filter, and writes the rlm@1: ;filtered result to disk. video-seq-filter could discard every other frame, rlm@1: ;take the sequence by fives and do temporal blurring, or just turn every rlm@1: ;frame to black and white. rlm@1: rlm@1: rlm@1: (do (use :reload-all 'clojureDemo.VideoTransforms) (in-ns 'clojureDemo.VideoTransforms)) rlm@1: rlm@1: ) rlm@1: rlm@1: rlm@1: