こんばんは、Yuinaです!
今日はSQLをお休みして、Pythonでプログラムを作成します。
ところで、みなさんは「このモデルさんみたいな顔になりたいな」「自分に似合うメイクってどうやって見つけるんだろう?」そんなふうに思ったこと、ありませんか?
メイクって、感覚や流行だけじゃなくて、「自分と理想の顔の“差”」を知ることでグッと精度が上がるんです。
今回は、自分の顔と理想の顔(女優さん・モデルさん・アニメキャラなどでもOK)を画像で比較して、
目や鼻、口、輪郭などの細かなパーツごとの特徴差を数値化しました。
理想の顔に“寄せていく”楽しさを、ぜひ体験してみてください!
よろしくお願いいたします🙏
環境:Google Colab
必要なライブラリ:
cv2
: OpenCV ライブラリです。画像データの読み込み、処理、表示などに使われます。dlib
: 顔検出や顔のパーツ(ランドマーク)の検出に使われるライブラリです。numpy
: 数値計算を効率的に行うためのライブラリです。ここでは、ランドマークの座標を数値配列として扱ったり、距離計算などを行ったりするのに使われます。
!pip install opencv-python dlib numpy
必要なファイル:
shape_predictor_68_face_landmarks.dat
これはdlibの顔ランドマーク検出に必要な学習モデルファイルです。
!wget http://dlib.net/files/shape_predictor_68_face_landmarks.dat.bz2
!bzip2 -d shape_predictor_68_face_landmarks.dat.bz2
画像ファイルの準備します。
self_image_path: あなたの顔写真のファイルパス
ideal_image_path: 理想の顔の写真のファイルパス
self_image_path = "/content/S__40124419.jpg"
ideal_image_path = "/content/S__40124437.jpg"
アップロードが完了したら、ファイル名を確認して次へ進みます。
import cv2
import dlib
import numpy as np
# 顔検出器と68点のランドマークモデル
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")
ライブラリの準備と読み込みをしていきます。
get_frontal_face_detector()
は顔を検出する関数です。
shape_predictor(...)
は、顔の68点ランドマークモデルを読み込んでいます。
def get_landmarks(image_path):
img = cv2.imread(image_path)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
faces = detector(gray)
if len(faces) == 0:
raise ValueError("顔が見つかりませんでした")
shape = predictor(gray, faces[0])
landmarks = np.array([[p.x, p.y] for p in shape.parts()])
return landmarks
ここでは、ランドマークの取得と特徴量を抽出しています。
まず画像を読み込み、グレースケールに変換します。
続いて、顔を検出し、最初に見つかった顔に対してランドマーク(目、鼻、口、輪郭など68点)を取得します。そして、取得した点をNumPy配列として返却します。
def extract_detailed_features(landmarks):
features = {}
features["eye_width_L"] = np.linalg.norm(landmarks[36] - landmarks[39])
features["eye_width_R"] = np.linalg.norm(landmarks[42] - landmarks[45])
...
return features
ここでは特徴の抽出と差分の計算をしています。
顔の各パーツ(目の横幅・間隔・鼻の長さ・唇の厚み・顔全体の比率など)を定義し、
np.linalg.norm
で2点間の距離を測定し、特徴として記録します。
ちなみに、landmarks[36]
や landmarks[39]
は、dlibの68点顔ランドマークモデルにおける 特定の顔パーツの座標 を意味します。
このモデルでは、以下は主な番号の意味です:
範囲 | 部位 | 説明 |
---|---|---|
0–16 | 顎ライン | あごの左端から右端まで |
17–21 | 左眉毛 | 左目の上の眉毛 |
22–26 | 右眉毛 | 右目の上の眉毛 |
27–30 | 鼻筋 | 眉間から鼻の先へ |
30–35 | 鼻の下部 | 鼻のふくらみ部分 |
36–41 | 左目 | 6点で囲まれる輪郭 |
42–47 | 右目 | 同様に6点で囲まれる輪郭 |
48–59 | 外唇 | 唇の輪郭部分 |
60–67 | 内唇 | 唇の内側の輪郭 |
landmarks_self = get_landmarks(self_image_path)
landmarks_ideal = get_landmarks(ideal_image_path)
features_self = extract_detailed_features(landmarks_self)
features_ideal = extract_detailed_features(landmarks_ideal)
for key in features_self:
diff = features_self[key] - features_ideal[key]
print(f"{key}: {diff:+.2f}")
自分と理想の顔のランドマークを比較し、各特徴量の差分を出力します。
出力結果を見てみる
以下は私の顔と理想の顔のランドマークを比較した結果です。
それぞれの項目は、私の顔の特徴が理想の顔と比べてどれだけ大きいか(プラスの値)
または小さいか(マイナスの値)の差分を示しています。
🔍 顔の特徴差分:
eye_width_L: +96.17
eye_width_R: +91.66
eye_distance: +155.96
nose_length: +192.96
nose_width: +97.02
nose_bridge_width: +47.98
mouth_width: +169.07
upper_lip_thickness: +28.00
lower_lip_thickness: +37.97
forehead_height: +96.50
brow_length_L: +183.88
brow_length_R: +154.48
brow_gap: +108.98
jaw_width: +410.44
chin_sharpness: +45.51
face_height: +390.80
face_width: +497.58
face_ratio: +0.04
表にまとめてみました。
特徴名 | 説明(何を測っているか) | 差分がプラスの場合の意味 |
---|---|---|
eye_width_L | 左目の目尻〜目頭の距離 | 左目が横に広い |
eye_width_R | 右目の目尻〜目頭の距離 | 右目が横に広い |
eye_distance | 左目の目頭〜右目の目頭の距離 | 目の間隔が広い(離れ目寄り) |
nose_length | 鼻の付け根(眉間)〜鼻先の距離 | 鼻が長い |
nose_width | 小鼻の端〜小鼻の端の距離 | 鼻が横に広い(小鼻が張っている) |
nose_bridge_width | 鼻筋の幅(鼻の上部の幅) | 鼻筋が太い |
mouth_width | 口角〜口角の距離 | 口が大きく見える |
upper_lip_thickness | 上唇の厚さ | 上唇が厚い |
lower_lip_thickness | 下唇の厚さ | 下唇が厚い |
forehead_height | 眉間〜額の上部の距離 | 額が広い(生え際が上にある印象) |
brow_length_L | 左眉の長さ | 左眉が長い |
brow_length_R | 右眉の長さ | 右眉が長い |
brow_gap | 左右眉の内側間の距離(眉間の広さ) | 眉間が広い |
jaw_width | 顎(エラ)の横幅 | 顎が広い、エラが張っている印象 |
chin_sharpness | 顎の尖り具合 | 顎が丸い、または前に出ている |
face_height | 眉間〜顎先までの顔の高さ | 顔が長い(面長) |
face_width | 顔の横幅(こめかみ〜こめかみ) | 顔の横幅が広い(横長) |
face_ratio | 顔の縦横比(face_height ÷ face_width) | 面長寄り |
まとめ
「黄金比」だけに頼らず、自分と理想の“差分”に注目したメイク分析は、結構実用的だと思いました。
“なりたい自分”に近づくためのアプローチとして、ぜひ取り入れてみてください😊
ありがとうございました!
コメント