人脸姿态对比---挑出最接近的照片

前言:

        我们在拍照时,距离镜头的远近、侧脸程度、俯仰姿态以及环境光照等因素都不尽相同;假如我们刚拍了一张照片,那么,如何在历史照片中,挑选出一张与当前照片最相似的呢?

用途:

本文目的在于挑选出与选定照片最相似的一张照片。、

至于用途,针对不同项目有不同效果,比如:

1.在测肤软件上,可以找出一张历史照片和当前作对比,可以跟踪肌肤的变化情况。

2.应用到拍照上,连续拍n张照片(不宜过多,避免影响分析速度),若是第一张模糊了,则找一张姿态最接近的照片顶替,由此获得较好的用户体验。

基本思想:

既然我们判断人脸姿态的入手点为:距离镜头的远近、侧脸程度、俯仰姿态以及环境光照几个因素,那我们就得想办法去提取这些特征值;本文通过人脸的特征点来计算出前三个特征值,光照则通过手机自带的光强传感器获取。

上面是一个人脸的71点特征点图,想要获取71点的坐标很简单,opencv就有自带的库可以检测特征点,这里不做详细介绍。

def get_distance(files, line, arr):
    lens = len(line)
    # 眉角:3-9,左右:12-24  24-18,鼻尖26
    brow = arr[9][0] - arr[3][0]  # 眉角距离
    left = arr[24][0] - arr[12][0]
    right = arr[18][0] - arr[24][0]
    left_right = float('%.2f' %(left/right))  # 左右侧脸距离
    pitch = float(line[lens - 6])  # 鼻尖俯仰值
    light = float(line[lens-5])  # 光强值
    fm = float(line[lens-4])  # fm值

获得了特征点就开始计算特征值了,上面这段代码是用来计算特征值的:

1.眉间距越大,证明离镜头越近,反之越远-------(3-9点的水平距离);

2.左右侧脸的距离,左右内眼角到中间的距离之比------(24-12)/(18-24);

3.鼻尖俯仰值(这里直接给出来了,也可以自己计算,大概就是26-29的比例)

4.光强(通过传感器获得)

5.fm值(也叫清晰度,可以自己找段程序计算)

计算步骤:

首先,有n张图片和n个txt(保存着图片对应的特征点),如下图:

txt格式:

代码1:

import glob
from PIL import Image
import os
import numpy as np
import xlrd
import xlutils.copy
import cv2
import function


def avg(list1):
    avg = float(sum(list1)) / len(list1)
    return avg

def get_light(value, files, point1, point2):
    im = Image.open(files)
    pix = im.load()
    w1 = point1[0]
    h1 = point1[1]
    w2 = point2[0]
    h2 = point2[1]
    w = int(w2 - w1)
    h = int(h2 - h1)
    gray = []
    new_gray=[]
    for i in range(w):
        for j in range(h):
            RGB = pix[int(w1 + i), int(h1 + j)]
            gray_value = RGB[0] * 0.3 + RGB[1] * 0.59 + RGB[2] * 0.11
            gray.append(gray_value)

    #把最小的20%去掉
    lens=int(len(gray)*0.8)
    gray.sort()
    gray.reverse()
    for i in range(lens):
        new_gray.append(gray[lens])

    light = avg(gray)
    light = '%.2f' % light
    return light

def get_top_bottom_light(arr,files):
    # 确定光照区域的范围,左上角和右下角的点
    top_point1_x = (arr[24][0]-(arr[24][0]-arr[62][0])/2)
    top_point1_y = (arr[24][1]-(arr[62][1]-arr[24][1])/4)
    top_point2_x = (arr[24][0]+(arr[24][0]-arr[62][0])/2)
    top_point2_y = (arr[24][1]+(arr[62][1]-arr[24][1])/4)
    top_point1=(top_point1_x,top_point1_y)
    top_point2=(top_point2_x,top_point2_y)
    
    bottom_point1_x = (arr[25][0]-(arr[24][0]-arr[62][0])/2)
    bottom_point1_y = (arr[25][1]-(arr[62][1]-arr[24][1])/4)
    bottom_point2_x = (arr[25][0]+(arr[24][0]-arr[62][0])/2)
    bottom_point2_y = (arr[25][1]+(arr[62][1]-arr[24][1])/4)
    bottom_point1=(bottom_point1_x,bottom_point1_y)
    bottom_point2=(bottom_point2_x,bottom_point2_y)

    top_light = get_light('top', files, top_point1, top_point2)
    bottom_light = get_light('bottom', files, bottom_point1, bottom_point2)
    lights = abs(float(bottom_light) - float(top_light))
    lights = '%.2f' % lights
    table2.write(n, 5, float(lights))  # 左右脸颊光均匀性对比
    print("上下亮度对比为:", lights)
    return top_light,bottom_light,top_point1,top_point2,bottom_point1,bottom_point2

