UJP - 写真に写る人間の顔をモザイクにするPython3 OpenCV

Life is fun and easy!

不正IP報告数

Okan Sensor
 
メイン
ログイン
ブログ カテゴリ一覧

ブログ - 写真に写る人間の顔をモザイクにするPython3 OpenCV

写真に写る人間の顔をモザイクにするPython3 OpenCV

カテゴリ : 
ハウツー
ブロガー : 
ujpblog 2025/10/15 1:51
 万博で写真をたくさん撮ったのだけど,知らない人の顔写真が入っていることが多い.これを手動でマスクするのは大変なので,OpenCVを使ってPythonスクリプトで削除してみた.

仮想環境を作成
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をつけて保存するようにしてください.
 以下のスクリプトをface_mosaic.pyとして保存する.
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) %

 結果はこのように.


 ・赤色矢印の部分は,顔の誤検知.
 ・青色矢印は未検知.

 手動で書き換えるよりは随分楽になるかな.

トラックバック


広告スペース
Google