乙Py先生のプログラミング教室
初学者のためのプログラミング学習サイト

opencv

サイゼリアのテイクアウトが新しくなったので
ではないですが、またまた間違い探しに挑戦です。

解説動画はこちら




前回はこちら
前回の挑戦記事 


さて今回はopnecvを用いてみます。

画像の差分を用いて答えを導こうというのは同じです。

差分があれば黒く塗ってみます。

画像はサイゼリアさんの方を見ていただければと思います。
サイゼ間違い探し


さてどうなるか?
ソースコードはこちら

opencvとnumpyで差分をみて黒く塗っています。
import cv2
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
img1 = cv2.imread('IMG/saize/saize1.png',0)
img2 = cv2.imread('IMG/saize/saize2.png',0) 
plt.figure(figsize=(20,10))
plt.imshow(np.where(img1 == img2, 1, 0))
plt.tick_params(labelbottom=False,labelleft=False,labelright=False,labeltop=False)
plt.tick_params(bottom=False,left=False,right=False,top=False)
plt.show()
download

おうふ、やっぱりちょっとは差がありますね。
左右の画像を完全一致させるのは難しいです。

ということですが、
黒いのが大きな領域は間違い部分である可能性が高いはずなので
見ていくと10個あるかもしれません。

うーんもう少しスマートにやる方法は無いものだろうか
そんなことを考えながら
サイゼのテイクアウトに舌鼓を打つ
今日この頃なのでした。

終・・・

顔の黄金比などを判定するのに使う比率を用いて
美人具合をランキングづけしてみました。

優勝者は誰でしょうか?

解説動画はこちら




さてやり方ですが
opencvを使って顔のポイントを取り
各パーツの長さを測ります。
そこから比率を出していきます。

顔のポイントを見るコードはこんな感じになります。
(要opencv,dlibのインストール)
import os
import time
import numpy as np
import cv2
import dlib
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.patches as patches
%matplotlib inline

detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor("../shape_predictor_68_face_landmarks.dat")

image_path = 'img/hashikan.png'
image = cv2.imread(image_path, cv2.IMREAD_COLOR)
rects = detector(image, 1)
for rect in rects:
    landmarks = np.matrix([[p.x, p.y] for p in predictor(image, rect).parts()])
fig, ax = plt.subplots(figsize=(16,9))
frame = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
for d in rects:
    parts = predictor(frame, d).parts()
    ax.scatter([point.x for point in parts], [point.y for point in parts])
    for k, point in enumerate(parts):
        ax.text(point.x, point.y, k)
    ax.imshow(frame)
    plt.tick_params(labelbottom=False,labelleft=False,labelright=False,labeltop=False)
    plt.show()

1000nenn

顔は68ポイントの点を取ることができます。

今回のランキングは下記の方々10人の写真で行いました。
橋本環奈 さん
有村架純 さん 
石原さとみ さん 
新垣結衣 さん
広瀬すず さん 
波瑠 さん
綾瀬はるか さん
浜辺美波 さん
桜井日奈子 さん
沢尻エリカ様


顔のパーツから比率を出すコードはこちら
def fwhrs(parts):
    height = parts[8].y - parts[21].y
    width = parts[16].x - parts[0].x
    fwhr = width/height
    return round(fwhr, 3)

def heights(parts):
    top_height = parts[33].y - parts[21].y
    bottom_height = parts[8].y - parts[33].y
    return top_height,bottom_height

def widths(parts):
    left_face = parts[16].x - parts[45].x
    left_eye = parts[45].x - parts[42].x
    middle_face = parts[42].x - parts[39].x
    right_eye = parts[39].x - parts[36].x
    right_face =parts[36].x - parts[0].x
    return left_face, left_eye, middle_face, right_eye,right_face

def mouses(parts):
    top_mouse = parts[57].y - parts[33].y
    bottom_mouse = parts[8].y - parts[57].y
    return top_mouse, bottom_mouse

df = pd.DataFrame()
for file_name in os.listdir('img'):
    frame = cv2.imread('img/'+file_name)
    dets = detector(frame[:, :, ::-1])
    if len(dets) > 0:
        parts = predictor(frame, dets[0]).parts()
        fwhr = fwhrs(parts)  
        top_height,bottom_height = heights(parts)
        left_face, left_eye, middle_face, right_eye,right_face = widths(parts)
        top_mouse, bottom_mouse = mouses(parts)
        t_dict = {'name':[file_name.replace('.png','')],
                  'fwhr':[fwhr],
                  'top_height':[top_height],
                  'bottom_height':[bottom_height],
                  'left_face':[left_face],
                  'left_eye':[left_eye],
                  'middle_face':[middle_face],
                  'right_eye':[right_eye],
                  'right_face':[right_face],
                  'top_mouse':[top_mouse],
                  'bottom_mouse':[bottom_mouse]}
        tmp = pd.DataFrame(t_dict)
        df = pd.concat([df,tmp])

df['Height-Ratio'] = df['top_height']/df['bottom_height']
df['Width-Ratio1'] = df['left_face']/df['middle_face']
df['Width-Ratio2'] = df['left_eye']/df['middle_face']
df['Width-Ratio3'] = df['right_eye']/df['middle_face']
df['Width-Ratio4'] = df['right_face']/df['middle_face']
df['Mouse-Ratio'] = df['top_mouse']/df['bottom_mouse']

ratios = ['Height-Ratio','Width-Ratio1','Width-Ratio2','Width-Ratio3','Width-Ratio4','Mouse-Ratio','fwhr']
df[ratios].mean()

difs = list(df[ratios].mean())
df['DIFF1'] = abs(difs[0] - df['Height-Ratio'] )
df['DIFF2'] = abs(difs[1]- df['Width-Ratio1'] )
df['DIFF3'] = abs(difs[2]- df['Width-Ratio2'] )
df['DIFF4'] = abs(difs[3]- df['Width-Ratio3'] )
df['DIFF5'] = abs(difs[4]- df['Width-Ratio4'] )
df['DIFF6'] = abs(difs[5]- df['Mouse-Ratio'] )
df['DIFF7'] = abs(difs[6] - df['fwhr'] )
df['total']   = df['DIFF1'] + df['DIFF2'] + df['DIFF3'] + df['DIFF4'] + df['DIFF5'] + df['DIFF6'] + df['DIFF7']

columns = ['name','total','fwhr','Height-Ratio','Width-Ratio1','Width-Ratio2','Width-Ratio3','Width-Ratio4','Mouse-Ratio']
df[columns].sort_values('total')

顔のパーツの比率を出しまして
10人の平均を出しました。

その平均との乖離が一番少ない人が
美人だろうということでランキング付けしています。

結果は
nametotal
sawarizi0.274496
haru0.475337
gakky0.545178
ishiharasatomi0.561904
hashikan0.56951
arimura0.660029
sakurai0.728494
hamabeminami0.847156
ayase0.918146
hirose1.051217

ということで
意外な結果が出ました!!!

この10人の平均に一番近かったのは
この方
sawarizi

思いっきしファイル名間違えたのですが
各パーツの整い方が一番平均に近いということで
選ばれました。

今さらですが、このやり方だと
単純に平均に近いかどうかだけなので
美人かどうかの判断にはならないですよねーー

やはり各パーツの比率とかをもっと細かくとって
機械学習で絶対的な美人度を点数化する奴を
作らないとアレですよね。

絶対美人は誰なんだろうか
日本人全員にアンケートとってみたい!!


今をときめくスーパースター
江頭2:50様と

今年引退するとかしないとか
よく分からないと噂のarashiメンバーの顔を
入れ替えて遊んでみました。



解説動画はこちら


前回やった
opencvのプログラムで
また顔の入れ替えをしてみます。


メンバー5人の

目鼻口を

江頭2:50さんの顔に当て込んでみます。



さてどうなるでしょうか!!!

・・・


・・





どーーーん
matuj

5人とも
ほぼ江頭さんになりますが
顔の特徴が微妙に出ているので
なかなか興味深いですね!!!!

5人結果の詳細は
動画をご覧くださいませ。

それでは

美人は何しても美人だろうということを
検証してみたいと思いました。

解説動画はこちら



対象者のお互いの顔を入れ替えてみました。

opencvを用いると
顔のパーツごとに判定して切り分け
お互いの顔のパーツを入れ替えることができます。

入れ替え可能なパーツは



です。

このうち
鼻や口はあまり顔の印象に
大きな影響を及ぼさないようです。

一番顔の印象を決定づけるのは



そしてやはり
顔の輪郭が大事だな
ということが分かると思います。

詳しくは
動画をご覧くださいませwww


それでは。


昔どっかの番組で
松崎しげるさんがどんどん黒くなったらいつ気づくのか?
みたいな番組をやっていたのを思い出しました。

今回はopencvを使って
画像の一部分の黒さを濃くするプログラムを作ってみました。

解説動画はこちら



ソースコードはこちら

画像はご自身で用意してくださいね。

import cv2
import numpy as np
import matplotlib.pyplot as plt
from ipywidgets import interact, IntSlider
%matplotlib inline

def detect_red_color(img):
    hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
    hsv_min = np.array([0,64,0])
    hsv_max = np.array([30,255,255])
    mask1 = cv2.inRange(hsv, hsv_min, hsv_max)
    hsv_min = np.array([150,64,0])
    hsv_max = np.array([179,255,255])
    mask2 = cv2.inRange(hsv, hsv_min, hsv_max)    
    mask = mask1 + mask2
    masked_img = cv2.bitwise_and(img, img, mask=mask)
    return masked_img

img = cv2.imread(‘ファイルパス’)
red_masked_img = detect_red_color(img)
mask_img = cv2.cvtColor(red_masked_img, cv2.COLOR_BGR2RGB)

rate1 = IntSlider(min=1 , max=20,step=1,value=20)

@interact(rate1=rate1)
def plot(rate1):
    mask = mask_img  // 20 * rate1 
    mask[mask==0]=255
    height, width, color = img.shape
    for y in range(0, height):
        for x in range(0, width):
            if (mask[y][x] < 240).all():
                img[y][x] = mask[y][x]
    plt.figure(figsize=(16,9))
    plt.imshow(img)
    plt.show()

ファイルパスの部分だけ
ご自身で用意したファイルに差し替えれば
動くと思います。

このプログラムですが
画像の色味を見てその濃さを調整するので
できれば顔以外は真っ黒な方が望ましいです。

スライダーで黒みを調整できます。
初期値は20で
この時は0%です。

スライドを左にずらして行けば
5%ずつ濃くなっていきます。

MAXにしてみると
download-1

ぶっちゃけ誰か分かりません!!!!

プログラム内で何をやっているかと言うと
まず赤みを判定して
顔のマスク部分を作る関数があります。

赤みの部分だけ抽出し
その濃さをスライダーの値から
計算して黒に近づけます。

画像は取り込んだ際に
配列で取り込まれているので
データ上は数値です。

RGB値だと
黒は0,0,0
白は255,255,255です。

単純に数値を
割って小さくすれば
黒に近づきます。

最後にマスク部分だけ
元の画像の色と入れ替えて表示
と言うことだけやっている
シンプルなプログラムです。

他の画像でも
色味を変えることはできますので
色々な方々でやってみてください。

本日はこれまで
それでは

このページのトップヘ