Mercurial > lasercutter
view src/clojureDemo/VisionCore.clj @ 15:8ad629298649
major refactoring
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sun, 29 Aug 2010 19:02:26 -0400 |
parents | 6d9bdaf919f7 |
children |
line wrap: on
line source
1 (ns clojureDemo.VisionCore)3 (import '(java.awt Rectangle Robot Toolkit) )4 (import '(java.awt.image BufferedImage) )5 (import '(java.awt Graphics2D Panel))6 (import '(java.io File) )7 (import '(javax.imageio ImageIO) )8 (import '(javax.swing JFrame))9 (import '(org.apache.commons.io FileUtils))10 (import clojure.lang.LazySeq)11 (import '(name.audet.samuel.javacv.jna highgui cv cxcore))12 (import '(name.audet.samuel.javacv CanvasFrame))13 (import '(name.audet.samuel.javacv.jna cxcore$IplImage))14 (import '(name.audet.samuel.javacv.jna highgui$CvCapture$PointerByReference))15 (import '(name.audet.samuel.javacv.jna highgui$CvVideoWriter$PointerByReference))16 (import '(name.audet.samuel.javacv.jna cxcore$IplImage$PointerByReference))17 (import '(name.audet.samuel.javacv.jna cxcore$IplImage))18 (import '(name.audet.samuel.javacv JavaCvErrorCallback))19 (.redirectError (JavaCvErrorCallback.))21 (use 'clojure.contrib.repl-utils)23 (def -inf Double/NEGATIVE_INFINITY)24 (def inf Double/POSITIVE_INFINITY)28 (def lian (File. "/home/r/Desktop/source-videos/lian1.mpeg"))29 (def look (File. "/home/r/Desktop/source-videos/dramatic_look.flv"))31 (def target (File. "/home/r/Desktop/output-vision/"))34 ;this is still a work in progress, I'll come back to it later when I understand35 ;jna more thoroughly. the important abstraction here is36 ;video-seq, which gives a lazy sequence of Intel Image Processing library images.38 (defn naturals [] (iterate inc 0))40 (def ext "jpg")41 ;see below for the rationale for this choice of extention.43 (def cache-location "/home/r/Desktop/vision-cache/")45 (defn close-capture46 [capture]47 (highgui/cvReleaseCapture (highgui$CvCapture$PointerByReference. capture)))49 (defn close-writer50 [writer] (highgui/cvReleaseVideoWriter (highgui$CvVideoWriter$PointerByReference. writer)))52 (defn- cache-path53 [video]54 (File. cache-location (.getName video)))56 (defn- already-cached57 "this is the simplest and most retarded way to do it"58 [video]59 (.exists (cache-path video)))61 (defn- write-frame62 [capture target-dir n]63 (let [image (highgui/cvQueryFrame capture)]64 (if (nil? image) false65 (highgui/cvSaveImage (str (File. target-dir (str n "." ext))) image))))67 (defn- write-frame-bad68 [capture target-dir n]69 (println (str "saving frame: " n))70 (let [image (highgui/cvQueryFrame capture)]71 (if (nil? image) false72 ( ImageIO/write (.getBufferedImage image) ext (File. target-dir (str n "." ext))))))74 (defn- write-frames75 [video target-dir]76 (let [capture (highgui/cvCreateFileCapture (.getPath video))]77 (dorun78 (for [n (naturals) :while (write-frame capture target-dir n) ] nil ))79 (highgui/cvReleaseCapture (highgui$CvCapture$PointerByReference. capture))))81 (defn- cache-frames82 [cache-location video]83 (time84 (do85 (println "\"caching entire video structure... this will take a while... go get a snack or something :)\"")86 (FileUtils/deleteDirectory (cache-path video))87 (FileUtils/forceMkdir (cache-path video))88 (write-frames video (cache-path video)))))90 (defn cache91 [video]92 (if (already-cached video) nil (cache-frames cache-location video)))94 (defn video-len95 [video] (cache video)96 (alength (.list (cache-path video))))97 (def video-len (memoize video-len))99 (defn video-data100 "since the opencv version is so absolutely unreliable..."101 [video]102 (let103 [capture (highgui/cvCreateFileCapture (.getPath video))104 info {:length (video-len video)105 :width (highgui/cvGetCaptureProperty capture highgui/CV_CAP_PROP_FRAME_WIDTH)106 :height (highgui/cvGetCaptureProperty capture highgui/CV_CAP_PROP_FRAME_HEIGHT)107 :fps (highgui/cvGetCaptureProperty capture highgui/CV_CAP_PROP_FPS)108 :codec (highgui/cvGetCaptureProperty capture highgui/CV_CAP_PROP_FOURCC)}]109 (close-capture capture)110 info))111 (def video-data (memoize video-data))113 (defn- video-frame114 [video n]115 (cache video)116 (let117 [c++-managed (highgui/cvLoadImage (str (File. (cache-path video) (str n "." ext))) highgui/CV_LOAD_IMAGE_COLOR)118 jvm-managed (.clone c++-managed)]119 ;this bit with the cloning is so I can deal with Garbage Collection once and for all.120 ;the cpp-managed image must be manually Garbage Collected, but it's clone is managed by121 ;the JVM's Garbage Collector. By getting rid of the c++ part right here and now, no122 ;other function has to worry about manual garbage collection ever again.123 ;Unfortunately, this doesn't seem to work for certain types of files. It's not file-size124 ;which is the issue, but something involving the image header.125 (cxcore/cvReleaseImage (.pointerByReference c++-managed))126 jvm-managed127 ))130 (defn- video-frame-buffered131 "takes one frame from a video in constant time"132 [video n]133 (cache video)134 (ImageIO/read (File. (cache-path video) (str n "." ext))))137 (defn- dumb-write138 [video n writer]139 (let140 [c++-managed (highgui/cvLoadImage (str (File. (cache-path video) (str n ext))) highgui/CV_LOAD_IMAGE_COLOR)]141 (highgui/cvWriteFrame writer c++-managed)142 (cxcore/cvReleaseImage (cxcore$IplImage$PointerByReference. c++-managed))))144 (defn video-seq145 "makes a lazy sequence of IPL images"146 ;additionally, I want to pass metadata around with the sequence.147 [video] (cache video)148 (map #(video-frame video %) (range (video-len video))))155 (comment157 ; I initially decided to use .sr because it loads the fastest out of all the158 ; formats opencv supports, under a simple benchmark of reading/writing159 ; a blank file of each type 100 times.161 ;I just kept changing the file extention at the REPL to generate these times.162 (def file "test.tiff")163 (do164 (time (dotimes [_ 100] (highgui/cvSaveImage (str cache-location file) ipl)))165 (time (dotimes [_ 100] (highgui/cvLoadImage (str cache-location file)))))167 ; Write Read168 (jpg 4404.000955 msecs 3397.8564 msecs)169 (jpeg 4376.138853 msecs 3482.990118 msecs)170 (jpeg 4253.721501 msecs 3414.004122 msecs)171 (bmp 3488.281695 msecs 786.883035 msecs)172 (dib 3589.010247 msecs 685.681985 msecs)173 (jpe 4288.541679 msecs 3359.819425 msecs)174 (png 10127.648557 msecs 3786.184994 msecs)175 (pbm 3880.794141 msecs 917.737667 msecs)176 (pgm 3879.710445 msecs 894.78237 msecs)177 (ppm 3938.319148 msecs 1014.412766 msecs)178 (sr 3510.893891 msecs 676.502596 msecs)179 (dib 3434.654784 msecs 737.495844 msecs)180 (bmp 3354.956726 msecs 783.353025 msecs)181 (ras 3351.400751 msecs 722.548007 msecs)182 (tiff 3657.893326 msecs 1361.576798 msecs)183 (tif 3594.753736 msecs 1254.568533 msecs)185 ;Ah, but now it's time for some more tests.186 ;I started using187 (def ext ".sr")188 ;, and an empty cache, and ran189 (cache lian)190 "caching entire video structure... this will take a while... go get a snack or something :)"191 "Elapsed time: 56486.816728 msecs"192 (time (dorun (video-seq lian)))193 "Elapsed time: 120515.66221 msecs"194 (time (dorun (video-seq lian)))195 "Elapsed time: 122867.82989 msecs" ;good agreement with times197 ;*erased vision cache with*198 ;*rm -rf ~/Desktop/vision-cache *199 (def ext ".bmp")200 (cache lian)201 "Elapsed time: 59613.624691 msecs"202 (time (dorun (video-seq lian)))203 "Elapsed time: 123850.390784 msecs"205 ;same process except with206 (def ext ".jpg")207 (cache lian)208 "Elapsed time: 139964.031921 msecs"209 (time (dorun (video-seq lian)))210 "Elapsed time: 127740.50204 msecs"212 ;I find this quite shocking --- the jpg's do take longer to cache,213 ;but the processing time is almost the same!215 ;since lian is 434 MB as a bunch of jpg files, and 3.7 GB as .sr files,216 ;I'll go with the jpgs.219 ;; writing files221 "JPG"222 (time (write-video sarah (File. "/home/r/Desktop/clojure2.avi")))223 "Elapsed time: 371541.024455 msecs"225 "BMP"226 (time (write-video sarah (File. "/home/r/Desktop/clojure3.avi")))227 "Elapsed time: 382568.502361 msecs"229 )