def get_left_right_light(arr,files):
    # 确定光照区域的范围,左上角和右下角的点
    left_point1 = (arr[15][0], arr[60][1])
    left_point2 = (arr[32][0], arr[64][1])
    right_point1 = (arr[67][0], arr[65][1])
    right_point2 = (arr[9][0], arr[67][1])

    left_light = get_light('left', files, left_point1, left_point2)
    right_light = get_light('right', files, right_point1, right_point2)
    lights = abs(float(right_light) - float(left_light))
    lights = '%.2f' % lights
    table2.write(n, 4, float(lights))  # 左右脸颊光均匀性对比
    print("左右亮度对比为:", lights)
    return left_light,right_light,left_point1,left_point2,right_point1,right_point2

def get_distance(files, line, arr):
    lens = len(line)
    # 眉角:3-9,左右:12-24  24-18,鼻尖26
    brow = arr[9][0] - arr[3][0]  # 眉角距离
    left = arr[24][0] - arr[12][0]
    right = arr[18][0] - arr[24][0]
    left_right = float('%.2f' %(left/right))  # 左右侧脸距离
    pitch = float(line[lens - 6])  # 鼻尖俯仰值
    light = float(line[lens-5])  # 光强值
    fm = float(line[lens-4])  # fm值

    #检查参数,固定在范围内
    if brow<1000:
        brow=1000
    elif brow>1600:
        brow=1600

    if pitch<0.7:
        pitch=0.7
    elif pitch>1.3:
        pitch=1.3

    if light>300:
        light=300

    if left_right<0.7:
        left_right=0.7
    elif left_right>1.3:
        left_right=1.3
    
    return brow, left_right, pitch, light, fm, left, right

def get_arr(line):
    lens = len(line)
    list2 = []
    for i in range(lens - 77, lens - 6):
        line[i] = line[i].strip()
        line[i] = line[i].strip('[]')
        line[i] = line[i].split(",")
        list2.append(line[i])
    arr = np.array(list2)
    arr = arr.astype(int)
    return arr

# 打开表格,选中表sheet1
path = 'data2/img/a1.xls'
data = xlrd.open_workbook(path)
ws = xlutils.copy.copy(data)
table2 = ws.get_sheet(0)
n = 0
point_list = []
path_txt = 'data2/img/1/txt/'
files = os.listdir(path_txt)
for file in files:
    if file.endswith('txt'):
        n = n + 1
        f1 = open(path_txt + file, 'r')
        line = f1.readlines()
        # txt文件名即为照片名
        lens = len(line)
        img = line[lens - 1].strip()
        files = 'data2/img/1/' + img

        arr = get_arr(line)  # 把文本特征点坐标,转化为arr,留待后用
        distance = get_distance(files, line, arr)  # 把特征点坐标取出来,计算前后左右俯仰

        table2.write(n,0,float(distance[0]))
        table2.write(n,1,float(distance[1]))
        table2.write(n,2,float(distance[2]))
        table2.write(n,3,float(distance[3]))
        table2.write(n,6,float(distance[4]))
        print("眉角间距离为:",distance[0])
        print("侧脸值为:",distance[1])
        print("俯仰值为:",distance[2])
        print("光强为:",distance[3])
        print("FM值为:",distance[4])

        light1=get_left_right_light(arr,files)
        light2=get_top_bottom_light(arr,files)
        print("第" + str(n) + "次------计算完毕")

        # #把计算区域画出来
        # save_light1='data/rect/light1/'
        # save_light2='data/rect/light2/'
        # save2='data/rect/left_right/'
        # save3='data/rect/71/'
        # function.draw_face(save_light1,files,light1[0],'left',light1[2],light1[3])     #把左右光亮度区域标记出来
        # function.draw_face(save_light1,files,light1[1],'right',light1[4],light1[5])
        # function.draw_face(save_light2,files,light1[0],'top',light2[2],light2[3])     #把光亮度区域标记出来
        # function.draw_face(save_light2,files,light1[1],'bottom',light2[4],light2[5])
        # function.draw_eye(save2,files,arr,distance[5],distance[6])     #把眼间距标记出来
        # function.draw_point(save3,files,line,arr)                      #把71点标记出来

ws.save(path)

计算每张图片的特征值

把计算结果存在一个表格中

代码2:

把每一张照片的特征值,和当前的照片作对比(或者选取中位数),并建立罚分制度,挑出罚分最小的一张,即是最接近当前照片。

import xlrd
import xlutils.copy
import os
import numpy as np

def avg(num):
    average = float(sum(num)) / len(num)
    return average

def get_max(a, b):
    if a > b:
        return a
    else:
        return b

def get_proportion1(row3,proportion1,x,y):
    old_list = []
    list_score = []
    for j in range(1, row3-1):  # row3-1是为了把最后一次的数据排除在外
        score = table3.cell_value(j, 6)
        old_list.append(float(score))
        list_score.append(float(score))
    list_score.sort()
    print(old_list)

    for i in range(x):
        a = list_score[i]
        n = old_list.index(a) + 1
        print("第" + str(n) + "张照片的占比为:" + proportion1[y][i+1])

    last_value=table3.cell_value(row3-1,6)
    print('当前照片总罚分为:',last_value,'得分占比为:',proportion1[y][0])

