顔モーフィング(1.顔の特徴点の検出)

こんにちは。

毎週木曜日の19時はVS嵐を見ることが習慣になっています。その中にある「顔ミックス対決」にトライしたので、分解して少しずつ記事にしていこうと思います。

mami
少しずつです(笑)

「顔ミックス」という名前ではなくて、顔モーフィング(face Morphing)というのが一般的なようです。モーフィングとは「ある物体から別の物体へと自然に変形する映像をみせる。」事だそうです。by ウィキ
ここではオードリーヘップバーンからマリリンモンローへのモーディングを例にしていきます。

顔モーフィングを作る手順は以下です。今回は「1.顔の特徴点の検出」について書いていきます。

顔モーフィング手順

  1. 顔の特徴点の検出
  2. ドロネーの三角形分割でメッシュ生成
  3. 三角形をワープしてブレンド

1.顔の特徴点の検出

顔の特徴点はdlibを使用して68点を検出します。
あとは画像のコーナー4点とそれらのコーナーの中間点4点を追加します。

オードリーヘップバーン



マリリンモンロー



ソースコード

def Face_landmarks(image_path):

  print("[INFO] loading facial landmark predictor...")
  detector = dlib.get_frontal_face_detector()
  predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")

  image = cv2.imread(image_path)
  size = image.shape

  gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
  rects = detector(gray, 0)

  if len(rects) > 2:
    print("[ERR] too many faces fount...")
    # print("[Error] {} faces found...".format(len(rect)))
    sys.exit(1)
  if len(rects) < 1:
    print("[ERR] face not found...")
    # print("[Error] face not found...".format(len(rect))
    sys.exit(1)

  for rect in rects:
    (bX, bY, bW, bH) = face_utils.rect_to_bb(rect)
    print("[INFO] face frame {}".format(bX, bY, bW, bH))

    shape = predictor(gray, rect)
    shape = face_utils.shape_to_np(shape)
    points = shape.tolist()

    # (0,0),(x,0),(0,y),(x,y)
    points.append([0, 0])
    points.append([int(size[1]-1), 0])
    points.append([0, int(size[0]-1)])
    points.append([int(size[1]-1), int(size[0]-1)])

    # (x/2,0),(0,y/2),(x/2,y),(x,y/2)
    points.append([int(size[1]/2), 0])
    points.append([0, int(size[0]/2)])
    points.append([int(size[1]/2), int(size[0]-1)])
    points.append([int(size[1]-1), int(size[0]/2)])

  cv2.destroyAllWindows()
  return points

特徴点を取得したらその点と番号を書いていきます。(モーフィングには使いません)

if __name__ == '__main__':

    filename = 'image/MarilynMonroe.jpg'
    name,ext = os.path.splitext(filename)
    img = cv2.imread(filename)

    points = Face_landmarks(filename)


    stringToWrite = ''
    for (i, (x, y)) in enumerate(points):
        print(x, y)
        stringToWrite += str(x) + " " + str(y) + "n"

        cv2.circle(img, (x, y), 1, (0, 0, 255), -1)
        cv2.putText(img, str(i + 1), (x - 10, y - 10),
            cv2.FONT_HERSHEY_SIMPLEX, 0.35, (0, 0, 255), 1)

    cv2.imwrite('%s-points.jpg' %name,img)

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)