システム概要
今回、OpenCVとArUcoモジュールを使って、画像の射影変換を行うアプリケーションを作成しました。
きっかけは、以下のようなご依頼からでした。

イラストコンテストを主催しているものです。
作品応募は写真で受付していますが、歪みや斜め撮影が生じており、現在手動で歪み補正とトリミングを行っています。
手間がかかるため自動化したいです。
ArUcoとは
ArUcoはカメラで読み取るために作られたマーカーです。
具体的には、以下のようなマーカーになります。


今回はこちらのマーカーを利用して射影変換を行います。
イラスト写真サンプル
今回、以下のようなイラスト写真のサンプルを用意しました。


依頼者様からの希望で、射影変換をするためのArUcoマーカーを抽出したいイラストエリアの4隅に置くことにしました。
応募者によってはより酷い撮り方もあることを想定し、以下のサンプルも用意しました。


射影変換は、これらの写真に対して以下の処理を行います。
- イラストエリアのみを切り抜く
- 画像は正面方向に射影変換
作成したアプリケーションの実行
まず、正しくArUcoマーカーを認識できているか確認します。


上記の通り、ArUcoマーカーを適切に認識できていることが分かります。
PythonとOpenCVを用いた射影変換は以下のように実行できます。
# マーカーの検出
corners, ids, _ = cv2.aruco.detectMarkers(img, aruco_dict, parameters=aruco_params)
# マーカーが4つあるか確認
if len(corners) != 4:
raise Exception("Expected 4 markers, but found " + str(len(corners)))
# 配列を初期化
sPoints = [ [0]*2 ] * 4
for i, corner in enumerate(corners):
points = corner[0].astype(np.int32)
# 左上
if ids[i][0] == 0:
sPoints[0] = points[2]
# 右上
if ids[i][0] == 1:
sPoints[1] = points[3]
# 左下
if ids[i][0] == 2:
sPoints[2] = points[1]
# 右下
if ids[i][0] == 3:
sPoints[3] = points[0]
# 射影元と射影先の設定
src = np.array(sPoints, dtype=np.float32)
# 左上、右上、左下、右下
dst = np.array([[0, 0], [600, 0], [0, 690], [600, 690]], dtype=np.float32)
# 射影行列の作成
M = cv2.getPerspectiveTransform(src, dst)
# 射影変換の適用
result = cv2.warpPerspective(img, M, (600, 690))
早速ですが、サンプル1の出力結果は以下の通りです。


イラストエリアの抽出と、正面方向への射影変換が適切に実施できていることが分かります。
続いて、サンプル1よりもより酷い歪み・斜め撮影を行ったサンプル2についてもマーカーが認識できているか確認します。


こちらについても先程と同様にマーカーがきちんと認識できていることが分かります。
出力結果は以下の通りでした。


撮影の状態が酷い写真についても、適切に射影変換できていることが分かります。
最終的にはこれら射影変換機能に加え、一括変換やリネーム、出力結果の画像サイズの変更などより使いやすい機能を付けたアプリケーションを納品させて頂きました。
ご依頼について
NeeNetではPythonやOpenCVを活用したアプリケーション作成のご相談もお受けしています。
OpenCVを利用したその他の事例として、以下のような対応もございます。


個人/法人問わず、お客様の業務効率化や手間削減などを支援できればと考えております。
何かご相談事項がございましたら、一度ご連絡いただければと思います。
ご相談や依頼は下記のお問い合わせページから可能です。