def get_proportion2(row3,proportion2,x,y):
    #1.遍历数据,填入数列,排序
    old_list = []
    list_score = []
    for j in range(1, row3 - 1):  # row3-1是为了把最后一次的数据排除在外
        score = table3.cell_value(j, 7)
        old_list.append(float(score))
        list_score.append(float(score))
    list_score.sort()
    #2.选出前五,放入数列
    list1=[]
    indexs=[]
    for i in range(x):
        a = list_score[i]                #遍历前五个数
        index1 = old_list.index(a) + 1   #找出前五个数在原数列中的位置
        list1.append(a)
        indexs.append(index1)
    #3.把最后一位数放入前五的数列,得到index2,选定第几套方案
    last_value=float(table3.cell_value(row3-1,7))
    list1.append(last_value)
    list1.sort()
    index2=list1.index(last_value)    #最后一张照片放进前五个数之后的位置
    plan=proportion2[y][index2]       #选定第n套方案

    print(list1,last_value)
    print('选用第'+str(y+1)+'组,第'+str(index2+1)+'套方案:',plan)
    print('当前照片占比为:',plan[0])
    for j in range(x):
        print('第'+str(indexs[j])+'张照片占比为:',plan[j+1])

def choose_plan1(row3,proportion1):
    if (row3-2)>=5:
        get_proportion1(row3,proportion1,5,0)
    elif (row3-2)==4:
        get_proportion1(row3,proportion1,4,1)
    elif (row3-2)==3:
        get_proportion1(row3,proportion1,3,2)
    elif (row3-2)==2:
        get_proportion1(row3,proportion1,2,3)
    elif (row3-2)==1:
        get_proportion1(row3,proportion1,1,4)
    elif (row3-2)==0:
        get_proportion1(row3,proportion1,0,5)

def choose_plan2(row3,proportion1):
    if (row3-2)>=5:
        get_proportion2(row3,proportion2,5,0)
    elif (row3-2)==4:
        get_proportion2(row3,proportion2,4,1)
    elif (row3-2)==3:
        get_proportion2(row3,proportion2,3,2)
    elif (row3-2)==2:
        get_proportion2(row3,proportion2,2,3)
    elif (row3-2)==1:
        get_proportion2(row3,proportion2,1,4)
    elif (row3-2)==0:
        get_proportion2(row3,proportion2,0,5)

# 计算sheet3的和,得到总分
def get_sum(row1, n):
    for i in range(1, row1):
        sums = 0
        for j in range(7):
            temp4 = float(table3.cell_value(i, j))
            sums += temp4

        makeup_code=table3.cell_value(i, 8)   #检查是否化妆,化妆则扣100分
        if makeup_code==1:
            sums=100
        table3_w.write(i, n, "%.2LF" % sums)
        print("第" + str(i) + "张图片,综合差异为:", sums)

def get_fm(row1, n, min, max, weight):
    for j in range(1, row1):
        fm = table1.cell_value(j, 6)
        if fm >= max:
            score = 0
        else:
            score = weight * (1 - (fm / max))
        score = "%.2LF" % score
        table3_w.write(j, n, score)
        # print(fm)

# 计算得分
def get_score(row1, n, min, max, weight):
    median = float(table2.cell_value(n + 1, 7))
    a = median - min
    b = max - median
    max_num = float("%.2LF" % get_max(a, b))
    for j in range(1, row1):
        temp1 = float(table1.cell_value(j, n))
        temp3 = abs(temp1 - median)
        if temp3 >= max_num:
            score = weight
        else:
            score = (temp3 / max_num) * weight
        score = "%.2LF" % score
        table3_w.write(j, n, score)
        print(score)

# 计算sheet1中6列指标的中位数
def get_median(row1):
    for i in range(7):
        lists = []
        for j in range(1, row1):
            col_value = table1.cell_value(j, i)
            lists.append(col_value)
        lists.sort()
        median="%.2LF" %(np.median(lists))
        table2_w.write(i + 1, 7, float(median))
        # print(median)

# 打开表格,选中表sheet1
path = 'data2/img/a1.xls'
data = xlrd.open_workbook(path)
ws = xlutils.copy.copy(data)
table1_w = ws.get_sheet(0)
table2_w = ws.get_sheet(1)
table3_w = ws.get_sheet(2)
table1 = data.sheets()[0]
table2 = data.sheets()[1]
table3 = data.sheets()[2]
row1 = table1.nrows
row2 = table2.nrows
row3 = table3.nrows
proportion1 = [['30%','18%','16%','14%','12%','10%'],['30%','25%','20%','15%','10%'],
['40%','30%','20%','10%'],['40%','35%','25%'],['50%','50%'],['100%']]

proportion2=[
[['70%','10%','8%','6%','4%','2%'],['60%','12%','10%','8%','6%','4%'],['50%','14%','12%','10%','8%','6%'],
['40%','16%','14%','12%','10%','8%'],['30%','18%','16%','14%','12%','10%'],['20%','20%','18%','16%','14%','12%']],

[['70%','10%','8%','7%','5%'],['60%','13%','11%','9%','7%'],['50%','15%','13%','12%','10%'],
['40%','18%','16%','14%','12%'],['32%','20%','18%','16%','14%']],

[['60%','16%','14%','10%'],['50%','22%','17%','11%'],['40%','25%','22%','13%'],['30%','30%','25%','15%']],

[['60%','25%','15%'],['50%','30%','20%'],['40%','35%','25%']],

[['60%','40%'],['40%','60%']],

[['100%']]
]

