当前位置: 首页 > 后端技术 > Python

图片相似度比较

时间:2023-03-26 01:00:53 Python

【声明】衡量两张图片相似度的算法有很多种。本文将总结常用的图像相似度算法。部分数据和资料来自各个技术网站。如有侵权,请联系删除。常用的算法有几类:1.哈希算法常用的哈希算法有三种,分别是平均哈希算法(aHash)、感知哈希算法(pHash)和差分哈希算法(dHash);还有一种小波哈希算法(whash)。Hash算法通过获取图片的哈希值,然后比较两张图片的哈希值的汉明距离来衡量两张图片是否相似。两张图片越相似,两张图片的哈希值之间的汉明距离越小。1、aHash——平均哈希算法步骤平均哈希算法是三种哈希算法中最简单的。它通过以下步骤获取图像的Hash值:(1)对图像进行缩放;(2)转换为灰度图;(3)计算像素均值;(4)根据相似均值计算指纹。得到图片的ahash值后,比较两张图片的ahash值的汉明距离。一般认为海明距离小于10的一组图片是相似图片。下面以一张动物的图片为例,详细讲解一下ahash算法的过程:灰度图:得到单通道灰度图,通过计算图片中每个像素值的平均值得到的平均值为152.4375。将每个像素与平均值比较,图片的ahash值为:1111100011110000111111001111011011100111111011101111000000001000ahashcodeimportcv2importnumpyasnpimport_pashicalgorithm'ahpath'Process:parampic_path:'cv2pic.img='cv2pic.img=return:'cv2pic.img.IMREAD_UNCHANGED)img_resize=cv2.resize(img,(8,8),cv2.INTER_AREA)gray_img=cv2.cvtColor(img_resize,cv2.COLOR_BGR2GRAY)print('单通道灰度图像:',gray_img)avg=np.mean(gray_img)print('Mean:',avg)dis=copy.deepcopy(gray_img)dis_hash_str=''forx_index,xinenumerate(gray_img):fory_index,yinenumerate(x):如果y>=avg:dis[x_index,y_index]=1else:dis[x_index,y_index]=0dis_hash_str+=str(dis[x_index,y_index])print('与平均值比较:',dis)print('的ahash值图片:',dis_hash_str)cv2.namedWindow('resize',0)cv2.resizeWindow('resize',600,600)cv2.imshow('resize',img_resize)cv2.namedWindow('gray',0)cv2.resizeWindow('gray',600,600)cv2.imshow('gray',gray_img)cv2.waitKey(0)cv2.destroyAllWindows()两张图片的比较自然需要另一张图片。同理,通过上述方法计算出哈希值后,计算汉明距离2.dHash-差分哈希算法步骤dhash和ahash算法的区别在于ahash是利用每个像素点与平均像素点进行比较得到一个布尔值,以及dhash使用当前像素与下一个像素进行比较得到一个布尔值,也正是由于这个原因,dhash算法需要将图像缩放到9*8像素。(1)将图片缩放为9*8,保留结构,去除细节;(2)灰度:转换为256级灰度图像;(3)计算平均值:计算灰度图中所有像素点的平均值;(4)比较:大于下一个像素值的像素值记为1,相反记为0。本行不与下一行比较,每行9个像素,8个不同点,8行,共64位;(5)生成hash:将以上步骤生成的1和0组合起来,成为图片的指纹(hash);取原图:缩放图片首先将图片缩放为9*8的图片,得到如下图:图片的灰度图获取灰度图:获取单通道灰度图的每个像素值,每个像素点和下一个像素点点值那么该图片图片的值即:001101101011101101101101101111111111111111111111111111111111111111111111111111111111DHASH代码,cv2.INTER_AREA)gray_img=cv2.cvtColor(img_resize,cv2.COLOR_BGR2GRAY)print('单通道灰度图像:',gray_img)dis=[[]forxinrange(8)]dis_hash_str=''forrowinrange(8):forcolinrange(8):ifgray_img[row,col]>=gray_img[row,col+1]:dis[row].append(1)dis_hash_str+=str(1)else:dis[排]。append(0)dis_hash_str+=str(0)print('比较值:',dis)print('图像的哈希值:',dis_hash_str)cv2.namedWindow('resize',0)cv2.resizeWindow('resize',600,600)cv2.imshow('调整大小',img_resize)cv2.namedWindow('gray',0)cv2.resizeWindow('gray',600,600)cv2.imshow('gray',gray_img)cv2.waitKey(0)cv2.destroyAllWindows()3.pHash感知哈希算法stepdhash是三种哈希算法中比较复杂的一种。它是基于DCT(离散余弦变换)得到图片的哈希值:(1)缩小图片:32*32是比较好的尺寸,这样方便DCT计算;(2)灰度:转换为256级灰度图像;(3)计算DCT:DCT将图片分离成一组比例,DCT(离散余弦变换);(4)shrinkDCT:DCT计算后矩阵为32*32,保留左上角的8*8,代表图片的最低频率;(5)计算平均值:计算所有像素点收缩DCT后的平均值;(6)比较平均值:大于平均值记为1,否则记为0,得到phash值拍摄原图:缩放图片先将图片缩放为32*32的图片,得到下图:图片的灰度得到灰度图:计算图片的DCT得到DCT图片:得到thelowfrequencyDCTofthepicturetogetthelowfrequencyDCTpicture:thelowfrequencyDCTvalue:average值为:97.10013低频DCT值与平均值比较得到phash值为:1110011010100100000010001101001100010000110000001001000000010000pHash代码importcv2importnumpyasnpdefphash_process(pic_path):img=cv2.imread(pic_path,cv2.IMREAD_UNCHANGED)img_resize=cv2.resize(img,(32,32),cv2.INTER_AREA)gray_img=cv2.cvtColor(img_resize,cv2.COLOR_BGR2GRAY)print('单通道灰度图:',gray_img)gray_img_dct=cv2.dct(np.float32(gray_img))gray_img_low_dct=gray_img_dct[0:8,0:8]print('低频DCT图像值:',gray_img_low_dct)avg=np.mean(gray_img_low_dct)print('低频DCT图像平均值:',avg)dis=[[]forxinrange(8)]dis_hash_str=''forrow_index,rowinenumerate(gray_img_low_dct):forcol_index,colinenumerate(row):print(row_index,col_index)ifcol>=avg:dis[row_index].append(1)dis_hash_str+='1'别的:dis[row_index].append(0)dis_hash_str+='0'print('phash值:',dis_hash_str)cv2.namedWindow('resize',0)cv2.resizeWindow('resize',600,600)cv2.imshow('resize',img_resize)cv2.namedWindow('gray',0)cv2.resizeWindow('gray',600,600)cv2.imshow('gray',gray_img)cv2.namedWindow('DCT',0)cv2.resizeWindow('DCT',600,600)cv2.imshow('DCT',gray_img_dct)cv2.namedWindow('low_DCT',0)cv2.resizeWindow('low_DCT',600,600)cv2.imshow('low_DCT',gray_img_low_dct)cv2.waitKey(0)cv2.destroyAllWindows()4.wHash-wavelethashwavelethash是频率表示的另一种形式whash相当于将phash中的DCT变换改为DWT。离散小波变换(DWT)是另一种频率表示形式。流行的DCT和傅里叶变换使用余弦函数作为sin\cos的基础:sin(x)、sin(2x)、sin(3x)等。相比之下,DWT使用单一功能作为基础,但形式不同:缩放和移动。wavelethash平时用的不多,这里就不展开了。以上是所有哈希算法的总结。5、彩蛋,我们平时使用不需要自己写hash算法过程。为什么写在最后,其实就是想让大家耐心看完前面的内容,对算法底层有一定的了解,不要挨打!有现成的包(imagehash)供大家使用:pipinstallimagehashfromimagehashimportphashdefimage_similar_compare(img1,img2):#用phash举个栗子,其他hash方法也可以直接引用hash1=phash(Image.open(img1))hash2=phash(Image.open(img2))#计算海明距离return1-(hash1-hash2)/len(hash1.hash)**2二、SSIM算法SSIM(结构相似性度量),这是一个全参考图像质量评价指标从亮度、对比度和结构三个方面衡量图像相似度。均值是亮度的估计值,标准差是对比度的估计值,协方差是结构相似性的度量。SSIM的取值范围是[0,1]。值越大,图像失真越小,越相似。计算步骤在实际应用中,可以采用滑动窗口对图像进行分块,分块总数为N。考虑到窗口形状对分块的影响,采用高斯加权计算均值、方差和每个窗口的协方差;然后计算对应块的结构相似度SSIM,最后取平均值作为两幅图像的结构相似度度量,即平均结构相似度MSSIM。优点结构相似性指标从图像组成的角度将结构信息定义为独立于亮度和对比度反映场景中物体结构的属性,并将失真建模为亮度、对比度和结构三个不同因素的组合。应用SSIM已成为广播和有线电视中广泛使用的视频质量测量方法。它已广泛用于超分辨率和图像去模糊。它更适用于传输过程前后的同一张照片。uX和uY分别代表图像X和Y的均值,σX和σY分别代表图像X和Y的标准差,σXσX和σYσY(我真的不会上标,理解万岁)代表分别是图像X和Y的方差。σXY表示图像X和Y的协方差。C1、C2、C3为常数,使分母不为0,保持稳定。通常取C1=(K1L)^2,C2=(K2L)^2,C3=C2/2,一般取K1=0.01,K2=0.03,L=255(是像素值的动态范围,一般取255)参考文章:https://cloud.tencent.com/dev...https://www.cnblogs.com/Kalaf...https://blog.csdn.net/u010977...