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

目次

概要

OpenCV を使用して画像にモザイクをかける方法について解説します。

リサイズを利用したモザイク処理

画像のモザイク処理を行う領域を最近傍補間で一度小さいサイズに縮小したあと、元のサイズに拡大することでモザイク処理が行えます。

モザイク処理の流れ

OpenCV で行う場合、cv2.resize() でリサイズします。

sample1.jpg

In [1]:
import cv2
from IPython.display import Image, display


def imshow(img):
    """ndarray 配列をインラインで Notebook 上に表示する。"""
    ret, encoded = cv2.imencode(".jpg", img)
    display(Image(encoded))
In [2]:
def mosaic(img, scale=0.1):
    img_h, img_w = img.shape[:2]  # 画像の大きさ

    # 画像を scale 倍に縮小する。
    img_resized = cv2.resize(
        img, dsize=None, fx=scale, fy=scale, interpolation=cv2.INTER_NEAREST
    )

    # 元の大きさに拡大する。
    dst = cv2.resize(img_resized, dsize=(img_w, img_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 のスライスを使用して切り出します。切り出した画像にモザイク処理を行い、元の画像の領域に代入します。

sample2.jpg

In [4]:
def mosaic(img, scale=0.1):
    img_h, img_w = img.shape[:2]  # 画像の大きさ

    # 画像を scale 倍に縮小する。
    img_resized = cv2.resize(
        img, dsize=None, fx=scale, fy=scale, interpolation=cv2.INTER_NEAREST
    )

    # 元の大きさに拡大する。
    dst = cv2.resize(img_resized, dsize=(img_w, img_h), interpolation=cv2.INTER_NEAREST)

    return dst


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) を大きな値にすると、よりぼやけた画像になります。

sample4.jpg

In [5]:
def mosaic_blur(img, k=15):
    h, w = img.shape[:2]  # 画像の大きさ

    dst = cv2.blur(img, ksize=(k, k))

    return dst


img = cv2.imread("sample4.jpg")

# roi を抽出する。
h, w = img.shape[:2]
roi = img[:, w // 2 :]  # 右半分をモザイクにする

# モザイク処理を行い、結果を roi に代入する。
roi[:] = mosaic_blur(roi)
imshow(img)

人の顔にモザイクをかける

一部の領域にモザイク処理を行う応用として、OpenCV のカスケード検出器で画像から顔の領域を検出し、モザイクをかける方法を紹介します。

まず、カスケード検出器である cv2.CascadeClassifier オブジェクトを作成します。 顔検出を行うには、CascadeClassifier.detectMultiScale() に画像を渡します。 顔が検出できた場合は、顔の領域を表す (左上の x 座標, 左上の y 座標, 幅, 高さ) のタプルのリストを返します。 この領域に対して、モザイク処理を行います。

sample3.jpg

In [6]:
import cv2
import os


def mosaic_face(img):
    # カスケード検出器を作成する。
    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:
        print(f"検出されました。(x: {x}, y: {y}, w: {w}, h: {h})")

        # roi を抽出する。
        roi = img[y : y + h, x : x + w]

        # モザイク処理を行い、結果を roi に代入する。
        roi[:] = mosaic(roi)


# 画像を読み込む。
img = cv2.imread("sample3.jpg")

mosaic_face(img)

imshow(img)
検出されました。(x: 140, y: 112, w: 58, h: 58)

コメント

コメントする

目次