# get_median(row1)                 #计算sheet1每一列指标的均值
# get_score(row1,0,1000,1600,20)   #1.远近距离得分
# get_score(row1,1,0.7,1.3,10)     #2.侧脸得分
# get_score(row1,2,0.7,1.3,20)     #3.俯仰得分
# get_score(row1,3,0,300,10)       #4.光强得分
# get_score(row1,4,0,100,15)       #5.左右亮度差得分
# get_score(row1,5,0,20,5)        #6.上下亮度差得分
# get_fm(row1,6,0,80,20)           #7.清晰度得分
# get_sum(row1,7)                  #求得分总和,得到综合差异
# choose_plan2(row3,proportion2)   #选用评分占比方案

ws.save(path)


# getget_score(总行数,第几列,min,max,分值权重)
# 1.远近   min:1000  max:1600,与均值最大偏差:min-avg or max-avg
# 2.侧脸   min:0.7     max:120,与均值最大偏差:min-avg or max-avg
# 3.俯仰   min:0.7   max:1.3,与均值最大偏差:min-avg or max-avg
# 4.光强   min:10    max:300,与均值最大偏差:min-avg or max-avg
# 5.左右亮度差 min:0     max:100,与均值最大偏差:min-avg or max-avg
# 6.清晰度80以上算满分

#评分方案2:
#用了6套评分参数,根据当前照片的综合分数排名,来选定用第几套评分参数;
#例如:当前分数排在第5,则选用第五套评分参数

代码3:存放函数的文件—function.py

import glob
from PIL import Image
import os
import numpy as np
import xlrd
import xlutils.copy
import cv2
import math
import time

#计算数据
def avg(num):
    average = float(sum(num)) / len(num)
    return average

def get_max(a, b):
    if a > b:
        return a
    else:
        return b

def get_finally_score(old_data,proportion,now_score,x):
    finally_score=[]
    for i in range(9):
        sums=0
        for j in range(x):
            index=proportion[0][j]     #每张照片的排名
            pro=proportion[1][j]       #每张照片所占的比例
            score=old_data[index][1]   #取得index行的一行分数
            new_score=[(num*pro)/100 for num in score]     #经过比例相乘后的分数
            a=new_score[i]
            sums+=a

        sums = float("%.2LF" % sums)               #历史照片分数
        score=float("%.2LF" %((now_score[i]*proportion[1][x])/100))   #当前照片分数
        score_sum=round(sums+score)     #四舍五入取整法
        # score_sum=float("%.2LF" %(sums+score))   #保留两位小数
        finally_score.append(score_sum)
    return finally_score

def get_proportion1(score_sum,rows,proportion1,x,y):
    new_list = []
    for i in range(rows):
        new_list.append(score_sum[i])
    new_list.sort()

    proportion=[[],[]]
    for i in range(x):
        a = new_list[i]
        n = score_sum.index(a)
        proportion[0].append(n)        #最低5次罚分,在历史中的位置
        proportion[1].append(proportion1[y][i+1])    #5张照片分别对应的占比
    proportion[1].append(proportion1[y][0])      #当次照片所占比例
    return proportion,x

def choose_plan1(score_sum,rows,proportion1):
    if (rows)>=5:
        proportion=get_proportion1(score_sum,rows,proportion1,5,0)
    elif (rows)==4:
        proportion=get_proportion1(score_sum,rows,proportion1,4,1)
    elif (rows)==3:
        proportion=get_proportion1(score_sum,rows,proportion1,3,2)
    elif (rows)==2:
        proportion=get_proportion1(score_sum,rows,proportion1,2,3)
    elif (rows)==1:
        proportion=get_proportion1(score_sum,rows,proportion1,1,4)
    elif (rows)==0:
        proportion=get_proportion1(score_sum,rows,proportion1,0,5)
    return proportion[0],proportion[1]

# 计算sheet3的和,得到总分
def get_sum(score_all,rows,n):
    score_sum=[]
    for i in range(rows):
        sums = 0
        for j in range(n):
            temp = score_all[j][i]
            sums += temp
        sums = float("%.2LF" % sums)
        score_sum.append(sums)
    return score_sum

def get_fm(old_data,rows, n, min, max, weight):
    scores=[]
    for i in range(rows):
        fm=old_data[i][0][n]      #历史数据中,i行n列的值
        if fm >= max:
            score = 0
        else:
            score = weight * (1 - (fm / max))
        score = float("%.2LF" % score)
        scores.append(score)
    return scores

# 计算得分
def get_score(old_data,rows,median_list,n,min,max,weight):
    median=median_list[n]
    a = median - min
    b = max - median
    max_num = float("%.2LF" % get_max(a, b))
    scores=[]
    for i in range(rows):
        col_value=old_data[i][0][n]      #历史数据中,i行n列的值
        result = abs(col_value - median)
        if result >= max_num:
            score = weight
        else:
            score = (result / max_num) * weight
        score = float("%.2LF" % score)
        scores.append(score)
    return scores

