ブログ - 写真に写る人間の顔をモザイクにするPython3 OpenCV
万博で写真をたくさん撮ったのだけど,知らない人の顔写真が入っていることが多い.これを手動でマスクするのは大変なので,OpenCVを使ってPythonスクリプトで削除してみた.
ChatGPTに次のように依頼.
引用: 以下のスクリプトをface_mosaic.pyとして保存する.
いくつか制限が.
・顔検出精度は「正面顔」に最適化されています。横顔や暗い写真は苦手です。
→ 高精度化したい場合は cv2.FaceDetectorYN や mediapipe を使うバージョンも作れます。
絵文字は難しいようなので,使わない設定に変更されてる.
実行してみた
結果はこのように.

・赤色矢印の部分は,顔の誤検知.
・青色矢印は未検知.
手動で書き換えるよりは随分楽になるかな.
仮想環境を作成
python3 -m venv venv🆑
仮想環境を有効化
source venv/bin/activate🆑
OpenCVをインストール
pip install opencv-python🆑
Pythonライブラリを個別の仮想環境に入れるツールのpipxをインストール
brew install pipx🆑
pipx install opencv-python🆑
OpenCVをインストールする.
python3 -m pip install opencv-python --break-system-packages --user🆑
python3 -m pip install pillow🆑
ChatGPTに次のように依頼.
引用:
OpenCVを使って人間の顔にモザイク(あるいは笑顔の顔文字)でおきかえるPythonを作ってください. スクリプトを実行時に,ファイルパスを受け取り,そこにあるJPEGファイルを受け取り,編集後はファイル名にmをつけて保存するようにしてください.
import cv2
import sys
import os
import numpy as np
from PIL import Image, ImageDraw, ImageFont
def mosaic_face(image, x, y, w, h, emoji=False):
"""顔領域をモザイクまたは絵文字に置き換える"""
if emoji:
# 絵文字画像を生成(背景透過のテキストを使わず絵文字画像を描く)
emoji_img = np.zeros((h, w, 3), dtype=np.uint8) + 255
pil_emoji = Image.fromarray(emoji_img)
draw = ImageDraw.Draw(pil_emoji)
draw.text((w//4, h//6), "😄", font=ImageFont.load_default(), fill=(0, 0, 0))
emoji_bgr = cv2.cvtColor(np.array(pil_emoji), cv2.COLOR_RGB2BGR)
# 顔部分に貼り付け
image[y:y+h, x:x+w] = emoji_bgr
return image
else:
# モザイク処理
face_region = image[y:y+h, x:x+w]
small = cv2.resize(face_region, (w//10, h//10))
mosaic = cv2.resize(small, (w, h), interpolation=cv2.INTER_NEAREST)
image[y:y+h, x:x+w] = mosaic
return image
def main():
if len(sys.argv) < 2:
print("使い方: python face_mosaic.py <画像ファイル>")
sys.exit(1)
file_path = sys.argv[1]
if not os.path.exists(file_path):
print("ファイルが見つかりません:", file_path)
sys.exit(1)
# 画像の読み込み
img = cv2.imread(file_path)
if img is None:
print("画像を読み込めませんでした。JPEGを指定してください。")
sys.exit(1)
# 顔検出器を読み込み(OpenCV標準のHaar Cascade)
cascade_path = cv2.data.haarcascades + "haarcascade_frontalface_default.xml"
face_cascade = cv2.CascadeClassifier(cascade_path)
# 顔を検出
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(gray, scaleFactor=1.2, minNeighbors=5, minSize=(50, 50))
print(f"{len(faces)} 個の顔を検出しました。")
# 処理を選択(絵文字 or モザイク)
use_emoji = input("絵文字で置き換えますか?(y/n): ").lower() == 'y'
# 各顔に処理を適用
for (x, y, w, h) in faces:
img = mosaic_face(img, x, y, w, h, emoji=use_emoji)
# 保存
base, ext = os.path.splitext(file_path)
output_path = f"{base}_m{ext}"
cv2.imwrite(output_path, img)
print("保存しました →", output_path)
if __name__ == "__main__":
main()
(venv) $
・顔検出精度は「正面顔」に最適化されています。横顔や暗い写真は苦手です。
→ 高精度化したい場合は cv2.FaceDetectorYN や mediapipe を使うバージョンも作れます。
絵文字は難しいようなので,使わない設定に変更されてる.
実行してみた
(venv) % python3 face_mosaic.py /Users/ujpadmin/Documents/IMG_7021.jpeg🆑
11 個の顔を検出しました。
絵文字で置き換えますか?(y/n): y🆑
保存しました → /Users/ujpadmin/Documents/IMG_7021_m.jpeg
(venv) %
結果はこのように.

・赤色矢印の部分は,顔の誤検知.
・青色矢印は未検知.
手動で書き換えるよりは随分楽になるかな.