LoginSignup
11
4

More than 1 year has passed since last update.

顔のパーツ検出を利用し、顔写真をちいかわにする

Posted at

この記事は OpenCV Advent Calender 20日目の記事です。

こんにちは。Webバックエンドエンジニアと、フォントクリエイターを名乗っております @irimo と申します。
今回は OpenCV アドカレに初参加させていただき、緊張しております。

昨日は @ki_230 さんの記事でした。
OpenCV.jsを利用したリアルタイムビデオ処理!
なんでもできそうですが、ネタが浮かばない... でも、いろいろアイデア出ししてみたいところです。

TL;DR

今回は「顔検出」と「ちいかわ」がテーマです。
顔写真をちいかわちゃんにするのがゴールになります。

このマツコ・デラックスさん(参照元)の写真を顔検出させて加工すると、
001.jpg
こうなりました。
ck.png

最近はOpenCV以外の顔検出のライブラリが充実しており、OpenCV縛りだとこれが限界になります。
顔検出ではあまり OpenCV はメジャーじゃないのかと思います。
商用ツールの顔認識は、自前で実装(修正)してるのだとわかりました。

口の検出は残念ながらありません。そのため、今回は適当に貼りました。
(別のライブラリでリベンジしたいところ)

やった

  • 輪郭、目 の検出
  • 画像の回転・合成
  • 回転率を合わせる
  • 貼り付け位置が不自然にならないように調節

宿題

  • 輪郭画像の透明部分が変になっている
  • 口の検出がないとはいえ、場所が適当になっている

顔検出について

OpenCVには「顔検出」の機能があります。
人間を読み込ませると、顔のパーツを四角形で返してくれるものです。

今回は一人が映っている写真の「顔の輪郭」「目」の検出をしました。

目の検出の教師データは「右目」「左目」と分かれているバージョンもありますが、厳密でないみたいなので「目」の教師データを使用しました。
この「目」の検出は、一人の写真なのになぜか目が3つ以上検知されます。判定のつきやすいものから検出していますので、前2つの四角を取得すれば、二つの目が検出できます。
ちなみに、「右目」は2つ、「左目」も2つ検出されます。こちらも一番前の四角を適用すると良いです。

class square_reco:
    img_gray = ""
    xml_path = ""
    xml_base_dir = "/usr/local/lib/python3.7/site-packages/cv2/data/"
    def __init__(self, img_gray, xml_filename):
        self.img_gray = img_gray
        self.xml_path = self.xml_base_dir + xml_filename
    def reco(self):
        classifier = cv2.CascadeClassifier(self.xml_path)
        targets = classifier.detectMultiScale(self.img_gray)
        return targets

class face_reco(square_reco):
    xml_face = "haarcascade_frontalface_default.xml"
    def __init__(self, img_gray):
        print("face_reco init")
        super().__init__(img_gray, self.xml_face)

class eyes_reco(square_reco):
    filename = "haarcascade_eye.xml"
    def __init__(self, img_gray):
        print("eyes_reco init")
        super().__init__(img_gray, self.filename)


law_path = "./images/idol/001.jpg"
img_origin = cv2.imread(law_path)
img_gray = cv2.cvtColor(img_origin, cv2.COLOR_BGR2GRAY)

face = face_reco(img_gray)
# targets は、二次元の配列(4要素 x, y, width, height)* 検出された分
targets = face.reco()

回転について

こちらを参考に、透明部分のある画像を回転させました。

パーツの拡大率について

ちいかわの画像を模写、自前で製作し、パーツ分けをしました。
ちいかわ.png

元パーツの比率度外視で、顔検出で検出された四角にそのままパーツをあてはめると、パーツの形が変わり、縮小率も違って不自然な画像になります。
ですので、一番縮小率の低い「輪郭パーツ」の縮小率に全てのパーツの縮小率を合わせました。

縮小率を考えていない画像と、考えた画像を比べました。不自然さが少しとれたと思います。回転させていない状態です。
ck顔と目の比率が’違ってろんぱってる.png
顔と目の比率が違う

ck目の縮小率を合わせたがろんぱってる.png
顔と目の縮小率を合わせた

おわりに

もっと「あなたに似たちいかわ」になるようにしたかったですが、顔のこだわりが少ないという性格ですので、あまり凝れませんでした。申し訳ありません。
改めて顔の仕事してる方々に敬意を示します。ですが、軽く挑戦できて面白かったです。

今回のリポジトリはこちらです。

明日の担当は @Kazuhito さんです!

11
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
4