# 计算sheet1中6列指标的中位数
def get_median(old_data,rows):
    median_list=[]
    for i in range(7):
        lists = []
        for j in range(rows):
            col_value = old_data[j][0][i]
            lists.append(col_value)
        lists.sort()
        median=float("%.2LF" %(np.median(lists)))
        median_list.append(median)
    return median_list

def get_light(files, point1, point2):
    im = Image.open(files)
    pix = im.load()
    w1 = point1[0]
    h1 = point1[1]
    w2 = point2[0]
    h2 = point2[1]
    w = int(w2 - w1)
    h = int(h2 - h1)
    gray = []
    new_gray=[]
    for i in range(w):
        for j in range(h):
            RGB = pix[int(w1 + i), int(h1 + j)]
            gray_value = RGB[0] * 0.3 + RGB[1] * 0.59 + RGB[2] * 0.11
            gray.append(gray_value)

    #把最小的20%去掉
    lens=int(len(gray)*0.8)
    gray.sort()
    gray.reverse()
    for i in range(lens):
        new_gray.append(gray[lens])

    light = avg(gray)
    light = float('%.2f' % light)
    return light

def get_top_bottom_light(point,files):
    # 确定光照区域的范围,左上角和右下角的点
    top_point1_x = (point[24][0]-(point[24][0]-point[62][0])/2)
    top_point1_y = (point[24][1]-(point[62][1]-point[24][1])/4)-100
    top_point2_x = (point[24][0]+(point[24][0]-point[62][0])/2)
    top_point2_y = (point[24][1]+(point[62][1]-point[24][1])/4)-100
    top_point1=(top_point1_x,top_point1_y)
    top_point2=(top_point2_x,top_point2_y)
    
    bottom_point1_x = (point[25][0]-(point[24][0]-point[62][0])/2)
    bottom_point1_y =    (point[25][1]-(point[62][1]-point[24][1])/4)
    bottom_point2_x = (point[25][0]+(point[24][0]-point[62][0])/2)
    bottom_point2_y = (point[25][1]+(point[62][1]-point[24][1])/4)
    bottom_point1=(bottom_point1_x,bottom_point1_y)
    bottom_point2=(bottom_point2_x,bottom_point2_y)

    top_light = get_light(files, top_point1, top_point2)
    bottom_light = get_light(files, bottom_point1, bottom_point2)

    lights = abs(float(bottom_light) - float(top_light))
    lights = float('%.2f' % lights)
    return lights,top_light,bottom_light,top_point1,top_point2,bottom_point1,bottom_point2

def get_left_right_light(point,files):
    # 确定光照区域的范围,左上角和右下角的点
    left_point1 = (point[15][0], point[60][1])
    left_point2 = (point[32][0], point[64][1])
    right_point1 = (point[67][0], point[65][1])
    right_point2 = (point[9][0], point[67][1])

    left_light = get_light(files, left_point1, left_point2)   #计算左脸亮度
    right_light = get_light(files, right_point1, right_point2)   #计算右脸亮度

    lights = abs(float(right_light) - float(left_light))
    lights = float('%.2f' % lights)
    return lights,left_light,right_light,left_point1,left_point2,right_point1,right_point2

def get_distance(point,data1):
    # 眉角:3-9,左右:12-24  24-18,鼻尖26
    brow = point[9][0] - point[3][0]  # 眉角距离
    left = point[24][0] - point[12][0]
    right = point[18][0] - point[24][0]
    left_right = float('%.2f' %(left/right))  # 左右侧脸距离

    light = float(data1[1])  # 光强
    pitch = float(data1[2])  # 鼻尖俯仰值
    fm = float(data1[3])  # fm值

    #检查参数,固定在范围内
    if brow<1000:
        brow=1000
    elif brow>1600:
        brow=1600

    if pitch<0.7:
        pitch=0.7
    elif pitch>1.3:
        pitch=1.3

    if light>300:
        light=300

    if left_right<0.7:
        left_right=0.7
    elif left_right>1.3:
        left_right=1.3
    
    return brow, left_right, pitch, light, fm, left, right

def get_old_data(now_makeup_code, now_mode, history_data):
    data1 = []
    for data in history_data:
        old_makeup_code = data[2]  # 历史数据化妆状态
        old_mode=data[4]
        old_time = data[3]  # 历史数据时间
        now_time = int(time.time())  # 当前时间
        times = now_time - old_time  # 时间间隔
        if old_makeup_code == now_makeup_code and times <= 15768000 and old_mode==now_mode:
            data1.append(data)

    old_data = []
    lens = len(data1)
    # 若是历史数据超过100,则挑出最后100条数据
    if lens > 100:
        for i in range(lens - 100, lens):
            old_data.append(data1[i])
    else:
        old_data = data1

    return old_data

