第 5 章 - 幾何学的変換

幾何学的変換は、ある画像を別の画像にマッピングする操作です。OpenCV は、いくつかのマッピング関連関数を提供します。

さまざまな OpenCV 関数に従って、マッピング関係はスケーリング、反転、アフィン変換、パースペクティブ、リマッピングなどに分類できます。

ワン.ズーム:

OpenCV では、 cv2.resize() を使用して画像を拡大縮小します。

  • dst = cv2.resize(src, dsize, [, fx [, fy [, interpolation]]])

    • dst: 出力対象の画像を表します。画像の種類は src と同じで、そのサイズは dsize (値が 0 以外の場合)、または src.size()、fx、fy によって計算できます。
    • src: スケーリングする必要がある元の画像を表します。
    • dsize: 出力画像サイズを表します。
    • fx: 水平方向のズーム率を表します。
    • fy: 垂直方向の拡大縮小率を表します。
    • interpolation: 次の表に示すように、補間方法を表します。

    画像-20211011194455301

    画像-20211011194626571

cv2.resize() 関数では、ターゲット画像のサイズは、次のように「パラメータ dsize」または「パラメータ fx および fy」のいずれかによって決定できます。

  1. パラメータ dsize で指定します。

    パラメータ dsize の値が指定されている場合、パラメータ fx と fy の値が指定されているかどうかに関係なく、ターゲット画像のサイズはパラメータ dsize によって決まります。
    この時点で、dsize の最初のパラメータはズームされた画像の幅 (幅、つまりパラメータ fx に関連する列の数) に対応し、2 番目のパラメータは画像の高さに対応することに注意してください。ズームされた画像 (高さ、つまりパラメーター fy に関連する行数 rows )。

    パラメータ dsize の値を指定した場合、x 方向のズーム サイズ (パラメータ fx) は次のようになります。

    • (double)dsize.width/src.cols

    同時に、y 方向のズーム サイズ (パラメーター fy) は次のようになります。

    • (double)dsize.height/src.rows
  2. パラメータ fx および fy で指定:
    パラメータ dsize の値が None の場合、ターゲット イメージのサイズはパラメータ fx および fy によって決定されます。この時点で、ターゲット画像のサイズは次のようになります。 dsize=Size(round(fx * src.cols),round(fy * src.rows))

補間:

補間とは、画像に対して幾何学的な処理を行う際に、マッピングでは直接得られない値をピクセルに割り当てることを指します。たとえば、画像を元のサイズの 2 倍に拡大すると、直接マッピングできないピクセルが必然的に増えますが、これらのピクセルについては、補間方法によってその値が決定されます。さらに、いくつかの非整数のマッピング値も存在します。たとえば、逆マッピングでは、ターゲット画像のピクセル値を、元の画像の非整数値に対応する位置にマッピングする可能性があります。このような非整数の位置がある場合、つまり、ターゲット画像上のピクセルが元の画像上の特定の位置に対応できない場合は、この時点で、これらのピクセル点も補間してマッピングを完了する必要があります。

知らせ:

関数 cv2.resize() は、元の画像のズーム機能を実現できます. 操作が開始される前に、操作前のターゲット画像 dst のサイズと種類は、最終的なターゲット画像 dst とは何の関係もないことに注意してください。宛先イメージ dst の最終的なサイズとタイプは、src、dsize、fx、fy によって指定されます。元の画像をターゲット画像と同じサイズにサイズ変更する場合は、上記のプロパティで指定する必要があります。

画像を縮小する場合は、エリア補間法 (INTER_AREA) を使用すると最良の結果が得られ、画像を拡大する場合は、3 次スプライン補間法 (INTER_CUBIC) と双線形補間法 (INTER_LINEAR) を使用すると、より良い結果が得られます。3次スプライン補間法は遅いですが、バイリニア補間法は比較的高速で効果も劣りません。

例:

import cv2

img = cv2.imread('../lena.bmp')
rows, cols = img.shape[:2]
size = (int(cols * 0.9), int(rows * 0.5))
rst = cv2.resize(img, size)
print('img.shape=', img.shape)
print('rst.shape=', rst.shape)
cv2.imshow('img', img)
cv2.imshow('rst', rst)
cv2.waitKey()
cv2.destroyAllWindows()


# 输出结果
img.shape= (512, 512, 3)
rst.shape= (256, 460, 3)

