前のチュートリアルでは、OpenCVのズーム、回転、および平行移動について説明しましたが、これらは基本的に単純な幾何学的変換です。今回は、もう少し複雑な幾何学的変換について説明します。
画像反転
固定APIを使用したり、操作にnumpyを使用したりするなど、画像を反転させる方法はたくさんあります。
フリップ機能を使用してフリップを実現する
関数プロトタイプ:
flip(src、flipCode [、dst])-> dst
・Src入力画像
・FlipCodeフリップコード
・1水平方向に反転(画像の2番目の次元は列です)
・0垂直方向に反転*垂直方向*(画像の最初の次元は行です)
・-1水平および垂直に水平および垂直に同時に反転
コードを見てみましょう:
view plaincopy to clipboardprint?
import numpy as np
import cv2
from matplotlib import pyplot as plt
img = cv2.imread('cat.jpg')
def bgr2rbg(img):
'''
将颜色空间从BGR转换为RBG
'''
return img[:,:,::-1]
水平反転
flip_h = cv2.flip(img、1)
上下に反転
flip_v = cv2.flip(img、0)
水平方向と垂直方向を同時に反転
flip_hv = cv2.flip(img, -1)
plt.subplot(221)
plt.title('SRC')
plt.imshow(bgr2rbg(img))
plt.subplot(222)
plt.title('Horizontally')
plt.imshow(bgr2rbg(flip_h))
plt.subplot(223)
plt.title('Vertically')
plt.imshow(bgr2rbg(flip_v))
plt.subplot(224)
plt.title('Horizontally & Vertically')
plt.imshow(bgr2rbg(flip_hv))
plt.show()
このコードは、水平反転、垂直反転、水平反転と垂直反転の3つの反転モードを実装しています。効果を見てみましょう:
画像の反転にnumpyインデックスを使用します
OpenCV APIを使用して画像の反転操作を実行しました。実際、numpyのみを使用するのが非常に便利です。numpyでは、img [:、::-1]を使用すると、マトリックスが水平方向に反転します。img[::-を使用します1]は行列の垂直反転なので、水平および垂直反転が同時にimg [::-1、::-1]であることを確認することは難しくありません。
コードを見てみましょう:
view plaincopy to clipboardprint?
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('cat.jpg')
height,width,channel = img.shape
水平反転
flip_h = img [:、::-1]
上下に反転
flip_v = img [::-1]
上下左右反転
flip_hv = img [::-1、::-1]
def bgr2rbg(img):
'''
将颜色空间从BGR转换为RBG
'''
return img[:,:,::-1]
plt.subplot(221)
plt.title('SRC')
plt.imshow(bgr2rbg(img))
plt.subplot(222)
plt.title('Horizontally')
plt.imshow(bgr2rbg(flip_h))
plt.subplot(223)
plt.title('Vertically')
plt.imshow(bgr2rbg(flip_v))
plt.subplot(224)
plt.title('Horizontally & Vertically')
plt.imshow(bgr2rbg(flip_hv))
plt.show()
効果は同じです:
wrapAffineを使用してフリップを実現する
実際、OpenCVのwrapAffineを使用して画像を反転することもできます。前のセクションのチュートリアルでは、関連する関数を使用して回転操作と平行移動操作を実現する方法を説明しました。基本的に、それらの原理は基本的に同じです。フリップを実現するためにそれを使用する原理を見てみましょう:
幅は画像の幅を表し、高さは画像の高さを表すと想定します。
水平方向に反転した変換行列は次のとおりです。
垂直反転変換行列は次のとおりです。
水平方向と垂直方向の反転を同時に実行する場合、次のようになります。
これに基づいて、実装されたコードを確認します。
view plaincopy to clipboardprint?
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('cat.jpg')
height,width,channel = img.shape
水平翻转
M1 = np.float32([[-1, 0, width], [0, 1, 0]])
flip_h = cv2.warpAffine(img, M1, (width, height))
垂直翻转
M2 = np.float32([[1, 0, 0], [0, -1, height]])
flip_v = cv2.warpAffine(img, M2, (width, height))
水平垂直同时翻转
M3 = np.float32([[-1, 0, width], [0, -1, height]])
flip_hv = cv2.warpAffine(img, M3, (width, height))
def bgr2rbg(img):
'''
将颜色空间从BGR转换为RBG
'''
return img[:,:,::-1]
plt.subplot(221)
plt.title('SRC')
plt.imshow(bgr2rbg(img))
plt.subplot(222)
plt.title('Horizontally')
plt.imshow(bgr2rbg(flip_h))
plt.subplot(223)
plt.title('Vertically')
plt.imshow(bgr2rbg(flip_v))
plt.subplot(224)
plt.title('Horizontally & Vertically')
plt.imshow(bgr2rbg(flip_hv))
plt.show()
実験的な効果は前の2つの方法と同じなので、ここではそれらを1つずつ示しません。
アフィン変換
実際、前に説明したズーム、回転、平行移動、フリップは、本質的に画像のアフィン変換ですが、ここでは、アフィン変換の要約である関数について説明します。
M = cv2.GetAffineTransform(src、dst)
src:元の画像の3つの点
の座標dst:変換後の3つの点に対応する座標
M:3つの対応する点から得られたアフィン変換行列
前の原則の説明では、アフィン変換は通常2 * 3行列に対するものであることも知っています。
2次元ベクトルの行列AとBを使用したい場合は、
変換が行われるため、次の形式で表すことができます。
ここで、コードを大まかに見てみましょう。
view plaincopy to clipboardprint?
import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np
img = cv.imread('cat.jpg')
rows,cols,ch = img.shape
pts1 = np.float32([[50,50],[200,50],[50,200]])
pts2 = np.float32([[10,100],[200,50],[100,250]])
M = cv.getAffineTransform(pts1,pts2)
dst = cv.warpAffine(img,M,(cols,rows))
plt.subplot(121),plt.imshow(img),plt.title('Input')
plt.subplot(122),plt.imshow(dst),plt.title('Output')
plt.show()
歪んだ猫が見えます。
透視変換
私たちは通常、Scan Allmightyなどのさまざまなスキャンソフトウェアを使用する場合があります。写真が斜めに撮影された場合でも、ソフトウェアは後の段階で写真を修正できることがわかります。画像補正処理を実行するために、この画像補正操作は実際には画像の透視変換です(キーワードマスキング、誰もが自分で理解しています)。ナンバープレートの認識、解答用紙の判定、テキストの認識など、現在の多くのケースはすべて、次のステップに進む前に、画像の透視変換によってすべて修正されます。
アフィン変換の概要では、アフィン変換AffineTransformについて説明しました。それでは、透視変換とアフィン変換の最大の違いは何ですか?アフィン変換では3つの点を使用して変換を決定できますが、透視変換は必ずしも必要ではないため、アフィン変換は射影変換の特殊なケースとして使用できます。透視変換を決定するには、4つのポイントが必要です。
OpenCVには、画像の透視変換を実現するwarpPerspective()関数が用意されています。台形の4つの頂点の座標とターゲットキャンバスの4つの角の座標を入力するだけで、変換が自動的に完了します。コアコードは2行しかありません。最初に2つの座標配列を読み取り、変換行列を計算してから、変換行列に従って元の画像に対して透視変換を実行し、ターゲットキャンバスに出力します。
関数プロトタイプ:
cv2.getPerspectiveTransform(src、dst)→retval
src:ソース画像で測定される長方形の4点座標
sdt:ターゲットイメージ内の長方形の4点の座標
ソース画像の長方形からターゲット画像の長方形に変換された行列を返し、次の関数を導きます:
cv2.warpPerspective(src、M、dsize [、dst [、flags [、borderMode [、borderValue]]]])→dst
src:入力画像
M:変換行列
dsize:ターゲット画像の形状
フラグ:補間方法、補間方法INTER_LINEARまたはINTER_NEAREST
borderMode:ボーダー補正モード、BORDER_CONSTANTまたはBORDER_REPLICATE
borderValue:ボーダー補正サイズ、定数値、デフォルトは0
または、別の関数を使用することもできます。
cv2.perspectiveTransform(src、m [、dst])→dst
src:2チャンネルまたは3チャンネルの画像を入力
m:変換行列
これら2つの関数は、同じ仕様の画像を返します。
透視変換では、3x3変換行列が必要です。変換後も直線は直線のままです。この変換行列を見つけるには、入力画像に4つの点があり、対応する点が出力画像に必要です。これらの4点のうち、3点が同一線上にあるべきではありません。次に、関数cv.getPerspectiveTransformを使用して変換行列を見つけることができます。次に、この3x3変換マトリックスにcv.warpPerspectiveを適用します。コードを見てみましょう。
view plaincopy to clipboardprint?
import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np
img = cv.imread('sudoku.png')
rows,cols,ch = img.shape
pts1 = np.float32([[56,65],[368,52],[28,387],[389,390]])
pts2 = np.float32([[0,0],[300,0],[0,300],[300,300]])
M = cv.getPerspectiveTransform(pts1,pts2)
dst = cv.warpPerspective(img,M,(300,300))
plt.subplot(121),plt.imshow(img),plt.title('Input')
plt.subplot(122),plt.imshow(dst),plt.title('Output')
plt.show()
画像が与えられた座標に対して修正されていることがわかります。これは、後続の形態学的操作に非常に便利です。
記事の概要ページを確認してくださいhttps://blog.csdn.net/weixin_44237705/article/details/107864965
openvinoの技術情報はグループで交換できます〜