def get_id_prob_imgs(id_path, prob_path):# 这里假设id图片只有一层目录,每个id一张照片; prob照片有两层目录,第一层子目录为id名称,子目录下面才是prob照片id_imgs = [os.path.join(idpath,i) for i in os.listdir(id_path)]probsubpaths = [os.path.join(probpath,i) for i in os.listdir(probpath)]probimgs = []for path_ in probsubpaths:probimgs.extend([os.path.join(path_,i) for i in os.listdir(path_)])retrun idimgs, probimgsdef generate_img_pairs():# 这里只是1张id照片和一张prob照片组成一对样本,实际也可以id照片id照片、prob照片和prob照片之间组成样本对# 视具体需要确定f = open('img_pairs.txt')idimgs,probimgs = get_id_prob_imgs()lines = []pos,neg=0,0for i in idimgs:# 具体获取id的方式取决于数据存放形式,这里id照片的id为文件名,prob照片的id为上一级子目录名称id_id = os.path.split(i)[-1]id_id = os.path.splitext(id_id)[0]for j in probimgs:id_prob = j.split(os.sep)[-2]if id_id == id_prob:lines.append('%s\t%s\t%s\n'%(i,j,1))pos += 1else:lines.append('%s\t%s\t%s\n'%(i,j,0))neg += 1print('number of positive/negative pairs', pos, neg)for line in lines:f,write(line)f.close()def cal_pairs_sims(face_model, imgpath, img_pairs='img_pairs.txt',result='img_pairs_sims.txt'):# ReadTxt_to_list函数见 https://blog.csdn.net/qxqxqzzz/article/details/118960933# 先计算,保存结果,避免后续需要重新预测一遍pairs = ReadTxt_to_list(img_pairs)f = open(result, 'w')for p in pairs:idimg,probimg,flag = p.split('\t')idimg,probimg = os.path.join(imgpath,idimg),os.path.join(imgpath,probimg)idfea,probfea = face_model(idimg),face_model(probimg)# 注意人脸相似度有负值!sim = np.dot(np.squeeze(idfea), np.squeeze(probfea)) / (np.linalg.norm(idfea) * np.linalg.norm(probfea))f.write(p+'\t%s\n'%sim)f.close()def read_sims(img_pairs='img_pairs.txt'):# ReadTxt_to_list函数见 https://blog.csdn.net/qxqxqzzz/article/details/118960933lines = ReadTxt_to_list(img_pairs)possims,negsims=[],[]for line in lines:idimg,probimg,flag,sim=line.split('\t')s = float(s)if flag == '1':possims.append(sim)else:negsims.append(sim)possims.sort(reverse=True)negsims.sort()return possims,negsimsdef cal_p_r(possims,negsims,th):for s in possims:if s > th: tp += 1else:fn += 1for s in negsims:if s > th:fp += 1else:tn += 1if tp + fp == 0:precision = 0else:precision = tp / (tp + fp)recall = tp / (tp + fn)return precision, recalldef plot_recall_precision():ths = np.linspace(0,1,num=100)possims,negsims = read_sims()# 遍历阈值,画图rs, ps = [], []for th in ths:precision,recall = cal_p_r(possims,negsims,th)rs.append(recall)ps.append(precision)plt.plot(ths,rs,label='recall')plt.plot(ths,ps,label='precision')plt.legend()plt.show()plt.savefig('p_r.jpg')
注:如果中途停止程序发现文本文件中没有写入结果内容,那是因为代码还没有运行到 f.close()