1 ;; bbox contains float values but is also used to represent pixel
2 ;; positions. In that case start is the first sample that is non-zero
3 ;; and end is the last non-zero pixel.
6 (end (alexandria:required-argument
) :type vec
))
8 (defun extract-bbox2-ub8 (a bbox
)
9 (declare ((simple-array (unsigned-byte 8) 2) a
)
11 (values (simple-array (unsigned-byte 8) 2) &optional
))
12 (destructuring-bind (y x
)
14 (with-slots (start end
)
16 (unless (and (< (vec-x end
) x
)
18 (error "bbox is bigger than array"))
19 (let* ((sx (floor (vec-x start
)))
20 (sy (floor (vec-y start
)))
21 (widths (v+ (v- end start
) (v one one
)))
22 (res (make-array (list (floor (vec-y widths
))
23 (floor (vec-x widths
)))
24 :element-type
'(unsigned-byte 8))))
25 (destructuring-bind (yy xx
)
26 (array-dimensions res
)
27 (do-rectangle (j i
0 yy
0 xx
)
29 (aref a
(+ j sy
) (+ i sx
)))))
32 (defun replace-bbox2-ub8 (a b bbox
)
33 "A beeing a big array, and B a smaller one with BBOX giving its
34 coordinates relative to A, replace the contents of A with B."
35 (declare ((simple-array (unsigned-byte 8) 2) a b
)
37 (values (simple-array (unsigned-byte 8) 2) &optional
))
38 (destructuring-bind (y x
)
40 (destructuring-bind (yy xx
)
42 (with-slots (start end
)
44 (unless (and (< (vec-x end
) x
)
46 (error "bbox is bigger than array"))
47 (let ((widths (v+ (v- end start
) (v one one
))))
48 (unless (and (= (floor (vec-x widths
)) xx
)
49 (= (floor (vec-y widths
)) yy
))
50 (error "size of BBOX isn't the same as size of small array B"))
51 (let ((sx (floor (vec-x start
)))
52 (sy (floor (vec-y start
))))
53 (do-rectangle (j i
0 yy
0 xx
)
54 (setf (aref a
(+ sy j
) (+ sx i
))
58 (defun find-bbox2-ub8 (a)
59 "Return the rectangle containing non-zero pixels. Returns nil if all
61 (declare ((simple-array (unsigned-byte 8) 2) a
)
62 (values (or null bbox
) &optional
))
63 (destructuring-bind (y x
)
66 ;; Note: the order of the loops of do-rectangle is important
67 (do-rectangle (j i
0 y
0 x
)
68 (unless (= 0 (aref a j i
))
71 (left () ;; search from left side for first non-zero
72 (do-rectangle (i j
0 x
0 y
)
73 (unless (= 0 (aref a j i
))
74 (return-from left i
)))
77 (do-rectangle (j i
0 y
0 x
)
78 ;; invert j so that it starts search from bottom
79 (let ((jj (- (1- y
) j
)))
80 (unless (= 0 (aref a jj i
))
81 (return-from bottom jj
))))
84 (do-rectangle (i j
0 x
0 y
)
85 (let ((ii (- (1- x
) i
)))
86 (unless (= 0 (aref a j ii
))
87 (return-from right ii
))))
91 (when (<= l r
) ;; otherwise all pixels are zero
92 (make-bbox :start
(v (* one l
) (* one
(top)))
93 :end
(v (* one r
) (* one
(bottom)))))))))
96 (let* ((a (make-array (list 5 5)
97 :element-type
'(unsigned-byte 8)
98 :initial-contents
'((0 0 0 0 0)
103 (empty (make-array (list 5 5)
104 :element-type
'(unsigned-byte 8)))
105 (box (find-bbox2-ub8 a
))
106 (ex (extract-bbox2-ub8 a box
)))
107 (replace-bbox2-ub8 empty ex box
))
109 (defun find-bbox3-ub8 (a)
110 "Return the box containing non-zero pixels. Returns nil if all
112 (declare ((simple-array (unsigned-byte 8) 3) a
)
113 (values (or null bbox
) &optional
))
114 (destructuring-bind (z y x
)
117 (do-box (k j i
0 z
0 y
0 x
)
118 (unless (= 0 (aref a k j i
))
119 (return-from front k
)))
122 (do-box (k j i
0 z
0 y
0 x
)
123 (let ((kk (- (1- z
) k
)))
124 (unless (= 0 (aref a kk j i
))
125 (return-from back kk
))))
128 (do-box (j k i
0 y
0 z
0 x
)
129 (unless (= 0 (aref a k j i
))
130 (return-from top j
)))
133 (do-box (i k j
0 x
0 z
0 y
)
134 (unless (= 0 (aref a k j i
))
135 (return-from left i
)))
138 (do-box (j k i
0 y
0 z
0 x
)
139 (let ((jj (- (1- y
) j
)))
140 (unless (= 0 (aref a k jj i
))
141 (return-from bottom jj
))))
144 (do-box (i k j
0 x
0 z
0 y
)
145 (let ((ii (- (1- x
) i
)))
146 (unless (= 0 (aref a k j ii
))
147 (return-from right ii
))))
151 (when (<= l r
) ;; otherwise all pixels are zero
152 (make-bbox :start
(v (* one l
) (* one
(top)) (* one
(front)))
153 :end
(v (* one r
) (* one
(bottom)) (* one
(back)))))))))
155 (defmacro def-extract-bbox3
()
157 ,@(loop for i in
'((df my-float
)
158 (cdf (complex my-float
))
159 (ub8 (unsigned-byte 8))) collect
160 (destructuring-bind (short long
)
162 `(defun ,(intern (format nil
"EXTRACT-BBOX3-~a" short
)) (a bbox
)
163 (declare ((simple-array ,long
3) a
)
165 (values (simple-array ,long
3) &optional
))
166 (destructuring-bind (z y x
)
168 (with-slots (start end
)
170 (unless (and (< (vec-x end
) x
)
173 (error "bbox is bigger than array"))
174 (let* ((sx (floor (vec-x start
)))
175 (sy (floor (vec-y start
)))
176 (sz (floor (vec-z start
)))
177 (widths (v+ (v- end start
) (v one one one
)))
178 (res (make-array (list (floor (vec-z widths
))
179 (floor (vec-y widths
))
180 (floor (vec-x widths
)))
181 :element-type
',long
)))
182 (destructuring-bind (zz yy xx
)
183 (array-dimensions res
)
184 (do-box (k j i
0 zz
0 yy
0 xx
)
185 (setf (aref res k j i
)
186 (aref a
(+ k sz
) (+ j sy
) (+ i sx
)))))
191 (defun replace-bbox3-ub8 (a b bbox
)
192 "A beeing a big array, and B a smaller one with BBOX giving its
193 coordinates relative to A, replace the contents of A with B."
194 (declare ((simple-array (unsigned-byte 8) 3) a b
)
196 (values (simple-array (unsigned-byte 8) 3) &optional
))
197 (destructuring-bind (z y x
)
199 (destructuring-bind (zz yy xx
)
201 (with-slots (start end
)
203 (unless (and (< (vec-x end
) x
)
206 (error "bbox is bigger than array"))
207 (let ((widths (v+ (v- end start
) (v one one one
))))
208 (unless (and (= (floor (vec-x widths
)) xx
)
209 (= (floor (vec-y widths
)) yy
)
210 (= (floor (vec-z widths
)) zz
))
211 (error "size of BBOX isn't the same as size of small array B"))
212 (let ((sx (floor (vec-x start
)))
213 (sy (floor (vec-y start
)))
214 (sz (floor (vec-z start
))))
215 (do-box (k j i
0 zz
0 yy
0 xx
)
216 (setf (aref a
(+ sz k
) (+ sy j
) (+ sx i
))
221 (let* ((empty (make-array (list 4 4 4) :element-type
'(unsigned-byte 8)))
222 (a (make-array (list 4 4 4)
223 :element-type
'(unsigned-byte 8)
241 (box (find-bbox3-ub8 a
))
242 (ex (extract-bbox3-ub8 a box
)))
243 (replace-bbox3-ub8 empty ex box
))