2 (:use
:cl
:sb-alien
:sb-c-call
)
45 #:convert3-cdf
/df-imagpart
46 #:convert3-df
/ub8-floor
47 #:convert2-ub8
/cdf-complex
48 #:convert2-cdf
/df-realpart
49 #:convert2-df
/cdf-complex
50 #:convert3-ub8
/cdf-complex
51 #:convert2-cdf
/ub8-realpart
52 #:convert3-cdf
/df-phase
53 #:convert2-cdf
/ub8-abs
54 #:convert3-cdf
/df-realpart
55 #:convert3-df
/cdf-complex
56 #:convert2-cdf
/ub8-phase
58 #:convert2-cdf
/df-imagpart
59 #:convert3-cdf
/ub8-abs
60 #:convert2-cdf
/df-phase
62 #:convert3-cdf
/ub8-phase
63 #:convert2-df
/ub8-floor
64 #:convert3-cdf
/ub8-realpart
66 #:normalize2-cdf
/ub8-phase
67 #:normalize3-cdf
/ub8-phase
68 #:normalize2-cdf
/ub8-realpart
69 #:normalize2-df
/ub8-floor
70 #:normalize2-cdf
/ub8-abs
71 #:normalize3-df
/ub8-realpart
72 #:normalize3-cdf
/ub8-abs
73 #:normalize3-cdf
/ub8-realpart
74 #:normalize3-df
/ub8-floor
80 ;; for i in `cat vol.lisp|grep defconst|cut -d " " -f 2`;do echo \#:$i ;done
84 #+nil
(declaim (optimize (speed 3) (debug 1) (safety 1)))
85 (declaim (optimize (speed 2) (debug 3) (safety 3)))
87 (load-shared-object "/usr/lib/libfftw3.so.3")
89 (define-alien-routine ("fftw_execute" execute
)
93 (defconstant +forward
+ 1)
94 (defconstant +backward
+ -
1)
95 (defconstant +estimate
+ (ash 1 6))
98 (define-alien-routine ("fftw_plan_dft_3d" plan-dft-3d
)
103 (in (* double-float
))
104 (out (* double-float
))
106 (flags unsigned-int
))
108 (define-alien-routine ("fftw_plan_dft_2d" plan-dft-2d
)
112 (in (* double-float
))
113 (out (* double-float
))
115 (flags unsigned-int
))
117 ;; C-standard "row-major" order, so that the last dimension has the
118 ;; fastest-varying index in the array.
122 (defmacro do-rectangle
((j i ymin ymax xmin xmax
) &body body
)
123 "Loop through 2d points in ymin .. ymax-1. e.g. call with 0 y 0 x to
125 `(loop for
,j from
,ymin below
,ymax do
126 (loop for
,i from
,xmin below
,xmax do
129 (defmacro do-box
((k j i zmin zmax ymin ymax xmin xmax
) &body body
)
130 "Loop through 3d points e.g. call with 0 z 0 y 0 x to visit every
132 `(loop for
,k from
,zmin below
,zmax do
133 (loop for
,j from
,ymin below
,ymax do
134 (loop for
,i from
,xmin below
,xmax do
137 (defun fftshift1 (in)
138 (declare ((simple-array (complex double-float
) 1) in
)
139 (values (simple-array (complex double-float
) 1) &optional
))
140 (let* ((n (length in
))
143 :element-type
'(complex double-float
))))
144 (dotimes (i (length in
))
145 (let ((ii (mod (+ i nh
) n
)))
146 (setf (aref out ii
) (aref in i
))))
149 (let* ((ls '(1 2 3 4 5 6 7 8 9))
150 (a (make-array (length ls
)
151 :element-type
'(complex double-float
)
152 :initial-contents
(mapcar
153 #'(lambda (z) (coerce z
154 '(complex double-float
)))
160 (defun fftshift2 (in)
161 (declare ((simple-array (complex double-float
) 2) in
)
162 (values (simple-array (complex double-float
) 2) &optional
))
163 (let ((out (make-array (array-dimensions in
)
164 :element-type
'(complex double-float
))))
165 (destructuring-bind (w1 w0
)
166 (array-dimensions in
)
167 (let ((wh0 (floor w0
2))
169 (do-rectangle (j i
0 w1
0 w0
)
170 (let* ((ii (mod (+ i wh0
) w0
))
171 (jj (mod (+ j wh1
) w1
)))
176 (defun ft2 (in &key
(forward t
))
177 (declare ((simple-array (complex double-float
) 2) in
)
179 (values (simple-array (complex double-float
) 2) &optional
))
180 (let ((dims (array-dimensions in
)))
181 (destructuring-bind (y x
)
183 (let* ((out (make-array dims
:element-type
'(complex double-float
))))
184 (sb-sys:with-pinned-objects
(in out
)
185 (let ((p (plan-dft-2d y x
187 (sb-ext:array-storage-vector in
))
189 (sb-ext:array-storage-vector out
))
195 (when forward
;; normalize if forward
196 (let ((1/n
(/ 1d0
(* x y
))))
197 (do-rectangle (j i
0 y
0 x
)
198 (setf (aref out j i
) (* 1/n
(aref out j i
))))))
202 `(ft2 ,in
:forward nil
))
205 ;; was originally fftshift3 /home/martin/usb/y2009/1123/1.lisp
206 ;; now it is better and work for odd dimensions
207 (defun fftshift3 (in)
208 (declare ((simple-array (complex double-float
) 3) in
)
209 (values (simple-array (complex double-float
) 3) &optional
))
210 (let ((out (make-array (array-dimensions in
)
211 :element-type
'(complex double-float
))))
212 (destructuring-bind (w2 w1 w0
)
213 (array-dimensions in
)
214 (let ((wh0 (floor w0
2))
217 (do-box (k j i
0 w2
0 w1
0 w0
)
218 (let ((ii (mod (+ i wh0
) w0
))
219 (jj (mod (+ j wh1
) w1
))
220 (kk (mod (+ k wh2
) w2
)))
221 (setf (aref out k j i
)
222 (aref in kk jj ii
))))))
226 (declaim (ftype (function ((simple-array (complex double-float
) (* * *))
227 &key
(:forward boolean
))
228 (values (simple-array (complex double-float
) (* * *))
231 (defun ft3 (in &key
(forward t
))
232 (let ((dims (array-dimensions in
)))
233 (destructuring-bind (z y x
)
235 (let* ((out (make-array dims
:element-type
'(complex double-float
))))
236 (sb-sys:with-pinned-objects
(in out
)
237 (let ((p (plan-dft-3d z y x
239 (sb-ext:array-storage-vector in
))
241 (sb-ext:array-storage-vector out
))
247 (when forward
;; normalize if forward
248 (let ((1/n
(/ 1d0
(* x y z
))))
249 (do-box (k j i
0 z
0 y
0 x
)
250 (setf (aref out k j i
) (* 1/n
(aref out k j i
))))))
254 `(ft3 ,in
:forward nil
))
256 (defun convolve2-circ (vola volb
)
257 (declare ((simple-array (complex double-float
) 2) vola volb
)
258 (values (simple-array (complex double-float
) 2) &optional
))
259 (let* ((da (array-dimensions vola
))
260 (db (array-dimensions volb
))
261 (compare-ab (map 'list
#'(lambda (x y
) (eq x y
)) da db
)))
262 (when (some #'null compare-ab
)
263 (error "convolve3-circ expects both input arrays to have the same dimensions.")))
264 (ift2 (.
*2 (ft2 vola
) (ft2 volb
))))
269 (values (simple-array (unsigned-byte 8) (* *))
272 (defun read-pgm (filename)
273 (with-open-file (s filename
)
274 (unless (equal (symbol-name (read s
)) "P5")
275 (error "no PGM file"))
279 (pos (file-position s
))
282 :element-type
'(unsigned-byte 8)))
285 :element-type
'(unsigned-byte 8)
286 :displaced-to data
)))
287 (declare ((simple-array (unsigned-byte 8) (* *)) data
)
288 ((array (unsigned-byte 8) (*)) data-1d
)
289 ((integer 0 65535) grays w h
))
290 (unless (= grays
255)
291 (error "image has wrong bitdepth"))
292 (with-open-file (s filename
293 :element-type
'(unsigned-byte 8))
294 (file-position s pos
)
295 (read-sequence data-1d s
))
300 ((array (unsigned-byte 8) 2)
302 (values null
&optional
))
304 (defun write-pgm (img filename
)
305 (destructuring-bind (h w
)
306 (array-dimensions img
)
307 (declare ((integer 0 65535) w h
))
308 (with-open-file (s filename
310 :if-exists
:supersede
311 :if-does-not-exist
:create
)
313 (format s
"P5~%~D ~D~%255~%" w h
))
314 (with-open-file (s filename
315 :element-type
'(unsigned-byte 8)
318 (let ((data-1d (make-array
320 :element-type
'(unsigned-byte 8)
322 (write-sequence data-1d s
)))
327 ((array (unsigned-byte 8) (*)) &optional fixnum
)
328 (values (simple-array fixnum
(*)) (unsigned-byte 8) (unsigned-byte 8) (unsigned-byte 8)
331 (defun histogram (img &optional
(bins 30))
332 (let* ((maxval (aref img
0))
336 (let ((v (aref img i
)))
341 (let* ((len (1+ (- maxval minval
)))
342 (result (make-array len
:element-type
'fixnum
))
343 (binsm (min (- maxval minval
) bins
)))
344 (when (eq maxval minval
)
345 #+nil
(error "data is too boring.")
346 (return-from histogram
(values result minval maxval binsm
)))
348 (incf (aref result
(floor (* binsm
351 (- maxval minval
)))))
352 (values result minval maxval binsm
))))
354 (declaim (ftype (function ((array * (* *)))
355 (values (simple-array * (*)) &optional
))
357 (defun get-linear-array (img)
358 (sb-ext:array-storage-vector img
)
359 #+nil
(make-array (* (array-dimension img
0)
360 (array-dimension img
1))
361 :element-type
(array-element-type img
)
365 (declaim (ftype (function (string)
366 (values (simple-array (unsigned-byte 8) (* * *))
369 (defun read-stack (fn)
370 (let* ((files (directory fn
))
371 (slices (length files
))
372 (a (read-pgm (first files
))))
373 (destructuring-bind (h w
)
375 (let* ((result (make-array (list slices h w
)
376 :element-type
'(unsigned-byte 8))))
378 (let* ((a (read-pgm (elt files k
))))
381 (setf (aref result k j i
)
385 (defmacro with-slice
((slice-array array slice-nr
) &body body
)
386 "Returns SLICE-NRth slice of ARRAY as the 2D SLICE-ARRAY."
390 `(destructuring-bind (,z
,y
,x
)
391 (array-dimensions ,array
)
392 (when (or (< ,slice-nr
0) (<= ,z
,slice-nr
))
393 (error "slice-nr=~d out of range [0,~d]" ,slice-nr
(1- ,z
)))
394 (let* ((,slice-array
(make-array (list ,y
,x
)
395 :element-type
'(unsigned-byte 8)
397 :displaced-index-offset
(* ,slice-nr
,x
,y
))))
400 (declaim (ftype (function (double-float) (values double-float
&optional
))
405 (declaim (ftype (function ((array double-float
*)
407 (array double-float
*))
408 (values double-float double-float
409 double-float double-float
&optional
))
411 ;; chernov/book.pdf p. 20
412 (defun linear-regression (y &optional
413 (x (let* ((n (length y
)))
416 :element-type
'double-float
418 (loop for i below n collect
(* 1d0 i
))))))
419 "Linear regression of the values in Y with the function y=a*x+b. If
420 X isn't supplied its assumed to be 0,1,2, ... . Returned are the
421 fitting parameters A and B and their errors DELTA_A and DELTA_B."
422 (let* ((n (length y
))
423 (xmean (/ (loop for xi across x sum xi
) n
))
424 (ymean (/ (loop for xi across y sum xi
) n
))
425 (sxx (loop for xi across x sum
(square (- xi xmean
))))
426 #+nil
(syy (loop for xi across y sum
(square (- xi ymean
))))
427 (sxy (loop for i below n sum
(* (- (aref x i
) xmean
)
428 (- (aref y i
) ymean
))))
430 (ahat (- ymean
(* bhat xmean
)))
431 (var (/ (loop for i below n sum
(square (- (aref y i
) ahat
432 (* bhat
(aref x i
)))))
434 (vara (* var
(+ (/ (square xmean
)
438 (values ahat bhat
(sqrt vara
) (sqrt varb
))))
441 (linear-regression (let* ((ll (list 1d0
2.01d0
3d0
4d0
)))
442 (make-array (length ll
)
443 :element-type
'double-float
444 :initial-contents ll
)))
446 (declaim (ftype (function (integer)
447 (values (unsigned-byte 8) &optional
))
451 (return-from clamp
0))
453 (return-from clamp
255))
457 (declaim (ftype (function ((simple-array (unsigned-byte 8) 2)
459 (values (unsigned-byte 8) &optional
))
461 (defun aref2-zero-ub8 (a j i
)
462 "Like AREF but return zero if subscripts J and I point outside of
464 (if (array-in-bounds-p a j i
)
468 (declaim (ftype (function ((simple-array double-float
2)
470 (values double-float
&optional
))
472 (defun aref2-zero-df (a j i
)
473 "Like AREF but return zero if subscripts J and I point outside of
475 (if (array-in-bounds-p a j i
)
479 (declaim (ftype (function ((simple-array (complex double-float
) 2)
481 (values (complex double-float
) &optional
))
483 (defun aref2-zero-cdf (a j i
)
484 "Like AREF but return zero if subscripts J and I point outside of
486 (if (array-in-bounds-p a j i
)
491 (declaim (ftype (function ((unsigned-byte 8)
494 (values double-float
&optional
))
496 (inline interp1-ub8
))
497 (defun interp1-ub8 (a b xi
)
498 "Interpolate between values A and B. Returns A for xi=0 and B for
500 (+ (* (- 1d0 xi
) a
) (* xi b
)))
502 (declaim (ftype (function (double-float double-float double-float
)
503 (values double-float
&optional
))
506 (defun interp1-df (a b xi
)
507 "Interpolate between values A and B. Returns A for xi=0 and B for
509 (+ (* (- 1d0 xi
) a
) (* xi b
)))
511 (declaim (ftype (function ((complex double-float
)
512 (complex double-float
) double-float
)
513 (values (complex double-float
) &optional
))
515 (inline interp1-cdf
))
516 (defun interp1-cdf (a b xi
)
517 "Interpolate between values A and B. Returns A for xi=0 and B for
519 (+ (* (- 1d0 xi
) a
) (* xi b
)))
521 (declaim (ftype (function ((or (unsigned-byte 8)
523 (complex double-float
))
524 (or (unsigned-byte 8)
526 (complex double-float
))
528 (values (or double-float
529 (complex double-float
)) &optional
))
532 (defun interp1 (a b xi
)
534 ((unsigned-byte 8) (interp1-ub8 a b xi
))
535 (double-float (interp1-df a b xi
))
536 ((complex double-float
) (interp1-cdf a b xi
))))
538 (declaim (ftype (function ((simple-array (unsigned-byte 8) 2)
539 double-float double-float
)
540 (values double-float
&optional
))
542 (defun interpolate2-ub8 (img x y
)
543 "Bilinear interpolation on an image IMG. The coordinates X and Y can
544 be floating point values. If they point outside of IMG 0 is returned."
545 (multiple-value-bind (i ix
)
547 (multiple-value-bind (j jx
)
549 ;; values on grid points, top left is i,j and stored in a
554 (let ((a (aref img i j
))
555 (b (aref2-zero-ub8 img
(1+ i
) j
))
556 (c (aref2-zero-ub8 img i
(1+ j
)))
557 (d (aref2-zero-ub8 img
(1+ i
) (1+ j
))))
558 ;; now interpolate verticals
564 (let ((e (interp1-ub8 a c jx
))
565 (f (interp1-ub8 b d jx
)))
566 ;; and now horizontal
568 (let ((g (interp1-df e f ix
)))
571 (declaim (ftype (function ((simple-array double-float
2)
572 double-float double-float
)
573 (values double-float
&optional
))
575 (defun interpolate2-df (img x y
)
576 "Bilinear interpolation on an image IMG. The coordinates X and Y can
577 be floating point values. If they point outside of IMG 0 is returned."
578 (multiple-value-bind (i ix
)
580 (multiple-value-bind (j jx
)
582 (let ((a (aref img i j
))
583 (b (aref2-zero-df img
(1+ i
) j
))
584 (c (aref2-zero-df img i
(1+ j
)))
585 (d (aref2-zero-df img
(1+ i
) (1+ j
))))
586 (let ((e (interp1-df a c jx
))
587 (f (interp1-df b d jx
)))
588 (let ((g (interp1-df e f ix
)))
591 (declaim (ftype (function ((simple-array (complex double-float
) 2)
592 double-float double-float
)
593 (values (complex double-float
) &optional
))
595 (defun interpolate2-cdf (img x y
)
596 "Bilinear interpolation on an image IMG. The coordinates X and Y can
597 be floating point values. If they point outside of IMG 0 is returned."
598 (multiple-value-bind (i ix
)
600 (multiple-value-bind (j jx
)
602 (let ((a (aref img i j
))
603 (b (aref2-zero-cdf img
(1+ i
) j
))
604 (c (aref2-zero-cdf img i
(1+ j
)))
605 (d (aref2-zero-cdf img
(1+ i
) (1+ j
))))
606 (let ((e (interp1-cdf a c jx
))
607 (f (interp1-cdf b d jx
)))
608 (let ((g (interp1-cdf e f ix
)))
612 (declaim (ftype (function ((simple-array * 2) double-float double-float
)
613 (values (or double-float
614 (complex double-float
)) &optional
))
616 (defun interpolate2 (img x y
)
617 "Bilinear interpolation on an image IMG. The coordinates X and Y can
618 be floating point values. If they point outside of IMG 0 is returned."
620 ((simple-array (unsigned-byte 8) 2) (interpolate2-ub8 img x y
))
621 ((simple-array double-float
2) (interpolate2-df img x y
))
622 ((simple-array (complex double-float
) 2) (interpolate2-cdf img x y
))))
625 (let ((a (make-array (list 2 2) :element-type
'(unsigned-byte 8)
626 :initial-contents
'((1 2) (2 3)))))
627 (interpolate2 a
.5d0
.2d0
))
629 (declaim (ftype (function (string (simple-array (complex double-float
) 3)
630 &key
(:function function
))
631 (values null
&optional
))
633 (defun save-stack (fn vol
&key
(function #'realpart
))
634 ;; add a slash / if there isn't one
635 (ensure-directories-exist (if (eq (1- (length fn
))
636 (position #\
/ fn
:from-end t
))
638 (format nil
"~a/" fn
)))
639 (destructuring-bind (z y x
)
640 (array-dimensions vol
)
641 (let ((b (make-array (list y x
)
642 :element-type
'(unsigned-byte 8))))
644 (do-rectangle (j i
0 y
0 x
)
646 (clamp (floor (* 255 (funcall function
(aref vol k j i
)))))))
647 (write-pgm b
(format nil
"~a/~3,'0d.pgm" fn k
)))))
650 (declaim (ftype (function (string (simple-array (unsigned-byte 8) 3))
651 (values null
&optional
))
653 (defun save-stack-ub8 (fn vol
)
654 (ensure-directories-exist (if (eq (1- (length fn
))
655 (position #\
/ fn
:from-end t
))
657 (format nil
"~a/" fn
)))
658 (destructuring-bind (z y x
)
659 (array-dimensions vol
)
660 (let ((b (make-array (list y x
)
661 :element-type
'(unsigned-byte 8))))
663 (do-rectangle (j i
0 y
0 x
)
666 (write-pgm b
(format nil
"~a/~3,'0d.pgm" fn k
)))))
669 (defun .
*2 (vola volb
)
670 (declare ((simple-array (complex double-float
) 2) vola volb
)
671 (values (simple-array (complex double-float
) 2) &optional
))
672 (let ((result (make-array (array-dimensions vola
)
673 :element-type
(array-element-type vola
))))
674 (destructuring-bind (y x
)
675 (array-dimensions vola
)
676 (do-rectangle (j i
0 y
0 x
)
677 (setf (aref result j i
)
682 (defun .
+2 (vola volb
)
683 (declare ((simple-array (complex double-float
) 2) vola volb
)
684 (values (simple-array (complex double-float
) 2) &optional
))
685 (let ((result (make-array (array-dimensions vola
)
686 :element-type
(array-element-type vola
))))
687 (destructuring-bind (y x
)
688 (array-dimensions vola
)
689 (do-rectangle (j i
0 y
0 x
)
690 (setf (aref result j i
)
695 (defun .
* (vola volb
)
696 (declare ((simple-array (complex double-float
) 3) vola volb
)
697 (values (simple-array (complex double-float
) 3) &optional
))
698 (let ((result (make-array (array-dimensions vola
)
699 :element-type
(array-element-type vola
))))
700 (destructuring-bind (z y x
)
701 (array-dimensions vola
)
702 (do-box (k j i
0 z
0 y
0 x
)
703 (setf (aref result k j i
)
705 (aref volb k j i
)))))
708 (defun .
+ (vola volb
)
709 (declare ((simple-array (complex double-float
) 3) vola volb
)
710 (values (simple-array (complex double-float
) 3) &optional
))
711 (let ((result (make-array (array-dimensions vola
)
712 :element-type
(array-element-type vola
))))
713 (destructuring-bind (z y x
)
714 (array-dimensions vola
)
715 (do-box (k j i
0 z
0 y
0 x
)
716 (setf (aref result k j i
)
718 (aref volb k j i
)))))
721 (declaim (ftype (function (double-float (simple-array (complex double-float
) 3))
722 (values (simple-array (complex double-float
) 3) &optional
))
725 (let* ((a (sb-ext:array-storage-vector vol
))
728 (setf (aref a i
) (* s
(aref a i
)))))
732 (declare (double-float s
)
733 ((simple-array (complex double-float
) 2) vol
)
734 (values (simple-array (complex double-float
) 2) &optional
))
735 (let* ((a (sb-ext:array-storage-vector vol
))
738 (setf (aref a i
) (* s
(aref a i
)))))
742 (declaim (ftype (function ((simple-array (complex double-float
) 3)
743 (simple-array (complex double-float
) 3))
744 (values (simple-array (complex double-float
) 3) &optional
))
745 convolve3-circ convolve3
))
746 (defun convolve3-circ (vola volb
)
747 (let* ((da (array-dimensions vola
))
748 (db (array-dimensions volb
))
749 (compare-ab (map 'list
#'(lambda (x y
) (eq x y
)) da db
)))
750 (when (some #'null compare-ab
)
751 (error "convolve3-circ expects both input arrays to have the same dimensions.")))
752 (ift3 (.
* (ft3 vola
) (ft3 volb
))))
754 ;; volb is the kernel
755 (defun convolve3 (vola volb
)
756 (destructuring-bind (za ya xa
)
757 (array-dimensions vola
)
758 (destructuring-bind (zb yb xb
)
759 (array-dimensions volb
)
760 (let* ((biga (make-array (list (+ za zb
)
763 :element-type
'(complex double-float
)))
764 (bigb (make-array (array-dimensions biga
)
765 :element-type
'(complex double-float
)))
772 (do-box (k j i
0 za
0 ya
0 xa
)
773 (setf (aref biga
(+ k fzb
) (+ j fyb
) (+ i fxb
))
775 (do-box (k j i
0 zb
0 yb
0 xb
)
776 (setf (aref bigb
(+ k fza
) (+ j fya
) (+ i fxa
))
778 (let* ((conv (convolve3-circ biga
(fftshift3 bigb
)))
779 (result (make-array (array-dimensions vola
)
780 :element-type
'(complex double-float
))))
781 (do-box (k j i
0 za
0 ya
0 xa
)
782 (setf (aref result k j i
)
783 (aref conv
(+ k fzb
) (+ j fyb
) (+ i fxb
))))
787 (let ((a (make-array (list 100 200 300)
788 :element-type
'(complex double-float
)))
789 (b (make-array (list 10 200 30)
790 :element-type
'(complex double-float
))))
795 (declaim (ftype (function ((simple-array (complex double-float
) 3))
796 (values (simple-array (unsigned-byte 8) 3)
799 (defun convert-vol (vol)
800 (destructuring-bind (z y x
)
801 (array-dimensions vol
)
802 (let ((result (make-array (array-dimensions vol
)
803 :element-type
'(unsigned-byte 8))))
804 (do-box (k j i
0 z
0 y
0 x
)
805 (setf (aref result k j i
)
806 (clamp (floor (* 255 (abs (aref vol k j i
)))))))
809 (declaim (ftype (function ((simple-array (complex double-float
) 2)
811 (values (simple-array (unsigned-byte 8) 2)
814 (defun convert-img (img &optional
(function #'abs
))
815 (destructuring-bind (y x
)
816 (array-dimensions img
)
817 (let ((result (make-array (array-dimensions img
)
818 :element-type
'(unsigned-byte 8))))
819 (do-rectangle (j i
0 y
0 x
)
820 (setf (aref result j i
)
821 (clamp (floor (funcall function
(aref img j i
))))))
824 (declaim (ftype (function ((simple-array (complex double-float
) 3))
825 (values (simple-array (complex double-float
) 3)
828 (defun resample-half (vol)
829 (destructuring-bind (z y x
)
830 (array-dimensions vol
)
831 (let* ((xx (floor x
2))
834 (small (make-array (list zz yy xx
)
835 :element-type
'(complex double-float
))))
836 (do-box (k j i
0 zz
0 xx
0 xx
)
837 (setf (aref small k j i
)
838 (aref vol
(* k
2) (* j
2) (* i
2))))
842 (declaim (ftype (function ((simple-array (complex double-float
) 3)
844 (values (simple-array (complex double-float
) 2)
847 (defun cross-section-xz (a &optional
(y (floor (array-dimension a
1) 2)))
848 (destructuring-bind (z y-size x
)
850 (unless (<= 0 y
(1- y-size
))
851 (error "Y is out of bounds."))
852 (let ((b (make-array (list z x
)
853 :element-type
`(complex double-float
))))
854 (do-rectangle (j i
0 z
0 x
)
859 ;; for writing several type conversion functions
860 ;; will have a name like convert3-ub8/cdf-complex
861 (defmacro def-convert
(dim in-type out-type
&optional
(function '#'identity
)
862 (short-function-name nil
))
863 (let ((short-image-types
864 '(((complex double-float
) . cdf
)
866 ((unsigned-byte 8) . ub8
))))
867 (labels ((find-short-type-name (type)
868 (cdr (assoc type short-image-types
:test
#'equal
)))
869 (find-long-type-name (short-type)
870 (car (rassoc short-type short-image-types
))))
871 `(defun ,(intern (format nil
"CONVERT~d-~a/~a-~a"
873 (find-short-type-name in-type
)
874 (find-short-type-name out-type
)
875 (if short-function-name
877 (subseq (format nil
"~a" function
)
879 (declare ((simple-array ,in-type
,dim
) a
)
880 (values (simple-array ,out-type
,dim
) &optional
))
881 (let* ((res (make-array (array-dimensions a
)
882 :element-type
(quote ,out-type
)))
883 (res1 (sb-ext:array-storage-vector res
))
884 (a1 (sb-ext:array-storage-vector a
))
888 (funcall ,function
(aref a1 i
))))
890 (def-convert 3 (unsigned-byte 8) (complex double-float
)
891 #'(lambda (c) (complex (* 1d0 c
))) complex
)
892 (def-convert 3 double-float
(complex double-float
)
893 #'(lambda (d) (complex d
)) complex
)
894 (def-convert 3 double-float
(unsigned-byte 8) #'floor
)
895 (def-convert 3 (complex double-float
) double-float
#'realpart
)
896 (def-convert 3 (complex double-float
) double-float
#'abs
)
897 (def-convert 3 (complex double-float
) double-float
#'phase
)
898 (def-convert 3 (complex double-float
) (unsigned-byte 8)
899 #'(lambda (z) (floor (realpart z
)))
901 (def-convert 3 (complex double-float
) (unsigned-byte 8)
902 #'(lambda (z) (floor (phase z
)))
904 (def-convert 3 (complex double-float
) (unsigned-byte 8)
905 #'(lambda (z) (floor (abs z
)))
908 (def-convert 2 (unsigned-byte 8) (complex double-float
)
909 #'(lambda (c) (complex (* 1d0 c
))) complex
)
910 (def-convert 2 double-float
(complex double-float
)
911 #'(lambda (d) (complex d
)) complex
)
912 (def-convert 2 double-float
(unsigned-byte 8) #'floor
)
913 (def-convert 2 (complex double-float
) double-float
#'realpart
)
914 (def-convert 2 (complex double-float
) double-float
#'abs
)
915 (def-convert 2 (complex double-float
) double-float
#'phase
)
916 (def-convert 2 (complex double-float
) (unsigned-byte 8)
917 #'(lambda (z) (floor (realpart z
)))
919 (def-convert 2 (complex double-float
) (unsigned-byte 8)
920 #'(lambda (z) (floor (phase z
)))
922 (def-convert 2 (complex double-float
) (unsigned-byte 8)
923 #'(lambda (z) (floor (abs z
)))
928 (convert3-cdf/ub8-realpart
929 (make-array (list 3 3 3) :element-type
'(complex double-float
)))
931 ;; will have a name like normalize3-cdf/ub8-abs
932 (defmacro def-normalize-cdf
(dim function
)
933 `(defun ,(intern (format nil
"NORMALIZE~d-CDF/UB8-~a" dim function
)) (a)
934 (declare ((simple-array (complex double-float
) ,dim
) a
)
935 (values (simple-array (unsigned-byte 8) ,dim
) &optional
))
936 (let* ((res (make-array (array-dimensions a
)
937 :element-type
'(unsigned-byte 8)))
938 (res1 (sb-ext:array-storage-vector res
))
939 (b (,(intern (format nil
"CONVERT~d-CDF/DF-~a" dim function
)) a
))
940 (b1 (sb-ext:array-storage-vector b
))
941 (ma (reduce #'max b1
))
942 (mi (reduce #'min b1
))
945 (/ 255d0
(- ma mi
)))))
946 (dotimes (i (length b1
))
948 (floor (* s
(- (aref b1 i
) mi
)))))
951 (def-normalize-cdf 3 abs
)
952 (def-normalize-cdf 3 realpart
)
953 (def-normalize-cdf 3 phase
)
955 (def-normalize-cdf 2 abs
)
956 (def-normalize-cdf 2 realpart
)
957 (def-normalize-cdf 2 phase
)
960 (defmacro def-normalize-df
(dim function
)
961 `(defun ,(intern (format nil
"NORMALIZE~d-DF/UB8-~a" dim function
)) (a)
962 (declare ((simple-array double-float
,dim
) a
)
963 (values (simple-array (unsigned-byte 8) ,dim
) &optional
))
964 (let* ((res (make-array (array-dimensions a
)
965 :element-type
'(unsigned-byte 8)))
966 (res1 (sb-ext:array-storage-vector res
))
967 (b1 (sb-ext:array-storage-vector a
))
968 (ma (reduce #'max b1
))
969 (mi (reduce #'min b1
))
972 (/ 255d0
(- ma mi
)))))
973 (dotimes (i (length b1
))
975 (floor (* s
(- (aref b1 i
) mi
)))))
978 (def-normalize-df 3 floor
)
979 (def-normalize-df 2 floor
)
981 (defun normalize-ub8 (a)
982 (declare ((simple-array * *) a
)
983 (values (simple-array (unsigned-byte 8) *) &optional
))
985 ((simple-array (complex double-float
) 2) (normalize2-cdf/ub8-realpart a
))
986 ((simple-array (complex double-float
) 3) (normalize3-cdf/ub8-realpart a
))
987 ((simple-array double-float
2) (normalize2-df/ub8-floor a
))
988 ((simple-array double-float
3) (normalize3-df/ub8-floor a
))))
991 (let ((a (make-array (list 3 4 5)
992 :element-type
'(complex double-float
))))
993 (setf (aref a
1 1 1) (complex 1d0
1d0
))
994 (normalize3-cdf/ub8 a
))
996 #+nil
;; find the names of all the functions that were defined by the
997 ;; above macros, for exporting
999 (with-package-iterator (next-symbol *package
* :internal
)
1000 (loop (multiple-value-bind (more? symbol
)
1005 (loop for s in
(delete-if-not #'(lambda (x)
1006 (let* ((pat #+nil
"CONVERT"
1009 (lpat (length pat
)))
1010 (when (< lpat
(length x
))
1014 (mapcar #'(lambda (x)
1015 (format nil
"~a" x
)) res
))
1016 do
(format t
"#:~a~%" (string-downcase s
))))
1019 (defun decimate-xy-ub8 (dx vol
)
1020 "Increase transversal sampling distance by odd integer factor DX."
1021 (declare (fixnum dx
)
1022 ((simple-array (unsigned-byte 8) 3) vol
)
1023 (values (simple-array (unsigned-byte 8) 3) &optional
))
1024 (unless (eq (mod dx
2) 1)
1025 (error "Factor DX has to be odd."))
1026 (destructuring-bind (z y x
)
1027 (array-dimensions vol
)
1028 (let* ((dx2 (* dx dx
))
1031 (result (make-array (list z ny nx
)
1032 :element-type
'(unsigned-byte 8))))
1033 (do-box (k j i
0 z
0 ny
0 nx
)
1035 (do-rectangle (jj ii
0 dx
0 dx
)
1040 (setf (aref result k j i
) (floor sum dx2
))))
1043 ;; 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3
1050 ;; output size floor(n,dx)=4
1051 ;; position of q: ii=3, i=0: dx*i+ii=5*0+3=3
1052 ;; position of o: ii=1, i=1: dx*i+ii=5+1=6
1054 (defun count-non-zero-ub8 (vol)
1055 (declare ((simple-array (unsigned-byte 8) 3) vol
)
1056 (values fixnum
&optional
))
1058 (vol1 (sb-ext:array-storage-vector vol
)))
1059 (dotimes (i (length vol1
))
1060 (when (< 0 (aref vol1 i
))