前言:
我们在拍照时,距离镜头的远近、侧脸程度、俯仰姿态以及环境光照等因素都不尽相同;假如我们刚拍了一张照片,那么,如何在历史照片中,挑选出一张与当前照片最相似的呢?
用途:
本文目的在于挑选出与选定照片最相似的一张照片。、
至于用途,针对不同项目有不同效果,比如:
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,则选用第五套评分参数