画像-20211011200133472

2. 裏返す:

OpenCVでは画像の反転はcv2.flip()という関数で実現しており、この関数は画像の水平方向の反転、垂直方向の反転、両方向の同時反転を行うことができます。

  • dst = cv2.flip( src, filpCode )

    • dst: 元の画像と同じサイズとタイプのターゲット画像を表します。
    • src: 処理される元の画像を表します。
    • flickCode: 回転タイプを表します。このパラメータの意味を表に示します。

    画像-20211011200633852

この関数では、ターゲット ピクセルとオリジナル ピクセルの関係は次のように表すことができます:
dstij = { srcsrc . rows − i − 1 , j , filc C ode = 0 srci , src .cols − j − 1 , filc C ode > 0 srcsrc . rows − i − 1 , src .cols − j − 1 , filc コード < 0 dst_{ij} = \begin{cases} src_{src.rows-i-1, \quad j}, \quad filcCode = 0 \\ src_{i, \quad src.cols-j-1}, \quad filcCode > 0 \\ src_{src.rows-i-1, \quad src.cols-j-1}, \quad flcCode < 0 \end{ケース}d s t=s r cs r c s i 1 _ _jフィルコード_ _ _ _ _ _=0s r cs r c c o l s j 1フィルコード_ _ _ _ _ _>0s r cs r c s i 1 _ _s r c c o l s j 1フィルコード_ _ _ _ _ _<0

このうち、dst が注目画素、src が元の画素です。

例:

import cv2

img = cv2.imread('../lena.bmp')
x = cv2.flip(img, 0)
y = cv2.flip(img, 1)
xy = cv2.flip(img, -1)
cv2.imshow('img', img)
cv2.imshow('x', x)
cv2.imshow('y', y)
cv2.imshow('xy', xy)
cv2.waitKey()
cv2.destroyAllWindows()

画像-20211011201407030

3. アフィン:

アフィン変換とは、一連の幾何学的変換を通じて画像の移動、回転、その他の操作を実行できることを意味しますこの変換により、画像の直線性と平行性が維持されます。直線性とは、画像がアフィン変換を受けた後も直線であることを意味し、平行線とは、画像がアフィン変換された後も平行であることを意味します。

OpenCV に実装されているアフィン関数は cv2.warpAffine() で、変換行列 (マッピング行列) M による変換を実装します。具体的には、dst ( x , y ) = src ( M 11 x + M 12 y + M 13 , M 13) x + M 22 y + M 23 ) dst(x, y) = src(M_{11}x + M_{12}y + M_{13}, M_{13}x + M_{22}y + M_{23 } )d s t ( x ,y )=s r c ( M1 1バツ+M1 2y+M1 3M1 3バツ+M2 2y+M2 3

図に示すように、元の画像 O は、変換行列 M によってアフィン画像 R に変換できます。

画像-20211011203322157

したがって、アフィン関数 cv2.warpAffine() を使用して、画像の移動や回転などの操作を実装できます。

  • dst = cv2.warpAffine( src, M, dsize [, flags [, borderMode [, borderValue ]]])
    • dst: アフィン後の出力画像を表し、画像の種類は元の画像と同じです。dsize は出力イメージの実際のサイズを決定します。
    • src: アフィン対象となる元の画像を表します。
    • M:2×3の変換行列を表す。異なる変換行列を使用すると、異なるアフィン変換を実現できます。
    • dsize: 出力画像のサイズを表します。
    • flags: 補間方法を表します。デフォルトは INTER_LINEAR です。値がWARP_INVERSE_MAPの場合、Mが対象画像dstから原画像srcへの逆変換を実現する逆変換タイプであることを意味する。
    • borderMode: エッジのタイプを表します。デフォルトは BORDER_CONSTANT です。値が BORDER_TRANSPARENT の場合、ターゲット画像の値が変更されていないことを意味し、これらの値は元の画像の外れ値に対応します。
    • borderValue: 境界値を表します。デフォルトは 0 です。

上記の分析を通じて、OpenCV でアフィン変換を実現するために関数 cv2.warpAffine() が使用されており、そのオプションのパラメーターを無視した後の構文形式は次のとおりであることがわかります。

  • dst=cv2.warpAffine(src ,M ,dsize)

変換行列 M を介して、元のイメージ src をターゲット イメージ dst に変換します。

  • dst ( x , y ) = src ( M 11 x + M 12 y + M 13 , M 13 x + M 22 y + M 23 ) dst(x, y) = src(M_{11}x + M_{12} y + M_{13}、M_{13}x + M_{22}y + M_{23} )d s t ( x ,y )=s r c ( M1 1バツ+M1 2y+M1 3M1 3バツ+M2 2y+M2 3

したがって、どのような形式のアフィン変換が実行されるかは、変換行列 M に完全に依存します異なる変換行列 M を通じて実現される異なるアフィン変換を以下にそれぞれ紹介します。

1. パンニング:

変換行列 M を使用して、元のイメージ src をターゲット行列 dst に変換します。

  • dst ( x , y ) = src ( M 11 x + M 12 y + M 13 , M 13 x + M 22 y + M 23 ) dst(x, y) = src(M_{11}x + M_{12} y + M_{13}、M_{13}x + M_{22}y + M_{23} )d s t ( x ,y )=s r c ( M1 1バツ+M1 2y+M1 3M1 3バツ+M2 2y+M2 3

元の画像 src を右に 100 ピクセル、下に 200 ピクセル移動します。対応する関係は次のとおりです。

  • dst(x, y) = src(x + 100, y + 200)

上記の式は不完全です。つまり、次のようになります。

  • dst(x, y) = src( 1 * x + 0 * y + 100, 0 * x + 1 * y + 200)

したがって、反対の飲み物の変換行列 M の各要素の値は、最初に次のように決定できます。

  • M 11 = 1 、 M 12 = 0 、 M 13 = 100 、 M 21 = 0 、 M 22 = 1 、 M 23 = 200 M_{11} = 1、 \quad M_{12} = 0、 \quad M_{13 } = 100、M_{21} = 0、\quad M_{22} = 1、\quad M_{23} = 200M1 1=1 M1 2=0 M1 3=1 0 0 M2 1=0 M2 2=1 M2 3=2 0 0

変換行列 M:

  • M = [ 1 0 100 0 1 200 ] M = \begin{bmatrix} 1 & 0 & 100 \\ 0 & 1 & 200 \end{bmatrix}M=[10011 0 02 0 0
import cv2
import numpy as np

img = cv2.imread('../lena.bmp')
h, w = img.shape[:2]
x = 100
y = 200
M = np.float32([[1, 0, x], [0, 1, y]])
move = cv2.warpAffine(img, M, (w, h))
cv2.imshow('img', img)
cv2.imshow('move', move)
cv2.waitKey()
cv2.destroyAllWindows()

画像-20211011205331763

2. 回転します。

OpenCV で関数 cv2.warpAffine() を使用して画像を回転する場合、関数 cv2.getRotationMatrix2D() を通じて変換行列を取得できます。この関数の構文は次のとおりです。

  • retval = cv2.getRotationMatrix2D(中心, 角度, スケール)
    • center: 回転の中心点
    • angle: 回転角度。正の数値は反時計回りの回転を意味し、負の数値は時計回りの回転を意味します。
    • スケール: 変換スケール (ズーム サイズ)

使用する変換行列 M は、関数 cv2.getRotationMatrix2D() を使用して直接生成できます例えば、画像の中心を原点として反時計回りに45度回転し、対象の画像を元の画像の0.6倍に縮小したい場合、関数cv2.getRotationMatrix2D()を呼び出して変換行列Mを生成する際の文は次のようになります。は:

  • M = cv2.getRotationMatrix2D( ( 高さ/2, 幅/2 ), 45, 0.6 )

例: 上記の要件に基づく画像の回転

import cv2

lena = cv2.imread('../lena.bmp')
h, w = lena.shape[:2]
M = cv2.getRotationMatrix2D((h / 2, w / 2), 45, 0.6)
rotate = cv2.warpAffine(lena, M, (w, h))
cv2.imshow('lena', lena)
cv2.imshow('rotate', rotate)
cv2.waitKey()
cv2.destroyAllWindows()

画像-20211012120510166

3. より複雑なアフィン変換:

上で述べたように、平行移動と回転のアフィン変換はどちらも比較的単純ですが、より複雑なアフィン変換の場合、OpenCV はアフィン関数 cv2.warpAffine() で必要な変換行列 M を生成する関数 cv2.getAffineTransFORM() を提供します。この関数の構文は次のとおりです。

  • retval = cv2.getAffineTransform(src, dst)

式では次のようになります。

  • src: 入力画像の3点の座標を表します
  • dst: 出力画像の 3 点の座標を表します

この関数では、パラメータ値 src と dst は 3 つの 2 次元配列 (x, y) 点を含む配列です。上記のパラメーターは、関数 cv2.getAffineTransform() を通じて 2 つの平行四辺形を定義します。src と dst の 3 点は、それぞれ、平行四辺形の左上隅、右上隅、左下隅の 3 点に対応します。関数 cv2.getAffineTransform() が指定された点のマッピングを完了した後、他のすべての点のマッピング関係が計算され、指定された点の関係に従って決定されます。関数 cv2.warpAffine() は、関数 cv2.getAffineTransform() で取得した変換行列 M をパラメータとして受け取り、src 内の点を dst にアフィンします。

例:

import cv2
import numpy as np

img = cv2.imread('../lena.bmp')
rows, cols, ch = img.shape
p1 = np.float32([[0, 0], [cols - 1, 0], [0, rows - 1]])
p2 = np.float32([[0, rows * 0.33], [cols * 0.85, rows * 0.25], [cols * 0.15, rows * 0.7]])
M = cv2.getAffineTransform(p1, p2)
dst = cv2.warpAffine(img, M, (cols, rows))
cv2.imshow('img', img)
cv2.imshow('dst', dst)
cv2.waitKey()
cv2.destroyAllWindows()

画像-20211012145205393

  • まず、2 つの 3 要素点セット p1 と p2 が構築されます。これらは、それぞれ元の画像とターゲット画像の平行四辺形の 3 つの頂点 (左上隅、右上隅、左下隅) を参照するために使用されます。 。
  • 次に、M=cv2.getAffineTransform(p1,p2) を使用して変換行列 M を取得します。
  • 次に、 dst=cv2.warpAffine(img,M,(cols,rows)) により、元の画像からターゲット画像へのアフィンが完了します。

4. 視点:

アフィンは長方形を任意の平行四辺形にマッピングでき、透視変換は長方形を任意の四角形にマッピングできます。

遠近変換の関数は cv2.warpPerspective() で、具体的な構文は次のとおりです。

  • dst = cv2.warpPerspective( src, M, dsize [, flags [, borderMode [, borderValue]]])
    • dst: 遠近法処理後の出力画像を表し、元の画像と同じタイプになります。dsize は出力イメージの実際のサイズを決定します。
    • src: 透視する画像を表します。
    • M: 3×3の変換行列を表します。
    • dsize: 出力画像のサイズを表します。
    • flags: 補間方法を表します。デフォルトは INTER_LINEAR です。値がWARP_INVERSE_MAPの場合、Mが対象画像dstから原画像srcへの逆変換を実現できる逆変換タイプであることを意味する。
    • borderMode: エッジのタイプを表します。デフォルトは BORDER_CONSTANT です。値が BORDER_TRANSPARENT の場合、ターゲット画像の値が変更されていないことを意味し、これらの値は元の画像の外れ値に対応します。
    • borderValue: 境界値を表します。デフォルトは 0 です。

アフィン変換と同様に、関数 cv2.warpPerspective() で使用される変換行列を生成するためにも関数が使用されます。関数は cv2.getPerspectiveTransform() で、構文形式は次のとおりです。

  • restval = cv2.getPerspectiveTransform( src, dst )
    • src: 入力画像の 4 つの頂点の座標を表します
    • dst: 出力画像の 4 つの頂点の座標を表します。

src パラメータと dst パラメータは 4 つの点を含む配列であることに注意してください。実際の使用では、必要に応じて、src の 4 点の dst の 4 点へのマッピングを制御できます。

例:

import cv2
import numpy as np

img = cv2.imread('../demo.bmp')
rows, cols = img.shape[:2]
pts1 = np.float32([[150, 50], [400, 50], [60, 450], [310, 450]])
pts2 = np.float32([[50, 50], [rows-50, 50], [50, cols-50], [rows-50, cols-50]])
M = cv2.getPerspectiveTransform(pts1, pts2)
dst = cv2.warpPerspective(img, M, (cols, rows))
cv2.imshow('img', img)
cv2.imshow('dst', dst)
cv2.waitKey()
cv2.destroyAllWindows()

画像-20211012181112996

  • 元画像の平行四辺形の 4 つの頂点 pts1 と、対象画像の長方形の 4 つの頂点 pts2 を指定します。
  • M=cv2.getPerspectiveTransform(pts1,pts2) を使用して、変換行列 M を生成します。
  • 次に、ステートメント dst=cv2.warpPerspective(img,M,(cols,rows)) を使用して、平行四辺形から長方形への変換を完了します。

5. 再マッピング:

ある画像内のピクセルを別の画像内の指定された位置にマッピングするプロセスは、再マッピングと呼ばれます。OpenCV には再マッピングの方法が多数ありますが、カスタムの方法を使用して再マッピングを完了したい場合があります。

OpenCV のリマッピング関数 cv2.remap() は、より便利で自由なマッピング方法を提供します。その構文形式は次のとおりです。

  • dst = cv2.remap( src,map1,map2,interpolation[,borderMode[,borderValue]])

    • dst: ターゲット イメージを表し、src と同じサイズとタイプを持ちます。
    • src: 元の画像を表します。
    • map1: パラメータには 2 つの可能な値があります。
      • (x,y) 点のマップを表します。
      • CV_16SC2、CV_32FC1、CV_32FC2 タイプの (x, y) 点の x 値を示します。
    • map2: パラメーターには 2 つの値も指定できます。
    • map1 が (x,y) を表す場合、値は空になります。
    • map1 が (x, y) 点の x 値を表す場合、この値は CV_16UC1、CV_32FC1 タイプの (x, y) 点の y 値になります。
    • Interpolation: 補間方法を表します。INTER_AREA 方法はここではサポートされていません。
    • borderMode : 境界モードを表します。値が BORDER_TRANSPARENT の場合、ソース画像内の特異点 (外れ値) に対応するピクセルがターゲット画像内で変更されないことを意味します。
    • borderValue: 境界値を表します。デフォルトは 0 です。

1. マッピングパラメータの理解:

**再マッピングでは、ピクセルの位置を変更することで新しい画像を取得します。新しい画像を構築する場合、元の画像内の新しい画像の各ピクセルの位置を決定する必要があります。したがって、マップ関数が行うことは、元の画像内の新しい画像ピクセルがどこにあるかを見つけることです。このプロセスは、新しい画像ピクセルを元の画像にマッピングするプロセスであるため、逆マッピングと呼ばれます。**関数 cv2.remap() では、パラメータ map1 とパラメータ map2 は逆マッピングを示すために使用されます。map1 は座標 x 用、map2 は座標 y 用です。

map1とmap2の値は両方とも浮動小数点数であることに注意してください。したがって、ターゲット イメージを非整数値にマッピングし直すことができます。これは、ターゲット イメージを元のイメージの 2 つのピクセル間の位置 (当然、ピクセル値は存在しません) に「バックマッピング」できることを意味します。このとき、補間を実現するためにさまざまな方法を使用でき、関数内の補間パラメータで補間方法を制御できます。パラメータmap1とパラメータmap2の値が浮動小数点数であるからこそ、関数 cv2.remamp() を通じて実現できるマッピング関係がより任意になり、さまざまな形式のマッピングを実現できます。カスタムマッピングパラメータ。

関数 cv2.remap() のパラメータ map1 はピクセルが配置されている列番号を参照し、パラメータ map2 はピクセルが配置されている行番号を参照していることに注意してください。**たとえば、ターゲット画像 (マッピング結果画像) の点 A を元の画像の 0 行 3 列のピクセル点 B にマッピングする場合、点に対応するパラメータ map1 をマッピングする必要があります。 Aを対応する位置に設定します。 の値は3に設定され、パラメータmap2の対応する位置の値は0に設定されます。**したがって、通常は、わかりやすくするために、map1 を mapx、map2 を mapy と書きます。

同様に、対象画像(マッピング結果画像)内のすべてのピクセルを元画像の0行3列目のピクセルBにマッピングしたい場合は、パラメータmap1の値を次のように設定する必要があります3、設定 パラメータmap2の値を全て0に設定します。

例:

  • 列の指定に使用されるパラメーターmap1 (mapx) の値は 3 です。
  • 行を指定するパラメータmap2(mapy)の値はすべて0です。
import cv2
import numpy as np

img = np.random.randint(0, 256, size=[4, 5], dtype=np.uint8)
# rows, cols = img.shape
mapx = np.ones(img.shape, np.float32) * 3
mapy = np.ones(img.shape, np.float32) * 0
rst = cv2.remap(img, mapx, mapy, cv2.INTER_LINEAR)
print('img=\n', img)
print('mapx=\n', mapx)
print('mapy=\n', mapy)
print('rst=\n', rst)

# 输出结果
img=
 [[196  22  15  82 189]
 [228 208 215  88 113]
 [159   6 157 101 174]
 [181  95 194 206 111]]
mapx=
 [[3. 3. 3. 3. 3.]
 [3. 3. 3. 3. 3.]
 [3. 3. 3. 3. 3.]
 [3. 3. 3. 3. 3.]]
mapy=
 [[0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0.]]
rst=
 [[82 82 82 82 82]
 [82 82 82 82 82]
 [82 82 82 82 82]
 [82 82 82 82 82]]

2. コピー:

リマッピング関数 cv2.remap() の使用方法をよりよく理解するために、この関数を使用してイメージをコピーする方法を以下に説明します。マッピングの際、パラメータは次のように処理されます。

  • 対応する位置のx軸の座標軸にmap1の値を設定します。
  • 対応する位置のy軸の座標軸としてmap2の値を設定します。

飲酒位置のx軸の座標軸としてmap1の値を設定します。

例:

import cv2
import numpy as np

img = cv2.imread('../lena.bmp')
rows, cols = img.shape[:2]
mapx = np.zeros(img.shape[:2], np.float32)
mapy = np.zeros(img.shape[:2], np.float32)
for i in range(rows):
    for j in range(cols):
        mapx.itemset((i, j), j)
        mapy.itemset((i, j), i)
rst = cv2.remap(img, mapx, mapy, cv2.INTER_LINEAR)
cv2.imshow('img', img)
cv2.imshow('rst', rst)
cv2.waitKey()
cv2.destroyAllWindows()

画像-20211012201615601

3. X 軸を中心に回転します。

マッピング プロセス中に X 軸を中心に回転したい場合は、次のようにします。

  • X軸はそのままです
  • y 座標軸の値は、x 軸を対称軸として交換されます。

マップ 1、マップ 2 に反映:

  • map1 の値は変わりません
  • map2 の値は「総行数 - 1 - 現在の行番号」に調整されます。

なお、OpenCVにおける行番号の添字は0から始まるため、対称関係では「現在の行番号+対称行番号=総行数-1」の関係になります。これにより、x軸を反転すると、map2の現在行の行番号が「総行数 - 1 - 現在の行番号」に調整されます。

import cv2
import numpy as np

img = cv2.imread('../lena.bmp')
rows, cols = img.shape[:2]
mapx = np.zeros(img.shape[:2], np.float32)
mapy = np.zeros(img.shape[:2], np.float32)
for i in range(rows):
    for j in range(cols):
        mapx.itemset((i, j), j)
        mapy.itemset((i, j), rows-1-i)
rst = cv2.remap(img, mapx, mapy, cv2.INTER_LINEAR)
cv2.imshow('img', img)
cv2.imshow('rst', rst)
cv2.waitKey()
cv2.destroyAllWindows()

画像-20211012202830164

4. Y 軸を中心に回転します。

マッピング プロセス中に Y 軸を中心に回転したい場合は、次のようにします。

  • y軸はそのままです
  • y 軸を対称軸として、x 座標軸の値が交換されます。

マップ 1、マップ 2 に反映:

  • map2の値は変更されません
  • map1 の値は、「合計列番号 - 1 - 現在の列番号」に調整されます。

なお、OpenCVにおける行番号の添字は0から始まるため、対称関係では「現在の列番号+対称列番号=総列数-1」の関係になります。したがって、y 軸を反転すると、map1 の現在の列の列番号は、「総列数 - 1 - 現在の列番号」に調整されます。

import cv2
import numpy as np

img = cv2.imread('../lena.bmp')
rows, cols = img.shape[:2]
mapx = np.zeros(img.shape[:2], np.float32)
mapy = np.zeros(img.shape[:2], np.float32)
for i in range(rows):
    for j in range(cols):
        mapx.itemset((i, j), cols - j -1)
        mapy.itemset((i, j), i)
rst = cv2.remap(img, mapx, mapy, cv2.INTER_LINEAR)
cv2.imshow('img', img)
cv2.imshow('rst', rst)
cv2.waitKey()
cv2.destroyAllWindows()

画像-20211012203527850

5. X 軸と Y 軸を中心に回転します。

マッピング プロセス中に X 軸と Y 軸を中心に回転したい場合は、次のようにします。

  • y 軸を対称軸として、x 座標軸の値が交換されます。
  • y 座標軸の値は、x 軸を対称軸として交換されます。

マップ 1、マップ 2 に反映:

  • map1 の値は「合計列番号 - 1 - 現在の列番号」に調整されます。
  • map2 の値は「総行数 - 1 - 現在の行番号」に調整されます。
import cv2
import numpy as np

img = cv2.imread('../lena.bmp')
rows, cols = img.shape[:2]
mapx = np.zeros(img.shape[:2], np.float32)
mapy = np.zeros(img.shape[:2], np.float32)
for i in range(rows):
    for j in range(cols):
        mapx.itemset((i, j), cols - j - 1)
        mapy.itemset((i, j), rows - i - 1)
rst = cv2.remap(img, mapx, mapy, cv2.INTER_LINEAR)
cv2.imshow('img', img)
cv2.imshow('rst', rst)
cv2.waitKey()
cv2.destroyAllWindows()

画像-20211012203929485

6. x 軸と y 軸が交換されます。

画像の x 軸と y 軸を交換する場合は、マッピング プロセス中に、任意の点の x 軸と y 軸の座標を交換する必要があることを意味します。Mapx と Mapy に反映:

  • mapx の値は、その行の行番号に合わせて調整されます。
  • mapy の値は、それが含まれる列の列番号に調整されます。

行数と列数が一致しない場合、上記の操作ではマッピングできない値が発生する可能性があることに注意してください。デフォルトでは、マッピングできない値は 0 として扱われます。

import cv2
import numpy as np

img = cv2.imread('../lena.bmp')
rows, cols = img.shape[:2]
mapx = np.zeros(img.shape[:2], np.float32)
mapy = np.zeros(img.shape[:2], np.float32)
for i in range(rows):
    for j in range(cols):
        mapx.itemset((i, j), i)
        mapy.itemset((i, j), j)
rst = cv2.remap(img, mapx, mapy, cv2.INTER_LINEAR)
cv2.imshow('img', img)
cv2.imshow('rst', rst)
cv2.waitKey()
cv2.destroyAllWindows()

画像-20211012204124880

7. 画像のスケーリング:

以前のマッピングはすべて整数の直接マッピングであり、処理がより便利です。より複雑な問題を扱う場合は、行と列の値に対してより複雑な操作を実行する必要があります。

例: cv2.remap() を使用して画像をダウンスケールします。

画像を縮小した後、画像を中心付近の特定の領域に固定できます。たとえば、x 軸と y 軸を次のように設定します。

  • ターゲット イメージの x 軸 (x 軸の長さ 0.25、x 軸の長さ 0.75) 間隔内で縮小イメージを生成します。x 軸の残りの点は、x 軸上の任意の点の値からサンプリングされます。軸。
  • ターゲット画像の y 軸 (0.25 · y 軸の長さ、0.75 · y 軸の長さ) 間隔内で縮小画像を生成します。y 軸の残りの点は、画像上の任意の点の値からサンプリングされます。 y 軸。

処理の都合上、上記領域外の点は(0,0)座標点の値を取ることにします。

import cv2
import numpy as np

img = cv2.imread('../11111.png')
print(img.shape)
rows, cols = img.shape[:2]
mapx = np.zeros(img.shape[:2], np.float32)
mapy = np.zeros(img.shape[:2], np.float32)
for i in range(rows):
    for j in range(cols):
        if 0.25 * cols < j < 0.75 * cols and 0.25 * rows < i < 0.75 * rows:
            mapx.itemset((i, j), 2 * (j - cols * 0.25) + 0.5)
            mapy.itemset((i, j), 2 * (i - rows * 0.25) + 0.5)
        else:
            mapx.itemset((i, j), 0)
            mapy.itemset((i, j), 0)
rst = cv2.remap(img, mapx, mapy, cv2.INTER_LINEAR)
cv2.imshow('img', img)
cv2.imshow('rst', rst)
cv2.waitKey()
cv2.destroyAllWindows()

画像-20211012210140333

おすすめ

転載: blog.csdn.net/weixin_57440207/article/details/122646987