-
Notifications
You must be signed in to change notification settings - Fork 0
/
opencv_compute_test.clj
108 lines (96 loc) · 4.75 KB
/
opencv_compute_test.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
(ns tech.opencv-compute-test
(:require [tech.opencv :as opencv]
[tech.resource :as resource]
[clojure.test :refer :all]
[tech.opencv-test :as opencv-test]
[tech.v2.datatype :as dtype]
[tech.v2.datatype.functional :as dfn]
[tech.v2.datatype.unary-op :as unary-op]
[tech.v2.tensor :as dtt]
[clojure.pprint]))
(deftest bgr-test
(resource/stack-resource-context
(let [test-image (opencv/load "test/data/test.jpg")
;;Select is in-place so this did not change the image at all.
bgr-image (dtt/select test-image :all :all [2 1 0])
dest-image (dtype/copy! bgr-image (dtype/from-prototype test-image))]
;;The datatype library has the convention that the thing that is mutated
;;is returned from the function.
(opencv/save dest-image "bgr.jpg"))))
(deftest lighten-bgr-test
(resource/stack-resource-context
(let [test-image (opencv/load "test/data/test.jpg")
result
(-> test-image
(dtt/select :all :all [2 1 0])
(dfn/+ 50)
;;Clamp top end to 0-255
(dfn/min 255)
(dtype/copy! (dtype/from-prototype test-image)))]
(opencv/save result "bgr-lighten.jpg"))))
(deftest modify-time-test
(resource/stack-resource-context
;;Clone test-image into jvm datastructures so the garbage collector
;;collects the garbage from the time tests below and we aren't sitting
;;with image allocation/deallocation times in our performance tests.
;;The gc will be a lot faster.
(let [source-image (opencv/load "test/data/test.jpg")
;; Reader composition is lazy so the expression below reads from the test image
;; (ecount image) times. It writes to the destination once and the byte value
;; is completely transformed from the src image to the dest while in cache.
;; Virtual table lookups happen multiple times per byte value. It is important
;; to realize that under the covers the image is stored as bytes. These are
;; read in a datatype-aware way and converted to their appropriate unsigned
;; values automatically and when written they are checked to ensure they are
;; within range. There are 2N checks for correct datatype in this pathway;
;; everything else is read/operated on as a short integer.
reader-composition #(-> source-image
(dtt/select :all :all [2 1 0])
(dfn/+ 50)
;;Clamp top end to 0-255
(dfn/min 255)
(dtype/copy! (dtype/from-prototype source-image)))
;; In this case, we use a macro to do the entire computation inline in one
;; reader. This saves the cost of a vtable lookup and some indirection at the
;; cost of creating a specific function for just this purpose. As above, the
;; data is read correctly from the source and then checked on write.
inline-fn #(as-> source-image dest-image
(dtt/select dest-image :all :all [2 1 0])
(unary-op/unary-reader
:int16 (-> (+ x 50)
(min 255)
unchecked-short)
dest-image)
(dtype/copy! dest-image
;;Note from-prototype fails for reader chains.
;;So you have to copy or use an actual image.
(dtype/from-prototype source-image)))]
;;warmup a little.
(reader-composition)
(inline-fn)
(clojure.pprint/pprint
{:reader-composition (with-out-str (time (dotimes [iter 10]
(reader-composition))))
:inline-fn (with-out-str (time (dotimes [iter 10]
(inline-fn))))}))))
(deftest smooth-image-flow
(resource/stack-resource-context
(let [src-img (opencv/load "test/data/test.jpg")]
(-> src-img
(dfn// 2)
(dtype/copy! (dtype/from-prototype src-img))
(opencv/save "tensor_darken.jpg")))))
(deftest tensor-test
(resource/stack-resource-context
(is (dfn/equals
(dtt/->tensor [[[172 170 170]
[172 170 170]
[171 169 169]]
[[173 171 171]
[174 172 172]
[173 171 171]]
[[174 172 172]
[175 173 173]
[174 172 172]]])
(dtt/select (opencv/load "test/data/test.jpg")
(range 3) (range 3) :all)))))