目次
概要
OpenCV を使用して画像にモザイクをかける方法について解説します。
リサイズを利用したモザイク処理
画像のモザイク処理を行う領域を最近傍補間で一度小さいサイズに縮小したあと、元のサイズに拡大することでモザイク処理が行えます。
OpenCV で行う場合、cv2.resize() でリサイズします。
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 のスライスを使用して切り出します。切り出した画像にモザイク処理を行い、元の画像の領域に代入します。
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)
を大きな値にすると、よりぼやけた画像になります。
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 座標, 幅, 高さ)
のタプルのリストを返します。
この領域に対して、モザイク処理を行います。
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)
コメント