生産技術者サラリーマンの日々

社畜サラリーマンが生産技術やお金の悩みを徒然と書くブログです。私の備忘録が共有できるとうれしいです

【PYTHON+OPENCV】回転不変位相限定相関法(RIPOC)を実装する

目次

1.やりたいこと

2つの画像間で特徴点を抽出して、その差分から誤差が最小になるように画像を幾何学的(回転、平行)変換から2つの画像間の式を求めたい。この式が精度良く求めることができると、カメラのキャリブレーション、時空間フレームの処理、ステレオカメラなどの視差画像など画像間の「照合」や「位置合わせ」に応用できる。

これら、「照合」や「位置合わせ」(画像1の画像座標Xが画像2の画像座標X"と対応していることを求めること)の方法として、いろいろなアルゴリズムがあるが、今回は回転不変位相限定相関法について実装してみた。

2.RIPOCとは

回転不変位相限定相関 (RIPOC)は位相限定相関 (POC)の応用の一つであり、登録画像に対して回転している入力画像に対しても相関をとることができ、相関結果から回転角度を推定することができるという特徴を持っているとのことです。

https://www.jstage.jst.go.jp/article/itetr/22.45/0/22.45_55/_article/-char/ja/www.jstage.jst.go.jp

qiita.com

理論は、下記が参考になるかと思います。私には数式の難易度が高くて
ついていけないなかったです。

東北大学 青木研究室様が位相限定相関法で有名のようです。

https://www.jstage.jst.go.jp/article/itej/63/7/63_7_935/_pdf/-char/ja

3.実装

実装にあたっては以下のサイト様を参考にしました。

csharpmagazine.hatenablog.com

import cv2
import numpy as np

#回転角度を算出する関数
def CalcDeg(dy, len):
	deg = dy / len * 360
	return deg

#回転不変位相限定相関法
def Ripoc():
        #画像の読み込み
	im1 = cv2.imread("Lenna.jpg",0)
	im2 = cv2.imread("Lenna90.jpg",0)
  #画像サイズの取得
	cy,cx = im1.shape
  #窓関数の生成
        win = cv2.createHanningWindow((cx,cy), cv2.CV_64F)
  #入力画像1,2に窓関数をかける
  wim1 = im1 * win	
	wim2 = im2 * win
  #極座標変換
	im1p = cv2.linearPolar(wim1, ((cx/2.0,cy/2.0)), r, cv2.WARP_FILL_OUTLIERS)
	im2p = cv2.linearPolar(wim2, ((cx/2.0,cy/2.0)), r, cv2.WARP_FILL_OUTLIERS)
  #32Bit画像に変換
	im11 = np.float32(im1p)
	im12 = np.float32(im2p)
  #位相限定相関法によるマッチング
	xy, match = cv2.phaseCorrelate(im11,im12)
	#得られた結果から、画像1と画像2間の角度を取得
	scalar, r = xy
	deg = CalcDeg(r, cy)
	return deg

4.処理結果

実行結果は、以下の通りです。
入力画像1のオリジナルの画像に対して、90度回転させた画像を入力画像2とした2つを用意し、下記のプログラムを実行し回転角度を計測した結果、ほとんど誤差がない結果が出ました。

但し、これはオリジナルの画像とオリジナルの画像を90度回転させたものである。入力画像2を別の画像でとった場合、その他の回転方向の誤差により、誤差が多くなるかもしれません。

>>> import ripoc as r
>>> deg = r.Ripoc()
>>> deg
-89.78454078999397

【入力画像 0度】
入力画像
【入力画像 90度】
入力画像90度
極座標変換 0度】
極座標変換画像 0度
極座標変換 90度】
極座標変換画像 90度


inusan0424.hatenablog.com
inusan0424.hatenablog.com

https://blog.hatena.ne.jp/inusan0424/inusan0424.hatenablog.com/config/design/detail