勉強しないとな~blog

ちゃんと勉強せねば…な電気設計エンジニアです。

OpenCVやってみる-4. 射影変換

今回は、画像の射影変換をやってみたいと思います。

射影変換

春のパン祭り得点集計では、射影変換が活用できそうなのでやってみます。
射影変換が何をやっているかは前に勉強していたのですが、完全に忘れた…

また復習して記事にします。

ひとまず、ある視点から見た画像を、別の視点から見た画像に変換する、というものです。
シール台紙を撮影するとき、多少斜めからの撮影になるので、これを正面からの画像に変換します。

OpenCVチュートリアルの以下を参照。

画像の幾何変換 — OpenCV-Python Tutorials 1 documentation

以下の画像を使いました。

>>> img1 = cv2.imread('harupan_210402_1.jpg')
>>> img2 = cv2.imread('harupan_210402_2.jpg')
>>> h,w = img1.shape[:2]
>>> img1 = cv2.resize(img1, (int(w/10), int(h/10)), interpolation=cv2.INTER_AREA)
>>> img2 = cv2.resize(img2, (int(w/10), int(h/10)), interpolation=cv2.INTER_AREA)
>>> cv2.imshow('image1', img1)
>>> cv2.waitKey(0)
13
>>> cv2.destroyAllWindows()
>>> cv2.imshow('image2', img2)
>>> cv2.waitKey(0)
13

f:id:nokixa:20210410222841p:plain

f:id:nokixa:20210410222932p:plain

射影変換で正面から見た画像に変換したいと思いますが、それには

  • 元画像での4点の座標
  • この4つの点の変換先座標

を指定する必要があります。
元画像の点としてシール台紙の4つの角を指定、変換先の座標としては長方形の4点を指定します。

元画像でのシール台紙の角は、手動で探します。ImageJを使いました。カーソルを当てた位置の座標を表示してくれます。
最終的には自動検出するようにしたい。

ImageJ

f:id:nokixa:20210410234332p:plain

1枚目 : (774,702), (444,3222), (2664,3282), (2394,762)

2枚目 : (978,978), (570,2934), (2190,3138), (2304,918)

※元画像はいずれも横3024pixel、縦4032pixelです。
縦横1/10にした画像で変換を行います。

長方形の4点を指定するためには縦横比が必要なので、実際に測ります。
16.0cm x 11.0cmでした。

正しく射影変換するためには、画像に既知の形状の物体が映っていないとだめということですね。

変換実施

射影変換やってみました。
変換先画像は、320×220の解像度にしました。

>>> import numpy as np
>>> 
>>> pts1_org = np.float32([[77,70],[44,322],[266,328],[239,76]])
>>> pts1_dst = np.float32(([[0,0],[0,160],[110,160],[110,0]]))
>>> M = cv2.getPerspectiveTransform(pts1_org, pts1_dst*2)
>>> img1_dst = cv2.warpPerspective(img1,M,(110*2,160*2))
>>> cv2.imshow('image1_dst', img1_dst)
>>> cv2.waitKey(0)
13
>>> cv2.destroyAllWindows()
>>> pts2_org = np.float32([[98,98],[57,293],[219,314],[230,92]])
>>> pts2_dst = np.float32(([[0,0],[0,160],[110,160],[110,0]]))
>>> M = cv2.getPerspectiveTransform(pts2_org, pts2_dst*2)
>>> img2_dst = cv2.warpPerspective(img2,M,(110*2,160*2))
>>> cv2.imshow('image2_dst', img2_dst)
>>> cv2.waitKey(0)

f:id:nokixa:20210410235510p:plain

f:id:nokixa:20210411000028p:plain

  • およそそれらしく変換できたかと。お手軽ですね。
  • シール台紙の角が少しめくれあがっていて、変換結果が引き伸ばされたようなちょっと微妙な感じに。
  • とは言えシール点数計算には十分な結果では?

ここまで

フィルタ処理をやろうと考えていましたが、OpenCVチュートリアルを見ると先に「幾何変換」の内容が来ていて、今回射影変換をやりました。

チュートリアルを見ると、次は「画像の閾値処理」だったので、これをやってみようと思います。