def get_data():
    #now_data=[[71点],[文件名,光强,俯仰值,清晰度,是否化妆],[单项+总得分]]
    point=[[1267,1443], [1085,1386],[895,1383], [727,1452], [873,1289], [1102,1295], [1570,1380], [1722,1237], [1948,1198], [2149,1364], 
    [1953,1292], [1769,1325], [1234,1691], [1104,1702], [989,1705], [862,1680], [989,1609], [1124,1617], [1694,1642], [1791,1551], 
    [1926,1521], [2063,1573], [1939,1617], [1818,1634], [1457,1592], [1465,1835], [1476,2080], [1730,2251], [1628,2209], [1493,2278], 
    [1350,2220], [1262,2276], [1198,2623], [1278,2537], [1394,2480], [1482,2507], [1573,2471], [1730,2518], [1865,2595], [1785,2705],
    [1658,2796], [1512,2829], [1380,2807], [1270,2730], [1352,2626], [1507,2648], [1686,2615], [2347,1521], [2358,1799], [2333,2066], 
    [2278,2347], [2174,2595], [2033,2816], [1840,3031], [1589,3127], [1333,3066], [1129,2879], [958,2672], [829,2444], [730,2168], [669,1909], 
    [642,1628], [1284,1953],[1212,2096], [1223,2254], [1705,1934], [1793,2072], [1804,2229], [1493,2551], [1636,2595], [1375,2609]]
    now_Torch=['1550545615850__Torch_0_fm490.75.jpg',43.8,0.89,490.75,0,'Torch',[84,82,86,92,88,80,80,26,86]]
    now_Flash=['1550545635453__Flash_0_fm395.55.jpg',43.8,0.89,490.75,0,'Flash',[84,82,86,92,88,80,80,26,87]]
    data1=[point,now_Torch,now_Flash]

    #old_data=[眉间距,左右侧脸,俯仰值,清晰度fm,光强,左右亮度,上下亮度,[单项+总得分]]
    data2=[
	[[1422,0.94,0.89,43.8,4.06,2.67,223.45],[86,83,86,90,87,80,81,25,88],1,1550733026,'Torch'],
	[[1353,0.99,0.88,43.4,12.9,1.12,172.08],[85,92,86,82,82,84,83,25,87],0,1536753026,'Flash'],
	[[1304,0.97,0.81,42.6,2.83,4.38,206.11],[83,82,86,90,87,80,82,26,85],1,1529733326,'Flash'],
	[[1284,1.12,0.83,42.9,4.81,6.10,182.05],[84,82,86,92,88,80,80,26,86],0,1537733029,'Torch'],
	[[1395,0.79,0.85,43.8,0.18,2.10,235.35],[83,82,76,92,88,90,80,26,86],0,1538723026,'Torch'],
	[[1259,0.79,0.91,42.6,6.80,5.29,228.56],[88,82,86,92,83,80,80,26,87],0,1539753026,'Torch'],
	[[1171,0.96,0.91,42.7,1.86,6.72,242.07],[83,82,82,82,88,80,80,26,83],0,1539833056,'Torch'],
	[[1373,0.78,1.30,49.6,9.07,7.19,131.54],[84,82,81,82,88,84,80,26,84],0,1541733026,'Torch'],
	[[1328,0.86,0.82,49.9,7.12,5.70,171.93],[84,85,85,92,88,80,82,26,86],0,1545733026,'Torch'],
	[[1353,1.14,0.82,51.6,25.5,8.11,203.08],[86,82,86,90,88,80,83,26,87],0,1541733026,'Torch']
	]
    proportion1 = [[30,18,16,14,12,10],[30,25,20,15,10],[40,30,20,10],[40,35,25],[50,50],[100]]
    return data1,data2,proportion1




#1.把关键点画出来-------------------------------
def draw_point(save,files,point):
	#画出点的位置
	img = cv2.imread(files)
	for i in range(70):	
		cv2.circle(img,(point[i][0],point[i][1]),5,(0,255,0),-1)
	#保存图片
	file_name=os.path.split(files)[1]
	cv2.imwrite(save+file_name, img)

def draw_eye(save,files,point,left,right):
	#画出眼间距 点的位置
	img = cv2.imread(files)
	cv2.circle(img,(point[3][0],point[3][1]),5,(0,255,0),-1)
	cv2.circle(img,(point[9][0],point[9][1]),5,(0,255,0),-1)
	cv2.circle(img,(point[12][0],point[12][1]),5,(0,255,0),-1)
	cv2.circle(img,(point[18][0],point[18][1]),5,(0,255,0),-1)
	cv2.circle(img,(point[24][0],point[24][1]),5,(0,255,0),-1)
	#画线、标距离数值
	cv2.line(img,(point[12][0],point[12][1]),(point[24][0],point[24][1]),(255,255,255),3)
	cv2.line(img,(point[18][0],point[18][1]),(point[24][0],point[24][1]),(255,255,255),3)
	font=cv2.FONT_HERSHEY_SIMPLEX
	cv2.putText(img,str(left),(point[12][0],point[12][1]), font, 2,(255,252,255),2)
	cv2.putText(img,str(right),(point[18][0],point[18][1]), font, 2,(255,252,255),2)
	#保存图片
	file_name=os.path.split(files)[1]
	cv2.imwrite(save+file_name, img)

