有没有夫妻相?刷一下脸就知道!

8532 2025-09-29 07:37:13
摘要:本文利用ssim算法,帮你快速打造一个“刷脸测试夫妻相”Demo出来。 本文分享自华为云社区《情人节季,快来上传你的女神照片,测试下

摘要:本文利用ssim算法,帮你快速打造一个“刷脸测试夫妻相”Demo出来。

本文分享自华为云社区《情人节季,快来上传你的女神照片,测试下你们的夫妻相》,作者: HWCloudAI 。

“夫妻相”是指两人之间的相貌让人感觉是一对夫妻,还有一种说法是指夫妻之间面容相似。

有研究认为:两个人在一起生活得久了,表情动作彼此模仿,会越来越像。其实是因为大多数人都珍爱自己,看到跟自己相像的人格外顺眼,从一开头就是拿自己当范本选择另一半。“夫妻相”的大抵意思是因为常常接触,心灵相倾,习惯趋同,相同的作息、肠道菌落交换等相互影响,以致到了面容相像。夫妻相是面容相像,心灵相倾,习惯趋同,相互影响。

世界各地都有类似的说法:人们容易被面容与自己有共同之处的人吸引。一些进化生物学家认为,这是因为我们潜意识里觉得,与自己长相相似的人更值得信任。然而也有研究表明,当动物处于压力下,它们更倾向与同伴中遗传距离较远的个体交配。

尽管上述描述在当今心理学、生物学方面有争议,但是大多数人还是比较认同“夫妻相”这一说法的。(以上“夫妻相”解释来自百度百科)

基于此,本文利用ssim算法,帮你快速打造一个“刷脸测试夫妻相”Demo出来。

夫妻相似度 ssim算法原理

SSIM(structural similarity)是一种用来衡量图片相似度的指标,也可用来判断图片压缩后的质量。

基本原理:

其中有几个需要注意的点:

C1、C2、C3为常数,避免分母接近于0时造成的不稳定性。

SSIM函数S具有对称性、有界性(不超过1)和最大值唯一性(当且仅当x=y时,S=1,表示两幅图一样)。

上述S函数为C3=C2/2的简化形式。

(更多SSIM介绍可自行搜索论文《Image Quality Assessment: From Error Visibility to Structural Similarity》)

注意事项:

本案例使用框架:PyTorch-1.8

本案例使用硬件规格:CPU: 2核 4GB

本案例的AI Gallery链接 上传你的女神照片,测试下你们的夫妻相

步骤一:下载需要的海报文件和字体

import os

import os.path as osp

import moxing as mox

parent = osp.join(os.getcwd(),'Valentine')

if not os.path.exists(parent):

mox.file.copy_parallel('obs://modelarts-labs-bj4-v2/case_zoo/Valentine',parent)

if os.path.exists(parent):

print('Download success')

else:

raise Exception('Download Failed')

else:

print("Model Package already exists!")

INFO:root:Using MoXing-v2.1.0.5d9c87c8-5d9c87c8

INFO:root:Using OBS-Python-SDK-3.20.9.1

Download success

步骤二:使用ssim算法计算夫妻相

import numpy as np

import cv2

import random

import matplotlib.pyplot as plt

from matplotlib import font_manager

import warnings

from scipy.signal import convolve2d

from PIL import Image,ImageDraw,ImageFont

warnings.filterwarnings('ignore')

def matlab_style_gauss2D(shape=(3,3),sigma=0.5):

"""

2D gaussian mask - should give the same result as MATLAB's

fspecial('gaussian',[shape],[sigma])

"""

m,n = [(ss-1.)/2. for ss in shape]

y,x = np.ogrid[-m:m+1,-n:n+1]

h = np.exp( -(x*x + y*y) / (2.*sigma*sigma) )

h[ h < np.finfo(h.dtype).eps*h.max() ] = 0

sumh = h.sum()

if sumh != 0:

h /= sumh

return h

def filter2(x, kernel, mode='same'):

return convolve2d(x, np.rot90(kernel, 2), mode=mode)

def compute_ssim(im1, im2, k1=0.01, k2=0.04, win_size=11, L=255):

if not im1.shape == im2.shape:

raise ValueError("Input Imagees must have the same dimensions")

if len(im1.shape) > 2:

raise ValueError("Please input the images with 1 channel")

M, N = im1.shape

C1 = (k1*L)**2

C2 = (k2*L)**2

window = matlab_style_gauss2D(shape=(win_size,win_size), sigma=0.5)

window = window/np.sum(np.sum(window))

if im1.dtype == np.uint8:

im1 = np.double(im1)

