OpenCVを利用してパノラマ画像を作成する

備忘録として書く。

## パノラマ写真とは
>パノラマ写真（パノラマしゃしん）とは、広い範囲を撮影した写真。通常の35ミリ銀塩フィルムの縦横比(2:3)や、標準的なディスプレイ／デジタルカメラの縦横比(3:4)ではなく、横長または縦長の写真。パーソナルコンピュータ上で、360度の全景データを作成し、連続的に表示する技術もあり、これもパノラマ写真の一種と考えられる。上下左右全てを撮影した完全な全天球写真の場合は、縦横比(2:1)である。

https://ja.wikipedia.org/wiki/%E3%83%91%E3%83%8E%E3%83%A9%E3%83%9E%E5%86%99%E7%9C%9F

## OpenCV Stitching について

今回のパノラマ画像を生成するにあたって必要なモジュール。


1枚1枚の画像は画像に映るオブジェクトが少し重なるように撮影する必要がある。ざっくり言うとモジュールの中では１枚１枚の画像繋ぎ合わせる処理を行っているため、画像の重なった部分がわからないと繋ぎ合わせることは出来ないと言うことになる。

## Stitchingの種類について
| Mode | 説明 |
| ---- | ---- |
| **PANORAMA** | 球面体のような画像を合成 |
| **SCAN**| コピー機でスキャンしたような平面の画像を合成。 |

https://docs.opencv.org/4.x/d8/d19/tutorial_stitcher.html






## 実際にコードを書いてみた
PANORAMAとSCANをそれぞれ作成してみる。
今回はどれだけ元画像と同じくらいに繋ぎ合わせられるか確認のために
１枚の画像をわざと左右２分割して、元に戻して確認してみます。

### 利用画像
元画像
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487318/5ff8a4e9-91b1-855f-344d-885750046980.jpeg" width="400" >

左側
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487318/7bc4da0d-13b5-05cc-77d7-7596860b713b.png" width="300" >
右側
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487318/304168ef-ff07-4a80-f580-a46dbf423c75.png" width="300" >

### ソースコード
```
def CreateImage():
    # 画像を読み込む。
    img1 = cv2.imread('ScreenShot/left.png')
    img2 = cv2.imread('ScreenShot/right.png')
    # ２枚の画像の高さと幅をresizeして同じにする　数字は任意で。本当は大きい方に自動的に合わせたかったけど今回割愛 
    img1_resize = cv2.resize(img1, (800, 700))
    img2_resize = cv2.resize(img2, (800, 700))

    # パノラマ合成する。
    stitcher_create = cv2.Stitcher.create()
    status1,stitched_panorama = stitcher_create.stitch([img1_resize, img2_resize])
    print(status1)
    # パノラマ画像を保存する。
    cv2.imwrite('panorama_output.png', stitched_panorama)

    # スキャンを合成する
    stitcher_scan = cv2.Stitcher.create(cv2.Stitcher_SCANS)
    status2,stitched_scan = stitcher_scan.stitch([img1_resize, img2_resize])
    print(status2)
    # Scan画像を保存する
    cv2.imwrite('scan_output.png', stitched_scan)

   
    print("finish")

CreateImage()
```
### 結果
**PANORAMA画像**
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487318/db6ff75f-809b-9a77-a559-dc5245c19ce5.png" width="400">
**SCAN画像**
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487318/0a18541c-5892-209e-7f57-08388b68145f.png"width="400">


画像が結合されて出力されました。
PANORAMA、SCAN画像共に元画像を比較しても画像のサイズが異なるだけで、画像の繋ぎ目におかしい点はないですね。

試しにSCAN画像と元画像のサイズを同じにしてみます。
```
~~さっきのソースコードの一番下に下記を追加
#作成したパノラマ画像読み込み
    image = cv2.imread('scan_output.png')
    #作成したパノラマ画像を元画像のwidth,heightと同じにする
    image_resize = cv2.resize(image, (1472, 800))
    #出力
    cv2.imwrite('resize_output.png', image_resize)
```

### 結果
**元画像**
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487318/cac4e038-5d76-22d6-8a69-88574cd9cc38.jpeg"width="400">

**リサイズしたSCAN画像**
<img src= "https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487318/7e24675c-3df0-d5fe-2a1a-e32b07ea321b.jpeg"width="400">


よくよく見るとSCAN画像の画質が少し荒いですね。キャラクター達全員なんとなくぼやけているような。。

## 最後に
元々iPhoneの複数枚あるスクショを１枚の画像にまとめることができないか探してた時にこのStitcherに辿り着きました。
OpenCVは元々テンプレートマッチングなどで遊んでいましたが、こんな便利なものがあるのかーと言う気持ちになりました。
ただ、肝心のiPhoneのスクショまとめる件についは上記のコードで生成できなかったです（白目）
面白そうなモジュールを発見できたと言うことで良します。

### 参考・引用

パノラマ写真
https://ja.wikipedia.org/wiki/%E3%83%91%E3%83%8E%E3%83%A9%E3%83%9E%E5%86%99%E7%9C%9F

OpenCV Stitching
https://docs.opencv.org/4.x/d8/d19/tutorial_stitcher.html

任天堂　進撃の巨人２～未来の座標～
https://www.nintendo.co.jp/titles/50010000043795