def draw_light_roi(save_path,files,light1,light2,point1,point2,point3,point4):
    w1=point1[0]
    h1=point1[1]
    w2=point2[0]
    h2=point2[1]
    w3=point3[0]
    h3=point3[1]
    w4=point4[0]
    h4=point4[1]
	#画出光照区域的框
    img=cv2.imread(files)
    cv2.rectangle(img,(int(w1),int(h1)),(int(w2),int(h2)),(255,0,0),3)
    cv2.rectangle(img,(int(w3),int(h3)),(int(w4),int(h4)),(255,0,0),3)
    dst = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    #把亮度数值标上去
    font=cv2.FONT_HERSHEY_SIMPLEX
    cv2.putText(img,light1,(int(w1+10),int(h1+10)), font, 2,(255,252,255),3)
    cv2.putText(img,light2,(int(w3+10),int(h3+10)), font, 2,(255,252,255),3)
    #保存图片
    file_name=os.path.split(files)[1]
    cv2.imwrite(save_path+file_name+'.jpg', img)

总结:

1.代码1是用来计算每张照片的特征值的,并放入表格存放起来;

2.代码2是把表格中的特征值拿出来进行比较,并建立了罚分制度(差别越大,罚分越多),最后挑出罚分最小的一张,获得最接近的照片。

3.代码3是前面两个的函数存放文件。

ps:代码2中的比较对象,可以选当前拍照那张(得到当前对比),也可以选所有照片罚分的中位数(得到拍照习惯),根据需要而定。

留尾:

这个文件是当时用来做评分测试的,忘记用法了,也一并先放上来吧

import xlrd
import xlutils.copy
import os
import sys
import numpy as np
import math

def get_avg(num):
    average = float(sum(num)) / len(num)
    return average

def get_max(a, b):
    if a > b:
        return a
    else:
        return b

def get_proportion1(row3,proportion1,x,y):
    old_list = []
    list_score = []
    for j in range(1, row3-1):  # row3-1是为了把最后一次的数据排除在外
        score = table3.cell_value(j, 7)
        old_list.append(float(score))
        list_score.append(float(score))
    list_score.sort()
    # print(old_list)

    score1=0
    for i in range(x):
        a = list_score[i]
        n = old_list.index(a) + 1
        # print("第" + str(n) + "张照片的占比为:" + str(proportion1[y][i+1]))
        s=table3.cell_value(n,8)*((proportion1[y][i+1])/100)
        score1=score1+s

    last_value=table3.cell_value(row3-1,7)
    # print('当前照片总罚分为:',last_value,',得分占比为:',proportion1[y][0])
    score2=table3.cell_value(row3-1,8)*(proportion1[y][0]/100)
    scores="%.2LF" %(score1+score2)
    return scores,proportion1[y][0]

def get_proportion2(row3,proportion2,x,y):
    #1.遍历数据,填入数列,排序
    old_list = []
    list_score = []
    for j in range(1, row3 - 1):  # row3-1是为了把最后一次的数据排除在外
        score = table3.cell_value(j, 7)
        old_list.append(float(score))
        list_score.append(float(score))
    list_score.sort()
    #2.选出前五,放入数列
    list1=[]
    indexs=[]
    for i in range(x):
        a = list_score[i]                #遍历前五个数
        index1 = old_list.index(a) + 1   #找出前五个数在原数列中的位置
        list1.append(a)
        indexs.append(index1)
    #3.把最后一位数放入前五的数列,得到index2,选定第几套方案
    last_value=float(table3.cell_value(row3-1,7))
    list1.append(last_value)
    list1.sort()
    index2=list1.index(last_value)    #最后一张照片放进前五个数之后的位置
    plan=proportion2[y][index2]       #选定第n套方案
    score1=0
    # print(list1,last_value)
    # print('选用第'+str(y+1)+'组,第'+str(index2+1)+'套方案:',plan)
    # print('当前照片占比为:',str(plan[0])+'%')

    for j in range(x):
        # print('第'+str(indexs[j])+'张照片占比为:',str(plan[j+1])+'%')
        a=table3.cell_value(indexs[j]+1,8)*float((plan[j+1])/100)
        score1=score1+a
    score2=table3.cell_value(row3-1,8)*float((plan[0])/100)
    scores="%.2LF" %(score1+score2)
    return scores,plan[0]


def choose_plan1(row3,proportion1):
    if (row3-2)>=5:
        a=get_proportion1(row3,proportion1,5,0)
    elif (row3-2)==4:
        a=get_proportion1(row3,proportion1,4,1)
    elif (row3-2)==3:
        a=get_proportion1(row3,proportion1,3,2)
    elif (row3-2)==2:
        a=get_proportion1(row3,proportion1,2,3)
    elif (row3-2)==1:
        a=get_proportion1(row3,proportion1,1,4)
    elif (row3-2)==0:
        a=get_proportion1(row3,proportion1,0,5)
    return a

