OpenCVのInpaintingでオクルージョン画像の物体検出精度向上🔍

# はじめに
コンピュータビジョンにおける重要なタスクの一つに、Image Inpainting（日本語では「画像修復」などと呼ばれます）があります。

「Inpainting」という言葉は、あまり聞き馴染みがない方もいらっしゃるかもしれませんが、Google Pixel の「消しゴムマジック」と言えばピンとくる方も多いのではないでしょうか？（消しゴムマジックは技術詳細公開されていませんが、類似の技術のはず。。。）

Image Inpainting は、近年AIによる精度向上が著しい分野の一つですが、Image Inpainting 自体の歴史は古く、AIが登場する以前から、以下のようなアルゴリズムが提案されており、OpenCVにも実装されています。
* An Image Inpainting Technique Based on the Fast Marching Method（2004年）
* Navier-Stokes, Fluid Dynamics, and Image and Video Inpainting（2001年）
<br>
以下は実行例です。<Br>
（1枚目は修復対象画像、2枚目は修復対象箇所のマスク、3枚目は1つ目のアルゴリズムでの修復結果、4枚目は2つ目のアルゴリズムでの修復結果）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140207/cad5cd2a-f6ef-9610-0b4d-49db278c1cd3.png)
[OpenCV Docs Image Inpainting から画像引用](https://docs.opencv.org/4.10.0/df/d3d/tutorial_py_inpainting.html)

今回は、このOpenCVのInpainting処理を活用して、オクルージョン画像の物体検出精度を向上させたケースのお話をします🦔

# Inpaintingでの物体検出精度向上アイデア
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140207/e1a3e3b1-bba4-861b-104d-6a4febdadcd0.png)
物体検出やってると「この手前の物体邪魔だな、、、( ´ー｀)y-~~」て思うケースにちょいちょい遭遇します。 ※例だと車の前にあるポール
（もちろん、カメラ設置時の前提条件とか撮影位置とかの条件を色々縛って、そもそも手前に邪魔な物体がこないようにすることが大事ですが）

そして、こんな感じの検出結果を、上長と一緒に眺めていた時に、以下のようなやりとりがありました🦔
高橋「邪魔な物体が映らないようにしてほしいですが、実運用的には難しいですかねー（現実的には設置可能な位置が限られているケースも多いし）」
上長「そうですよね。ちなみにこれ消しゴムマジックみたいに消せないんですか？」
高橋「、、、(ﾟДﾟ)！」
高橋「意外といけるか。。。？」

と言うわけで、この当時有名だったTransformerベースの Inpainting AIの「[ProPainter](https://github.com/sczhou/ProPainter)」で試してみた結果がこちら↓
※結果が分かりやすいようにcarクラスのみ描画しています

<iframe width="560" height="315" src="https://www.youtube.com/embed/DzKn2qJyx20?si=iex-SPONcT9vamvQ" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

何個かフレームを抜き出して確認した結果↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140207/05d7f65b-da14-4ba9-c4f3-6d7eb32c135f.png)
お、良いんじゃないコレ👀？

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140207/b99a082d-af2a-7c69-8422-6f5e4b26fa36.png)
良いんじゃない？良いんじゃない👀？

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140207/a8a0a1f1-7db3-3ea1-4aca-daba4629a14b.png)
検出精度上がってそー👀

Inpaintingで邪魔な物体(静止物)を消すのは効果がありそうです。
ただ、バカでかい問題が、、、ProPainterが超重い、、、😇！！
ローカルPCで動かせなかったので、Colaboratory上でInpaintingした後に、その修復動画を持ってきて物体検出を試す。なんてことも当時していました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140207/d459e36c-9dc1-306c-8f26-7a6acfe67c10.png)
約24秒の動画(800x464)をA100のGPUで処理して4分9秒。。。
ユースケースにもよりますが、物体検出の前処理として運用するには、これはちょっと重いと思いますね。
Inpainting結果は流石に綺麗なのですが。。。

ProPainterを用いたInpainting動画の生成は、Colaboratoryで試しました。ノートブックはこちら↓
* [Qiita-Advent-Calendar-ProPainter.ipynb](https://drive.google.com/file/d/1Eyh73b_MSKAfvEMyBsin__p_jfeblmsE/view?usp=sharing)

# もっと軽量なInpaintingを求めてOpenCVへ
ProPainterでは重すぎるので、当時はOSSのAIの他モデルをせっせと探していました。
が、
ある日「そもそもAIじゃなくてOpenCV実装の軽いInpaintingでもいけるんじゃね👀？」と思い試してみた結果がこちら↓

<iframe width="560" height="315" src="https://www.youtube.com/embed/9P8lLygHbKc?si=0AmZRCYK2VDbj_s2" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140207/e16ded72-2e02-fb03-4542-d4d5509e859d.png)
いけるやん👀

もちろん画像修復自体の綺麗さはProPainterの足元にもおよびませんが、CPUでもそれなりの速度が出せて、そこそこ画像修復出来て、隠れた物体の検出精度も上がっている。ならOpenCVのInpaintingも全然現役で使えるケースありますね🦔
この投稿では、そんな一例の紹介でした。

上記を試したソースコードは以下にコミットしています。
* [Kazuhito00/Qiita-AdventCalendar-20241210-OpenCV](https://github.com/Kazuhito00/Qiita-AdventCalendar-20241210-OpenCV)

---
ちなみに、ProPainterとOpenCVのInpainting(アルゴリズムはcv2.INPAINT_TELEA)を並べた動画はこちら↓

<iframe width="560" height="315" src="https://www.youtube.com/embed/fGYEooqV7E4?si=mH10Q3eiGlzU5I10" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140207/93b536f8-82ff-9b00-7b47-6347c06d9b1c.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140207/47ea253c-5eb2-0310-7cac-30e6d4a28672.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140207/ea29a47f-ab59-6078-fc55-27d505c2c53d.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140207/469f5fd3-0046-8eb8-a5e4-9ccc4be4810b.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140207/ed1342aa-54e4-b428-dd2e-cd3841bbb1c4.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140207/3dd6e71c-abdb-807d-1ceb-ec5587aba90d.png)
OpenCVのInpaintingも、結構善戦している感じしますね🤔