OpenCV – 画像にモザイク処理を行う方法について

概要
OpenCV を使用して画像にモザイクをかける方法について解説します。
モザイク処理のやり方
画像のモザイク処理したい領域を最近傍補間で一度小さいサイズに縮小したあと、元のサイズに拡大することでモザイクをかけることができます。
OpenCV で行う場合、cv2.resize() でリサイズします。
import cv2
from IPython.display import Image, display
def imshow(img):
"""ndarray 配列をインラインで Notebook 上に表示する。
"""
ret, encoded = cv2.imencode(".jpg", img)
display(Image(encoded))
import cv2
def mosaic(img, scale=0.1):
h, w = img.shape[:2] # 画像の大きさ
# 画像を scale (0 < scale <= 1) 倍に縮小する。
dst = cv2.resize(
img, dsize=None, fx=scale, fy=scale, interpolation=cv2.INTER_NEAREST
)
# 元の大きさに拡大する。
dst = cv2.resize(dst, dsize=(w, h), interpolation=cv2.INTER_NEAREST)
return dst
# 画像を読み込む。
img = cv2.imread("sample1.jpg")
# モザイク処理を行う。
dst = mosaic(img)
imshow(dst)

cv2.reisze() でリサイズする際、補完方法に最近傍補完 (interpolation=cv2.INTER_NEAREST
) 以外を指定すると、以下のようなぼやけた画像になってしまいます。
画像の一部だけをモザイク処理する
画像の一部の範囲のみモザイク処理したい場合は、まず処理したい領域 (rectangular region of interest, ROI) を numpy のスライスを使用して切り出します。
img[<左上の y 座標>:<右下の y 座標>, <左上の x 座標>:<右下の x 座標>]
# 画像を読み込む。
img = cv2.imread("sample2.jpg")
# roi を抽出する。
roi = img[140:170, 200:250]
# モザイク処理を行い、結果を roi に代入する。
roi[:] = mosaic(roi)
imshow(img)

すりガラス風のモザイクをかける
iPhone のようなすりガラス風のエフェクトをかけたい場合は cv2.blur()
を使用します。
第2引数のカネールサイズ ksize=(k, k)
を大きな値にすると、よりぼやけた画像になります。
# 画像を読み込む。
img = cv2.imread("sample4.jpg")
def mosaic_blur(img, k=15):
h, w = img.shape[:2] # 画像の大きさ
dst = cv2.blur(img, ksize=(k, k))
return dst
# roi を抽出する。
h, w = img.shape[:2]
roi = img[:, w//2:] # 右半分をモザイクにする
# モザイク処理を行い、結果を roi に代入する。
roi[:] = mosaic_blur(roi)
imshow(img)

人の顔にモザイクをかける
前項の応用として、OpenCV のカスケード検出器で画像から顔の領域を検出し、モザイクをかける方法を紹介します。
まず、カスケード検出器である cv2.CascadeClassifier オブジェクトを作成します。
顔検出を行うには、CascadeClassifier.detectMultiScale() に画像を渡します。
顔が検出できた場合は、顔の領域を表す (左上の x 座標, 左上の y 座標, 幅, 高さ)
のタプルのリストを返します。
この領域に対して、モザイク処理を行います。
import cv2
import os
# 画像を読み込む。
img = cv2.imread("sample3.jpg")
# カスケード検出器を作成する。
cascade = cv2.CascadeClassifier(
os.path.join(cv2.data.haarcascades, "haarcascade_frontalface_default.xml")
)
# 顔検出する。
faces = cascade.detectMultiScale(img, scaleFactor=1.1, minNeighbors=1, minSize=(1, 1))
for x, y, w, h in faces:
# roi を抽出する。
roi = img[y : y + h, x : x + w]
# モザイク処理を行い、結果を roi に代入する。
roi[:] = mosaic(roi)
imshow(img)

-
前の記事
OpenCV – 特徴点マッチングを行う方法について 2020.04.07
-
次の記事
OpenCV – カスケード分類器 CascadeClassifier で画像から顔や目を検出する方法について 2020.05.08