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 understand
35 ;jna more thoroughly. the important abstraction here is
36 ;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-capture
46 [capture]
47 (highgui/cvReleaseCapture (highgui$CvCapture$PointerByReference. capture)))
49 (defn close-writer
50 [writer] (highgui/cvReleaseVideoWriter (highgui$CvVideoWriter$PointerByReference. writer)))
52 (defn- cache-path
53 [video]
54 (File. cache-location (.getName video)))
56 (defn- already-cached
57 "this is the simplest and most retarded way to do it"
58 [video]
59 (.exists (cache-path video)))
61 (defn- write-frame
62 [capture target-dir n]
63 (let [image (highgui/cvQueryFrame capture)]
64 (if (nil? image) false
65 (highgui/cvSaveImage (str (File. target-dir (str n "." ext))) image))))
67 (defn- write-frame-bad
68 [capture target-dir n]
69 (println (str "saving frame: " n))
70 (let [image (highgui/cvQueryFrame capture)]
71 (if (nil? image) false
72 ( ImageIO/write (.getBufferedImage image) ext (File. target-dir (str n "." ext))))))
74 (defn- write-frames
75 [video target-dir]
76 (let [capture (highgui/cvCreateFileCapture (.getPath video))]
77 (dorun
78 (for [n (naturals) :while (write-frame capture target-dir n) ] nil ))
79 (highgui/cvReleaseCapture (highgui$CvCapture$PointerByReference. capture))))
81 (defn- cache-frames
82 [cache-location video]
83 (time
84 (do
85 (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 cache
91 [video]
92 (if (already-cached video) nil (cache-frames cache-location video)))
94 (defn video-len
95 [video] (cache video)
96 (alength (.list (cache-path video))))
97 (def video-len (memoize video-len))
99 (defn video-data
100 "since the opencv version is so absolutely unreliable..."
101 [video]
102 (let
103 [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-frame
114 [video n]
115 (cache video)
116 (let
117 [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 by
121 ;the JVM's Garbage Collector. By getting rid of the c++ part right here and now, no
122 ;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-size
124 ;which is the issue, but something involving the image header.
125 (cxcore/cvReleaseImage (.pointerByReference c++-managed))
126 jvm-managed
127 ))
130 (defn- video-frame-buffered
131 "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-write
138 [video n writer]
139 (let
140 [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-seq
145 "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 (comment
157 ; I initially decided to use .sr because it loads the fastest out of all the
158 ; formats opencv supports, under a simple benchmark of reading/writing
159 ; 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 (do
164 (time (dotimes [_ 100] (highgui/cvSaveImage (str cache-location file) ipl)))
165 (time (dotimes [_ 100] (highgui/cvLoadImage (str cache-location file)))))
167 ; Write Read
168 (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 using
187 (def ext ".sr")
188 ;, and an empty cache, and ran
189 (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 times
197 ;*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 with
206 (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 files
221 "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 )