def choose_plan2(row3,proportion1):
    if (row3-2)>=5:
        a=get_proportion2(row3,proportion2,5,0)
    elif (row3-2)==4:
        a=get_proportion2(row3,proportion2,4,1)
    elif (row3-2)==3:
        a=get_proportion2(row3,proportion2,3,2)
    elif (row3-2)==2:
        a=get_proportion2(row3,proportion2,2,3)
    elif (row3-2)==1:
        a=get_proportion2(row3,proportion2,1,4)
    elif (row3-2)==0:
        a=get_proportion2(row3,proportion2,0,5)
    return a

def var(lst):
    var1=0
    avg=get_avg(lst)
    for i in lst:
        var1+=float((i-avg)**2*1.0)
        var2=(math.sqrt(var1/(len(lst)-1)*1.0))
    return var2

# 计算sheet3的和,得到总分
def get_sum(row3, n):
    a=[]
    for i in range(1, row3):
        sums = 0
        for j in range(6):
            temp4 = float(table3.cell_value(i, j))
            sums += temp4
        table3_w.write(i, n, "%.2LF" % sums)
        print("第" + str(i) + "张图片,综合差异为:", sums)
    #     a.append(sums)
    # vars=var(a)
    # print('方差为:',vars)

def get_fm(row1, n, min, max, weight):
    for j in range(1, row1):
        fm = table1.cell_value(j, 6)
        if fm >= max:
            score = 0
        else:
            score = weight * (1 - (fm / max))
        score = "%.2LF" % score
        table3_w.write(j, n, score)
        # print(fm)

# 计算得分
def get_score(row1, n, min, max, weight):
    median = float(table2.cell_value(n + 1, 7))
    a = median - min
    b = max - median
    max_num = float("%.2LF" % get_max(a, b))
    for j in range(1, row1):
        temp1 = float(table1.cell_value(j, n))
        temp3 = abs(temp1 - median)
        if temp3 >= max_num:
            score = weight
        else:
            score = (temp3 / max_num) * weight
        score = "%.2LF" % score
        table3_w.write(j, n, score)
        # print(score)

# 计算sheet1中6列指标的中位数
def get_median(row1):
    for i in range(7):
        lists = []
        for j in range(1, row1):
            col_value = table1.cell_value(j, i)
            lists.append(col_value)
        lists.sort()
        median="%.2LF" %(np.median(lists))
        table2_w.write(i + 1, 7, float(median))
        # print(median)

# 打开表格,选中表sheet1
path = 'data/score_test/a1.xls'
data = xlrd.open_workbook(path)
ws = xlutils.copy.copy(data)
table1_w = ws.get_sheet(0)
table2_w = ws.get_sheet(1)
table3_w = ws.get_sheet(2)
table1 = data.sheets()[0]
table2 = data.sheets()[1]
table3 = data.sheets()[2]
row1 = table1.nrows
row2 = table2.nrows
row3 = table3.nrows
proportion1 = [[30,18,16,14,12,10],[30,25,20,15,10],
[40,30,20,10],[40,35,25],[50,50],[100]]

proportion2=[
[[70,10,8,6,4,2],[60,12,10,8,6,4],[50,14,12,10,8,6],
[40,16,14,12,10,8],[30,18,16,14,12,10],[20,20,18,16,14,12]],

[[70,10,8,7,5],[60,13,11,9,7],[50,15,13,12,10],
[40,18,16,14,12],[32,20,18,16,14]],

[[60,16,14,10],[50,22,17,11],[40,25,22,13],[30,30,25,15]],

[[60,25,15],[50,30,20],[40,35,25]],

[[60,40],[40,60]],

[[100]]
]

# get_median(row1)                 #计算sheet1每一列指标的均值
# get_score(row1,0,1000,1600,20)   #1.远近距离得分
# get_score(row1,1,0.7,1.3,10)     #2.侧脸得分
# get_score(row1,2,0.7,1.3,20)     #3.俯仰得分
# get_score(row1,3,0,300,10)       #4.光强得分
# get_score(row1,4,0,100,10)       #5.左右亮度差得分
# get_score(row1,5,0,20,10)        #6.上下亮度差得分
# get_fm(row1,6,0,80,20)           #7.清晰度得分
# get_sum(row3,7)                  #求得分总和,得到综合差异

# for i in range(10):
#     gg=choose_plan1(row3-i,proportion1)   #选用评分占比方案
#     print(str(gg[1])+' '+str(gg[0]))


ws.save(path)
    

# getget_score(总行数,第几列,min,max,分值权重)
# 1.远近   min:1000  max:1600,与均值最大偏差:min-avg or max-avg
# 2.侧脸   min:0     max:120,与均值最大偏差:min-avg or max-avg
# 3.俯仰   min:0.8   max:1.3,与均值最大偏差:min-avg or max-avg
# 4.光强   min:10    max:300,与均值最大偏差:min-avg or max-avg
# 5.左右亮度差 min:0     max:100,与均值最大偏差:min-avg or max-avg
# 6.清晰度80以上算满分

#评分方案2:
#用了6套评分参数,根据当前照片的综合分数排名,来选定用第几套评分参数;
#例如:当前分数排在第5,则选用第五套评分参数

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值