こしあん
2019-02-08

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


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

PCA Color Augmentationを拡張してTensorFlow/Keras向けに実装した... PCA Color AugmentationはAlexNetの論文に示された画像向けのData Augmentationですが、画像用だけではなく、テンソルの固有値分解をすることで構造化データに対しても使えるようにしてみました。これの解説と効果を書きます。 リポジトリ こちら https://...
keras_preprocessingを使ってお手軽に画像を回転させる方法... Data Augmentationで画像を回転させたいことがあります。画像の回転は一般に「アフィン変換」と呼ばれる操作で、OpenCVやPillowのライブラリを使えば簡単にできるのですが、Numpy配列に対して1から書くとかなりめんどいのです。Kerasが裏で使っているkeras_preproc...
Python(Numpy)で画像を水平反転する方法:Data Augmentation向け... OpenCVを使わずに単純に画像を左右反転(水平反転)する方法を考えます。ディープラーニングでデータのジェネレーターを自分で実装した場合、Data Augmentationを組み込む際にも必要になります。それを見ていきましょう。 左右反転自体は実は簡単 例えばNumpyの行列を左右反転させてみ...
Numpyの配列のみを操作して四角形を描画する(Numpyの画像処理)... Numpyの画像処理です。Numpyの配列のみを操作して、画面上に四角形を描画してみます。Numpyの画像処理は出力結果の合成のときにたまに使う割には若干独特なので注意が必要です。 Numpy arrayの画像の構造は(y, x, channel) ここだけ覚えておけば大丈夫です。Pillo...
Pythonで画像のカラーヒストグラムを簡単に表示する方法... 画像で赤、緑、青の画素がどのような分布になっているかという「カラーヒストグラム」を見たいことがあります。しかしいざ探すとツールが少ないのです。Pythonならほんの数行で出せます。 PillowとPyplotでとてもお手軽 カラーヒストグラムの原理は単純で、縦横カラーチャンネルの画像を、カラー...

Add a Comment

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