OpenCV 4.13.0
Open Source Computer Vision
読み込み中...
検索中...
見つかりません
🤖 AIによる機械翻訳(非公式) — これは OpenCV 4.13.0 公式リファレンス(英語)を AI (Claude) で自動翻訳したものです。訳に誤りを含む場合があります。正確な情報は 公式英語版(原文) を参照してください。
画像のインペインティング

目標

本章では、

  • インペインティングと呼ばれる手法を用いて、古い写真から小さなノイズや傷などを除去する方法を学ぶ
  • OpenCVのインペインティング機能について見ていく。

基礎

多くの人は、黒い斑点や傷などが付いた古く劣化した写真を自宅に持っているだろう。それを元に戻して復元したいと思ったことはないだろうか。ペイントツールで単に消すことはできない。なぜなら、黒い構造を白い構造に置き換えるだけで役に立たないからである。こうした場合には、画像インペインティング(image inpainting)と呼ばれる技術が使われる。基本的な考え方は単純で、これらの悪い跡を周囲のピクセルで置き換え、周辺に馴染むようにするというものである。下に示す画像(Wikipedia から引用)を見てみよう:

image

この目的のためにいくつかのアルゴリズムが設計されており、OpenCVはそのうちの2つを提供している。どちらも同じ関数 cv.inpaint() からアクセスできる

1つ目のアルゴリズムは、2004年の Alexandru Telea による論文 "An Image Inpainting Technique Based on the Fast Marching Method" に基づいている。これは Fast Marching Method(高速行進法)に基づく。画像中のインペインティング対象となる領域を考える。アルゴリズムはこの領域の境界から始まり、境界部分から先にすべてを埋めながら徐々に領域の内側へ進んでいく。インペインティング対象となるピクセルの周辺に、小さな近傍領域をとる。このピクセルは、近傍にある既知のピクセルすべての正規化された重み付き和で置き換えられる。重みの選択は重要な問題である。対象点に近いピクセル、境界の法線近くにあるピクセル、そして境界の輪郭上にあるピクセルに、より大きな重みが与えられる。1つのピクセルがインペインティングされると、Fast Marching Method を用いて次の最も近いピクセルへ移動する。FMM は既知のピクセルに近いものから先にインペインティングされることを保証するため、手作業のヒューリスティックな操作のように機能する。このアルゴリズムはフラグ cv.INPAINT_TELEA を使うことで有効になる。

2つ目のアルゴリズムは、2001年の Bertalmio, Marcelo、Andrea L. Bertozzi、Guillermo Sapiro による論文 "Navier-Stokes, Fluid Dynamics, and Image and Video Inpainting" に基づいている。このアルゴリズムは流体力学に基づき、偏微分方程式を利用する。基本原理はヒューリスティックである。まず既知領域から未知領域へエッジに沿って進む(エッジは連続しているはずだからである)。インペインティング領域の境界において勾配ベクトルを整合させながら、等位線(等しい強度を持つ点を結ぶ線。等しい標高の点を結ぶ輪郭線のようなもの)を延長していく。このために流体力学のいくつかの手法が用いられる。それらが得られると、その領域内の分散を最小にするように色が埋められる。このアルゴリズムはフラグ cv.INPAINT_NS を使うことで有効になる。

コード

入力画像と同じサイズのマスクを作成する必要がある。マスクでは非ゼロのピクセルがインペインティング対象の領域に対応する。それ以外はすべて単純である。私の画像は(手作業で加えた)いくつかの黒い傷で劣化している。これに対応する傷を Paint ツールで作成した。

import numpy as np
import cv2 as cv
img = cv.imread('messi_2.jpg')
mask = cv.imread('mask2.png', cv.IMREAD_GRAYSCALE)
dst = cv.inpaint(img,mask,3,cv.INPAINT_TELEA)
cv.imshow('dst',dst)
void imshow(const String &winname, InputArray mat)
Displays an image in the specified window.
int waitKey(int delay=0)
Waits for a pressed key.
void destroyAllWindows()
Destroys all of the HighGUI windows.
Mat imread(const String &filename, int flags=IMREAD_COLOR_BGR)
Loads an image from a file.
void inpaint(InputArray src, InputArray inpaintMask, OutputArray dst, double inpaintRadius, int flags)
Restores the selected region in an image using the region neighborhood.

下に結果を示す。1枚目の画像は劣化した入力を示す。2枚目はマスクである。3枚目は1つ目のアルゴリズムの結果、最後の画像は2つ目のアルゴリズムの結果である。

image

追加リソース

  1. Bertalmio, Marcelo, Andrea L. Bertozzi, and Guillermo Sapiro. "Navier-stokes, fluid dynamics, and image and video inpainting." In Computer Vision and Pattern Recognition, 2001. CVPR 2001. Proceedings of the 2001 IEEE Computer Society Conference on, vol. 1, pp. I-355. IEEE, 2001.
  2. Telea, Alexandru. "An image inpainting technique based on the fast marching method." Journal of graphics tools 9.1 (2004): 23-34.

演習

  1. OpenCVにはインペインティングに関するインタラクティブなサンプル samples/python/inpaint.py が付属しているので、試してみよう。
  2. 数か月前、Adobe Photoshop で使われている高度なインペインティング技術である Content-Aware Fill についての動画を見た。さらに調べたところ、同じ技術が "Resynthesizer" という別の名前で既に GIMP に存在していることがわかった(別途プラグインのインストールが必要)。きっとこの技術を楽しめるはずだ。