if im2.dtype == np.uint8:

im2 = np.double(im2)

mu1 = filter2(im1, window, 'valid')

mu2 = filter2(im2, window, 'valid')

mu1_sq = mu1 * mu1

mu2_sq = mu2 * mu2

mu1_mu2 = mu1 * mu2

sigma1_sq = filter2(im1*im1, window, 'valid') - mu1_sq

sigma2_sq = filter2(im2*im2, window, 'valid') - mu2_sq

sigmal2 = filter2(im1*im2, window, 'valid') - mu1_mu2

ssim_map = ((2*mu1_mu2+C1) * (2*sigmal2+C2)) / ((mu1_sq+mu2_sq+C1) * (sigma1_sq+sigma2_sq+C2))

return np.mean(np.mean(ssim_map))

def img_show(similarity, img1, img2, name1, name2):

# similarity = random.uniform(60,100)

zt = "./Valentine/方正兰亭准黑_GBK.ttf"

my_font = font_manager.FontProperties(fname = zt,size =20 )

img1 = cv2.resize(img1, (520, 520))

img2 = cv2.resize(img2, (520, 520))

imgs = np.hstack([img1, img2])

imgs2 = imgs[:,:, ::-1]

plt.axis('off')

plt.title('{0} VS {1} \n CP指数: {2}%'.format(name1, name2, round(similarity, 2)), fontproperties=my_font)

plt.imshow(imgs2)

path = "a.jpg"

cv2.imwrite(path, imgs)

加入人脸检测

def getFaces(gray):

cascPath = "/home/ma-user/anaconda3/envs/PyTorch-1.8/lib/python3.7/site-packages/cv2/data/haarcascade_frontalface_default.xml"

faceCascade = cv2.CascadeClassifier(cascPath)

im1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)

# Detect faces

faces = faceCascade.detectMultiScale(

gray,

scaleFactor=1.1,

minNeighbors=5,

flags=cv2.CASCADE_SCALE_IMAGE

)

return faces

步骤三:修改预置的视频和图片

在Valentine文件夹下中,有一个预置的1.png和2.png图片,大家可以将里面的图片替换成自己的, 图片的名称不建议修改,如果修改成其他的名称,后面的路径也要相应的修改,上传的图片不要太大,尽量使用正脸的图片。

if __name__ == '__main__':

name1 = input('请输入图1照片姓名: \n')

name2 = input('请输入图2照片姓名: \n')

img1_path = 'Valentine/1.png'

img2_path = 'Valentine/2.png'

img1 = cv2.imread(img1_path)

img2 = cv2.imread(img2_path)

im1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)

im2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)

im1_faces = getFaces(im1)

im2_faces = getFaces(im2)

if len(im1_faces) !=1 or len(im2_faces)!= 1:

raise ValueError("输入图片需要包含一个人脸")

im1 = cv2.resize(im1, (520,520))

im2 = cv2.resize(im2, (520,520))

similarity = compute_ssim(im1, im2)*100

if similarity == 100:

raise ValueError("图片重复! 请重新上传图片")

img_show(similarity, img1, img2, name1, name2)

请输入图1照片姓名:

王强

请输入图2照片姓名:

李欣

image = Image.open("a.jpg")

image = image.resize((498,278))

步骤四:打印输出海报

import os

from PIL import Image,ImageDraw,ImageFont,ImageFilter

from PIL import ImageFile

ImageFile.LOAD_TRUNCATED_IMAGES = True

#@title 请在下面填写创作者 :

def gen_poster(img,txt1,txt2,path):

font1 = ImageFont.truetype(zt,42)

font2 = ImageFont.truetype(zt,24)

img_draw = ImageDraw.Draw(img)

img_draw.text((197,629), txt1, font=font1,fill='#961900')

img_draw.text((152,689), txt2, font=font2, fill='#252b3a')

img.filter(ImageFilter.BLUR)

img.save(path)

template_img = "./Valentine/ValentinPoster.png"

zt = "./Valentine/方正兰亭准黑_GBK.ttf"

temp_image = Image.open(template_img)

temp_image.paste(image ,(40,266))

title_char = str(round(similarity,1)) + "%"

author_char = "王强" #@param {type:"string"}

savepath = 'ValentinPoster.png' # 海报图片路径

gen_poster(temp_image,title_char,author_char,savepath)

Image.open(savepath) # 显示图片

点击关注,第一时间了解华为云新鲜技术~

拥有上万年历史的岫玉,你了解多少?又如何收藏?|2025兔巴士(城北店)攻略,资中兔巴士(城北店)美食推荐,点评/电话/地址