溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

怎么用github寫個口紅色號識別器

發(fā)布時間:2021-11-06 11:38:41 來源:億速云 閱讀:171 作者:iii 欄目:web開發(fā)

這篇文章主要介紹“怎么用github寫個口紅色號識別器”,在日常操作中,相信很多人在怎么用github寫個口紅色號識別器問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”怎么用github寫個口紅色號識別器”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習(xí)吧!

來自 Github 的口紅色號宇宙

要想識別口紅色號,先得讓機器知道到底都有哪些顏色。

聽柜姐介紹,紅色系有:“草莓紅、鐵銹紅、楓葉紅...”,其他還有“豆沙色、吃土色、番茄色...”

怎么用github寫個口紅色號識別器

世界觀還未建立完全就要開始土崩瓦解,這看著有區(qū)別嗎?“豆沙色最為百搭,橘調(diào)的番茄色比較顯白...”眼前的黑不是黑,你說的紅是什么紅?

怎么用github寫個口紅色號識別器

還好,在萬能的 Github  上找到了一個寶藏數(shù)據(jù)庫“口紅顏色可視化”,這個數(shù)據(jù)庫堪比口紅的色號宇宙,不僅囊括了當前最主流品牌的各種系列色號,還很良心的在色盤上排列了出來。

這個數(shù)據(jù)集是一個嵌套的字典數(shù)據(jù)結(jié)構(gòu),存為 json 串的形式,里面記錄了每個口紅品牌系列下不同口紅色號的顏色 id、名稱、和 16 進制顏色值。

直!男!救!星!有木有!

口紅色號可視化鏈接:

https://github.com/Ovilia/lipstick

不過看著這密密麻麻的顏色,真心佩服各大口紅品牌的文案高手,是怎么樣區(qū)別每一個看不出區(qū)別的顏色,并且還要分別取名字的。

怎么用github寫個口紅色號識別器

傻傻分不清的我對 5 個品牌的不同系列做了一下統(tǒng)計和色號錄入,于是,剩下的就交給計算機啦。

先用番茄做個實驗?

既然有了如此完備的色號數(shù)據(jù)庫,那么文摘菌就有了一個討巧的方法:要想找到合適的色號,可以直接截取顏色,然后在數(shù)據(jù)庫中進行比對。

這個方法非常好操作,在上唇色之前,我們不如先拿別的紅色物品來練手。

比如,這里有一只番茄圖片,你看這個番茄它又大又圓:

怎么用github寫個口紅色號識別器

在其中截取了成色均勻、無高亮的矩形圖片:

怎么用github寫個口紅色號識別器

提取這張純色圖片的 RGB 值在技術(shù)上是可行的,getcolor.py 代碼如下:

import colorsys import PIL.Image as Image  def get_dominant_color(image):     max_score = 0.0001     dominant_color = None     for count,(r,g,b) in image.getcolors(image.size[0]*image.size[1]):         # 轉(zhuǎn)為HSV標準         saturation = colorsys.rgb_to_hsv(r/255.0, g/255.0, b/255.0)[1]         y = min(abs(r*2104+g*4130+b*802+4096+131072)>>13,235)         y = (y-16.0)/(235-16)          #忽略高亮色         if y > 0.9:             continue         score = (saturation+0.1)*count         if score > max_score:             max_score = score             dominant_color = (r,g,b)     return dominant_color

為了減少誤差,需要裁剪多個不同位置的圖片,保存在本地的一個文件夾中,讀取文件,提取顏色,求平均值,得到的番茄最終的 RGB 顏色,代碼如下:

import os import getcolor from os.path import join as pjoin from scipy import misc  def load_color(color_dir,list):      count = 0     for dir in os.listdir(color_dir):           img_dir = pjoin(color_dir, dir)           image = getcolor.Image.open(img_dir)         image = image.convert('RGB')         get=getcolor.get_dominant_color(image)         list.append(get)         count = count+1         #print(person_dir)     #print(count)     return count  def Mean_color(count,list):      Mean_R=Mean_G=Mean_B=0      for i in range(count):         tuple=list[i]         Mean_R+=tuple[0]         Mean_G+=tuple[1]         Mean_B+=tuple[2]      MeanC=((int)(Mean_R/count),(int)(Mean_G/count),(int)(Mean_B/count))      return Me

