こしあん
2019-02-08

[Python]OpenCVのアフィン変換でAssertion failed

Pocket
LINEで送る


OpenCVのアフィン変換のgetAffineTransformで、起点と終点の行列をちゃんと正しいshapeで指定しているのにもかかわらず「(-215:Assertion failed)」とエラーになってしまいました。かなり難解なエラーだったので、原因を探ってみました。

このコード

アフィン変換を使って画像を歪ませるコードです。

def shear_image_center(base_image, shear_range):
    assert shear_range >= 0.0 and shear_range <= 1.0
    h = base_image.shape[0] // 2
    w = base_image.shape[1] // 2
    randoms = np.random.uniform(1.0-shear_range, 1.0+shear_range, (3,2))
    coefs = np.array([[-1,-1],[1,-1],[1,1]], np.float32)
    centers = np.array([[h,w]], np.float32)
    origin = centers + centers * coefs
    dest = centers + centers * coefs * randoms
    affine_matrix = cv2.getAffineTransform(origin, dest)
    return cv2.warpAffine(base_image, affine_matrix, (base_image.shape[1], base_image.shape[0]))

こんなエラーが出てきます。

    affine_matrix = cv2.getAffineTransform(origin, dest)
cv2.error: OpenCV(3.4.2) C:\Miniconda3\conda-bld\opencv-suite_1534379934306\work
\modules\imgproc\src\imgwarp.cpp:3163: error: (-215:Assertion failed) src.checkV
ector(2, 5) == 3 && dst.checkVector(2, 5) == 3 in function 'cv::getAffineTransfo
rm'

エラー文を読むと、「originとdestの配列の1次元目が3(3点分のxy座標)でないといけない」というような趣旨です。しかし、originとdestのshapeを確認すると、

print(origin.shape) #(3,2)
print(dest.shape) #(3,2)

と、特にshape上は問題がありません。どういうことでしょう?

原因はNumpy配列のfloatの型

実は、getAffineTransformの引数はfloat32でなくてはいけません。このコード

randoms = np.random.uniform(1.0-shear_range, 1.0+shear_range, (3,2))

ここの部分で生成される乱数がnp.float64であるために、destの型が64ビット変数になってしまっていたのです。実際printで型を確認すると、

print(origin.dtype) # float32
print(dest.dtype) # float64

このように2つの型が違います。これに気づいてしまえば解決法は簡単です。destをastypeでfloat32にすればいいのです。

def shear_image_center(base_image, shear_range):
    assert shear_range >= 0.0 and shear_range <= 1.0
    h = base_image.shape[0] // 2
    w = base_image.shape[1] // 2
    randoms = np.random.uniform(1.0-shear_range, 1.0+shear_range, (3,2)).astype(np.float32) #32ビット変数にする
    coefs = np.array([[-1,-1],[1,-1],[1,1]], np.float32)
    centers = np.array([[h,w]], np.float32)
    origin = centers + centers * coefs
    dest = centers + centers * coefs * randoms
    affine_matrix = cv2.getAffineTransform(origin, dest)
    return cv2.warpAffine(base_image, affine_matrix, (base_image.shape[1], base_image.shape[0]))

これで解決しました。もうちょっとコードが長ければ最後にastypeでもいいでしょう。ちなみに、両方np.float64に揃えるとエラーになってしまうので、やはりnp.float32でなくてはいけないのだと思います。

shapeについてのassertion errorなのに、実は問題なのが変数の型というのはちょっとわかりづらいですよね。

Related Posts

PyTorch/TorchVisionで複数の入力をモデルに渡したいケース... PyTorch/TorchVisionで入力が複数あり、それぞれの入力に対して同じ前処理(transforms)をかけるケースを考えます。デフォルトのtransformsは複数対応していないのでうまくいきません。しかし、ラッパークラスを作り、それで前処理をラップするといい感じにできたのでその方法を...
Pythonで画像のカラーヒストグラムを簡単に表示する方法... 画像で赤、緑、青の画素がどのような分布になっているかという「カラーヒストグラム」を見たいことがあります。しかしいざ探すとツールが少ないのです。Pythonならほんの数行で出せます。 PillowとPyplotでとてもお手軽 カラーヒストグラムの原理は単純で、縦横カラーチャンネルの画像を、カラー...
PyTorchで行列(テンソル)積としてConv2dを使う... PyTorchではmatmulの挙動が特殊なので、思った通りにテンソル積が取れないことがあります。この記事では、基本的な畳み込み演算である「Conv2D」を使い、Numpyのドット積相当の演算を行うという方法を解説します。 はじめに PyTorchの変態コーディング技術です。多分。 画像のテ...
ML Study Jams中級編終わらせてきた ML Study JamsというGoogle Cloudが提供している無料の学習プログラムの第二弾がオープンしています。今度は中級編が追加されており、全部終わらせてきたのでその報告と感想を書いていきたいと思います。 前回の記事 QWIKLABSの使い方とかはこっち。 ML Study Jam...
画像のダウンサンプリングとPSNRの測定... U-Netでどこまでの深さが効いているのかを考えるために、画像をダウンサンプリングし、アップサンプリングするという処理を行いPSNRを見ていきます。その結果、PSNRが15~20程度だと、U-Netの深い層が効かないかもしれないという状況を確認することができました。 きかっけ・考え方 U-Ne...
Pocket
Delicious にシェア

Add a Comment

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です