ぱたへね

はてなダイアリーはrustの色分けができないのでこっちに来た

Gauche-CVで投影変換Hを求める

投影変換Hを求めるのに必要な条件の続き。
つまり4つの点の対応が分かれば、投影変換を表す行列Hは計算できます。

この図のような変換を使って実験してみます。(変換は青→黄)
座標の対応はこのようになります。

xi x'i
(5,5) (20,15)
(15,5) (25,20)
(15,15) (25,25)
(5,15) (15,20)

この4点の対応を引数にcv-get-perspective-transformを呼ぶと、投影変換を表すHが計算できます。

(use srfi-1)
(use cv)

(require "../proj2d/proj2d")
(import proj2d)
(load "../cvutil/cvutil.scm")

;; 変換元の4角形
(define src-rect '((5 5) (15 5) (15 15) (5 15)))

;; 行列Hの計算
(define pts-src (map (lambda (p) (make-cv-point-2d32f (first p) (second p))) src-rect))
(define pts-dst (map (lambda (p) (make-cv-point-2d32f (first p) (second p))) '((20 15) (25 20) (25 25) (15 20))))
(define H (make-cv-mat 3 3 CV_32F)) 
(cv-get-perspective-transform pts-src pts-dst H)

;; 結果の確認と表示
(format #t "Projective matrix H~%") 
(print-2d-matrix H)

(define display-transform
  (lambda (H)
    (lambda (x)
      (let ((xh (make-hm-point-2d (first x) (second x))))
        (let ((xdash (transform H xh)))
          (format #t "~A -> ~A~%" x xdash))))))
(map (display-transform H) src-rect)

計算した行列Hの中身はこうなります。
[ [ 1.75 -1.25 17.5 ] [ 1.5 -0.5 10.0 ] [ 0.05000000074505806 -0.05000000074505806 1.0 ]]

この投影変換Hを使って、もとの点を変換してみると、全ての点が正しく変換されていることがわかります。
(5 5) -> (20.0, 15.0)
(15 5) -> (25.0, 20.0)
(15 15) -> (25.0, 25.0)
(5 15) -> (15.0, 20.0)

ソースはこちら
https://github.com/natsutan/computervision/blob/master/mvg/chap4/perspective-transform.scm