番茄的顏色提取到了,那么和什么做比對呢?

當然是口紅的數(shù)據(jù),文摘菌這兒用到了 5 個品牌,分別是圣羅蘭、香奈兒可可小姐、迪奧、美寶蓮、紀梵希,共 17 個系列,271 個口紅色號。

數(shù)據(jù)集是一個嵌套的字典數(shù)據(jù)結(jié)構(gòu),存為 json 串的形式,里面記錄了每個口紅品牌系列下不同口紅色號的顏色 id、名稱、和 16 進制顏色值。

lipstick.json部分數(shù)據(jù)集展示如下:

{"brands":[{"name":"圣羅蘭","series": [{"name":"瑩亮純魅唇膏","lipsticks": [{"color":"#D62352","id":"49","name":"撩騷"}, {"color":"#DC4B41","id":"14","name":"一見傾心"}, {"color":"#B22146","id":"05","name":"浮生若夢"},

數(shù)據(jù)集中存儲的 RGB 顏色是 16 進制的字符串形式,需要將其轉(zhuǎn)換成 RGB 值,比較兩個顏色相近與否。

實際上是比較 RGB 三個分量維度上的誤差,最小的口紅輸出對應(yīng)的品牌、系列、色號和 id。

代碼如下:

import json import getcolor import numpy as np import lipcolor  #filename = 'temp.txt' ##write the temp data to file## def WtoFile(filename,RGB_temp):     num=len(RGB_temp)     with open(filename,'w') as f:         for i in range(num):            s = str(RGB_temp[i]).replace('[','').replace(']','')            f.write(s)            f.write("\n")  #operate the data # ##save the brand&series&color id&color name to sum_list## ##covert the color #D62352 to RGB_array## ##caculate the RGB difference to RGB_temp and write the value to file## def data_operate():     with open('lipstick.json', 'r', encoding='utf-8') as f:       ret_dic = json.load(f)       #print(ret_dic['brands'])       #print(type(ret_dic)) # <class 'dict'>       #print(ret_dic['brands'][0]['name'])        b_num=len(ret_dic['brands'])       #print(b_num)#brands number        s_list=[]       #series brands#       for i in range(len(ret_dic['brands'])):           s_num=len(ret_dic['brands'][i]['series'])           s_list.append(s_num)           #print("{0} has {1} series".format((ret_dic['brands'][i]['name']),(s_list[i])))         #the lipstick color of every brands every series#       #the first loop calculate the total color numbers       sum=0       for b1 in range(b_num):           for s1 in range(s_list[b1]):               brand_name=ret_dic['brands'][b1]['name']               lip_name=ret_dic['brands'][b1]['series'][s1]['name']               color_num=len(ret_dic['brands'][b1]['series'][s1]['lipsticks'])               sum+=color_num#calculate the total color numbers        #the second loop save the message to a list#       sum_list=np.zeros((sum,4), dtype=(str,8))       value_array=np.zeros((sum,6), dtype=int)       i=0           for b2 in range(b_num):           for s2 in range(s_list[b2]):               brand_name=ret_dic['brands'][b2]['name']               #print(type(brand_name))               lip_name=ret_dic['brands'][b2]['series'][s2]['name']               color_num=len(ret_dic['brands'][b2]['series'][s2]['lipsticks'])               for c in range(color_num):                     color_value=ret_dic['brands'][b2]['series'][s2]['lipsticks'][c]['color']                     color_name=ret_dic['brands'][b2]['series'][s2]['lipsticks'][c]['name']                     color_id=ret_dic['brands'][b2]['series'][s2]['lipsticks'][c]['id']                     #print("{0} series {1} has {2} colors,color {3}:{4}".format(brand_name,lip_name,color_num,c+1,color_name))                     sum_list[i][0]=brand_name                     sum_list[i][1]=lip_name                     sum_list[i][2]=color_id                     sum_list[i][3]=color_name                     #value_array[i]=value_array[i][1]                     #convert "#D62352" to [13  6  2  3  5  2]#                     for l in range(6):                         temp=color_value[l+1]                         if(temp>='A'and temp<='F'):                            temp1=ord(temp)-ord('A')+10                         else:                            temp1=ord(temp)-ord('0')                         value_array[i][l]=temp1                     i+=1       #the third loop covert value_array to RGB_array#       RGB_array=np.zeros((sum,3), dtype=int)       for i in range(sum):           RGB_array[i][0]=value_array[i][0]*16+value_array[i][1]           RGB_array[i][1]=value_array[i][2]*16+value_array[i][3]           RGB_array[i][2]=value_array[i][4]*16+value_array[i][5]        #calculate the similar and save to RGB_temp       #RGB_temp=np.zeros((sum,1), dtype=int)       RGB_temp=np.zeros((sum,1), dtype=float)       for i in range(sum):           R=RGB_array[i][0]           G=RGB_array[i][1]           B=RGB_array[i][2]           RGB_temp[i]=abs(get[0]-R)+abs(get[1]*3/4-G)+abs(get[2]-B)       RGB_temp.tolist();#covert array to list       #print(RGB_temp)       filename="temp.txt"       WtoFile(filename,RGB_temp)       #sort the RGB_temp#       result=sorted(range(len(RGB_temp)), key=lambda k: RGB_temp[k])       #print(result)       #output the three max prob of the lipsticks#       print("The first three possible lipstick brand and color id&name are as follows:")       for i in range(3):           idex=result[i]           print(sum_list[idex])       print("The first three possible lipstick brand RGB value are as follows:")       for i in range(3):           idex=result[i]           R=RGB_array[idex][0]           G=RGB_array[idex][1]           B=RGB_array[idex][2]           tuple=(R,G,B)           print(tuple)   if __name__ == '__main__':      #image = getcolor.Image.open(inputpath)      #image = image.convert('RGB')      #get=getcolor.get_dominant_color(image)#tuple #get=(231, 213, 211)      list=[]      color_dir="output"      count=lipcolor.load_color(color_dir,list)      get=lipcolor.Mean_color(count,list)      print("the extracted RGB value of the color is {0}".format(get))      #operate the data#      data_operat

輸出最有可能吻合番茄顏色的前三個口紅的信息,然后在 Spyder 中的運行結(jié)果:

怎么用github寫個口紅色號識別器

可以看到最有可能的三個口紅品牌色號的 RGB 值與番茄的 RGB 值是非常接近的。

提取到的番茄顏色:

怎么用github寫個口紅色號識別器

'迪奧' '烈艷藍金唇膏' '080' '微笑正紅&rsquo;的顏色:

怎么用github寫個口紅色號識別器

'圣羅蘭' '純口紅' '56' '橙紅織錦'的顏色:

怎么用github寫個口紅色號識別器

'紀梵希' '高定香榭天鵝絨唇' '325' '圣水紅'的顏色:

怎么用github寫個口紅色號識別器

我已經(jīng)眼花繚亂,三個顏色&hellip;&hellip;有區(qū)別嗎?!以后不如準備統(tǒng)一叫它們,番茄色!

怎么用github寫個口紅色號識別器

不過,這也正說明了,剛剛的提取&對比方法可行!

既然可以識別番茄的顏色,那么,可以識別人像中的口紅色號嗎?

進入正題!人像口紅色號識別

接下來,我們需要做的是輸入一張人像圖片,可以自動識別其中的嘴唇區(qū)域,并提取出嘴唇區(qū)域中的一部分做為顏色提取的源圖像。

這里就要用到 CV 的人臉識別了,還好 Dlib 庫又幫助我們減輕一大部分的工作量。

Dlib 中有自帶的 68  個人臉的識別器,可以得到人臉部位包括眉毛、眼睛、鼻梁、面部輪廓和嘴唇區(qū)域的具體點的位置,到這兒,我以為很輕松就可以截到嘴唇區(qū)域了,結(jié)果有點尷尬.........

我們首先找到了一張小姐姐的照片:

怎么用github寫個口紅色號識別器

截取到的嘴唇區(qū)域如下:

怎么用github寫個口紅色號識別器

很明顯的看到上下嘴唇黑色的區(qū)域也截取到了,這對后續(xù)的提色有影響,所以不得不回到最初的 68  個檢測點來思考人生。

怎么用github寫個口紅色號識別器

圣羅蘭官網(wǎng) #842C71 口紅

標記的 68 個人臉檢測點如上圖所示,而嘴唇部位是從第 49 個標記點開始的(數(shù)組的話,下標是 48)。

為了盡可能的截取到均勻成色的嘴唇片段,剛開始是想從第 50 個標記點對角線截取到第 56  個標記點,而這不可避免的會截取到上下嘴唇之間的縫隙,這兒的陰影也會影響后續(xù)的顏色提取準確度。

考慮到下嘴唇比上嘴唇寬,所以截取到下嘴唇中間的兩個小正方形區(qū)域:

怎么用github寫個口紅色號識別器怎么用github寫個口紅色號識別器

人臉識別和截取嘴唇區(qū)域的代碼如下:

import numpy as np  import cv2 import dlib from PIL import Image  def crop(source,pos):        x1=pos[2][0]       y1=pos[2][1]       x2=pos[1][0]       y2=pos[1][1]       d=abs(x2-x1)       region = source[(int)(y1-d*0.75):y2,x1:x2]       # save the image       cv2.imwrite("output/Mouth2.jpg", region)        x1=pos[1][0]       y1=pos[1][1]       x2=pos[0][0]       y2=pos[0][1]       d=abs(x1-x2)       region = source[y1-d:y2,x1:x2]       # save the image       cv2.imwrite("output/Mouth3.jpg", region)   def detect_mouth(img,pos):         gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)         gray = cv2.equalizeHist(gray)         detector = dlib.get_frontal_face_detector()         #use the predictor          predictor = dlib.shape_predictor('shape_predictor_68_face_landmarks.dat')         dets = detector(img, 1)            print("Number of faces detected: {}".format(len(dets)))         for a in dets:                cv2.rectangle(img,(a.left(),a.top()),(a.right(),a.bottom()),(255,0,0))         #point_list=[]#save the mouth point to point_list[]#         #Extract 68 feature points of the face and crop the lip image#         for index, face in enumerate(dets):            print('face {}; left {}; top {}; right {}; bottom {}'.format(index, face.left(), face.top(), face.right(), face.bottom()))            shape = predictor(gray, face)            for i, pt in enumerate(shape.parts()):             #print('Part {}: {}'.format(i, pt))             #print(i)              pt_pos = (pt.x, pt.y)              if i>=48 and i<=67:                 cv2.circle(img, pt_pos, 2, (255, 0, 0), 1)              if i>=56 and i<=58:                 #print(pt_pos)                 pos[i-56][0]=pt.x                 pos[i-56][1]=pt.y              #cv2.circle(img, pt_pos, 2, (255, 0, 0), 1)         return img  if __name__ == "__main__":        img = cv2.imread("test3.png")       #copy the input image for the later crop#       img_clone = np.copy(img)       cv2.imwrite("input/source.jpg",img_clone)       #save the lip position to pos array#       pos=np.zeros((3,2), dtype=int)       result=detect_mouth(img,pos)       cv2.imwrite("input/source2.jpg",result)       #crop the lip areas#       source = cv2.imread("input/source.jpg")       crop(source,pos)       # show the result       cv2.imshow('FaceDetect',result)       cv2.waitKey(0)        cv2.destroyAllWindow

既然已經(jīng)截取到嘴唇的小矩形圖像了,接下來的工作就和前面一樣了,在數(shù)據(jù)庫中對比每個 RGB 值輸出最小誤差對應(yīng)的口紅信息,而這兒也有難到我。

單純的比對 RGB 分量對口紅色號來說并不適用,有可能每個分量相差很小,而疊加起來的顏色和提取到的顏色并不相似,在顏色的比對上需要手動調(diào)參。

幾經(jīng)波折,最后輸出的結(jié)果還是可以接受的,上圖人像中涂的口紅色號,感興趣的讀者可以查下正好是下面輸出排名第一的口紅信息。

怎么用github寫個口紅色號識別器

誤差分析

怎么用github寫個口紅色號識別器

對于我們測試的圖片信息,標記了嘴唇區(qū)域的特征點,我們提取到的 RGB  值(156,59,103)顏色如下所示:

怎么用github寫個口紅色號識別器

可以看到和圖片的顏色已經(jīng)十分接近了,而數(shù)據(jù)集合 lipstick.json 中這種口紅存儲的 16  進制顏色值為 #842C71,對應(yīng)的顏色如下:

怎么用github寫個口紅色號識別器

明顯看到數(shù)據(jù)集存儲的顏色和實際照片的顏色是有些許誤差的,而在本文算法實現(xiàn)過程中,又不可避免的有以下誤差:

  • 嘴唇區(qū)域截取不可避免會截取到皮膚中的一部分顏色,雖然算法已經(jīng)將那種可能降到最低。

  • 顏色提取上,雖然截取多個嘴唇圖片求平均值,但是本身的提取算法還是和實際值稍有偏差。

  • RGB 顏色相似度比對的算法也不夠精確。

  • 最最重要的是,照片必須是原圖,而且光線要自然,加了濾鏡的圖是怎么也不可能識別出來的。

以上種種,使得讓計算機快速高效地識別不同的口紅色號還是有困難的,原來計算機有時候也會很直男。

實時人像口紅色號預(yù)測

看到這兒,可能很多讀者朋友想實時地試一下能不能讓計算機判斷自己的口紅色號,這對于 OpenCV 這一強大的圖形操作庫來說,不是什么問題。

它可以打開你的攝像頭,讀取每一幀的圖片,結(jié)合前文提到的人臉識別代碼,可以實時地截取到嘴唇區(qū)域的圖片,然后交給計算機預(yù)測,從此再也不怕女朋友的靈魂拷問!

最后,附上打開攝像頭的代碼,快叫女朋友過來試下吧!

#coding=utf8 import cv2 import time print('Press Esc to exit') imgWindow = cv2.namedWindow('FaceDetect', cv2.WINDOW_NORMAL) import sys import os import dlib import glob import numpy from skimage import io def detect_face():     capInput = cv2.VideoCapture(0)     #nextCaptureTime = time.time()     faces = []     feas = []      if not capInput.isOpened(): print('Capture failed because of camera')     while 1:         ret, img = capInput.read()         gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)         gray = cv2.equalizeHist(gray)         time=0         eTime = time.time() + 0.1         detector = dlib.get_frontal_face_detector()          predictor = dlib.shape_predictor('shape_predictor_68_face_landmarks.dat')         dets = detector(gray, 1)           print("Number of faces detected: {}".format(len(dets)))         for a in dets:                cv2.rectangle(img,(a.left(),a.top()),(a.right(),a.bottom()),(255,0,0))         for index, face in enumerate(dets):            print('face {}; left {}; top {}; right {}; bottom {}'.format(index, face.left(), face.top(), face.right(), face.bottom()))            shape = predictor(gray, face)               for i, pt in enumerate(shape.parts()):             #print('Part {}: {}'.format(i, pt))              pt_pos = (pt.x, pt.y)              cv2.circle(img, pt_pos, 2, (255, 0, 0), 1)         cv2.imshow('FaceDetect',img)         if cv2.waitKey(1) & 0xFF == 27: break     capInput.release()     cv2.destroyAllWindows() if __name__ == "__main__":      detect_face()

到此,關(guān)于“怎么用github寫個口紅色號識別器”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識,請繼續(xù)關(guān)注億速云網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>

向AI問一下細節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI