1.哈希方法,其中包括均值哈希、插值哈希、感知哈希方法。计算出图片的哈希值,一般使用汉明
距离计算两个图片间的差距。
2.直方图算法,其中包括灰度直方图算法,RGB直方图算法,
3.灰度图算法:MSE、SSIM、图像相似度算法
4.余弦相似性、欧氏距离
5.MD5
一、直方图算法
方法描述:按照某种距离度量的标准对两幅图像的直方图进行相似度的测量。
(1)单通道直方图
def histogram(image1, image2):
# 灰度直方图算法
# 计算单通道的直方图的相似值
hist1 = cv2.calcHist([image1], [0], None, [256], [0.0, 255.0])
hist2 = cv2.calcHist([image2], [0], None, [256], [0.0, 255.0])
# 计算直方图的重合度
degree = 0
for i in range(len(hist1)):
if hist1[i] != hist2[i]:
degree = degree + \
(1 - abs(hist1[i] - hist2[i]) / max(hist1[i], hist2[i]))
else:
degree = degree + 1
degree = degree / len(hist1)
return degree
(2)RGB三通道直方图
def Multiparty_histogram(self, image1, image2, size=(256, 256)):
# RGB每个通道的直方图相似度
# 将图像resize后,分离为RGB三个通道,再计算每个通道的相似值
image1 = cv2.resize(image1, size)
image2 = cv2.resize(image2, size)
sub_image1 = cv2.split(image1)
sub_image2 = cv2.split(image2)
sub_data = 0
for im1, im2 in zip(sub_image1, sub_image2):
sub_data += self.calculate(im1, im2)
sub_data = sub_data / 3
return sub_data
二、灰度图算法:利用灰度图的值、均值、方差计算图像的差异性
(1)MSE(Mean Squared Error)均方误差:针对单通道灰度图
对于两个m×n的单通道图像I和K,它们的均方误差可定义为:
缺点:当差值大于1时,会放大误差;而当差值小于1时,则会缩小误差,这是平方运算决定的。MSE对于较大的误差(>1)给予较大的惩罚,较小的误差(<1)给予较小的惩罚。也就是说,对离群点比较敏感,受其影响较大。
(2)SSIM(structural similarity)结构相似性:针对单通道灰度图
SSIM(structural similarity),结构相似性,是一种衡量两幅图像相似度的指标。
SSIM公式基于样本x和y之间的三个比较衡量:亮度 (luminance)、对比度 (contrast) 和结构 (structure)。
𝝁𝒙为均值, 𝝈𝒙 为方差, 𝝈𝒙𝒚 表示协方差。
常数𝑪𝟏, 𝑪𝟐, 𝑪𝟑是为了避免当分母为 0 时造成的不稳定问题。
在实际应用中,可以利用滑动窗将图像分块,令分块总数为N,考虑到窗口形状对分块的影响,采用高斯加权计算每一窗口的均值、方差以及协方差,然后计算对应块的结构相似度SSIM,最后将平均值作为两图像的结构相似性度量,即平均结构相似性SSIM。
def contrast_image(imageA, imageB):
"""
对比两张图片的相似度,相似度等于1 完美匹配
:param imageA:
:param imageB:
:return:
"""
imageA = cv2.imread(imageA)
imageB = cv2.imread(imageB)
grayA = cv2.cvtColor(imageA, cv2.COLOR_BGR2GRAY)
grayB = cv2.cvtColor(imageB, cv2.COLOR_BGR2GRAY)
# 计算两个灰度图像之间的结构相似度指数,相似度等于1完美匹配
(score, diff) = structural_similarity(grayA, grayB, full=True)
diff = (diff * 255).astype("uint8")
print("SSIM:{}".format(score))
return score, diff
(3)图片相似度算法(对像素求方差并比对)的学习
(4)PSNR
def PSNR(img1, img2):
mse = np.mean((img1/255. - img2/255.) ** 2)
if mse == 0:
return 100
PIXEL_MAX = 1
return 20 * math.log10(PIXEL_MAX / math.sqrt(mse))
三、哈希算法
计算图片的哈希表示后,利用汉明距离计算两张图片的差异
哈希相似度
实现图片相似度比较的hash算法有三种:均值哈希算法(AHash),差值哈希算法(DHash),感知哈希算法 (PHash)。(图片转成哈希表示后,用汉明距离计算两个图片的差距)
- aHash:平均值哈希。速度比较快,但是常常不太精确。
- pHash:感知哈希。精确度比较高,但是速度方面较差一些。
- dHash:差异值哈希。精确度较高,且速度也非常快。
(1)均值哈希算法(AHash)
def aHash(img):
# 平均值哈希算法
# 缩放为8*8
img = cv2.resize(img, (8, 8))
# 转换为灰度图
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# s为像素和初值为0,hash为hash值初值为''
s = 0
hash= ''
# 遍历累加求像素和
for i in range(8):
for j in range(8):
s = s + gray[i, j]
# 求平均灰度
avg = s / 64
# 灰度大于平均值为1相反为0生成图片的hash值
for i in range(8):
for j in range(8):
if gray[i, j] > avg:
hash_str = hash + '1'
else:
hash_str = hash + '0'
return hash_str
(2)感知哈希算法 (PHash)
感知哈希算法是一个比均值哈希算法更为健壮的一种算法,与均值哈希算法的区别在于感知哈希算法是通过DCT(离散余弦变换)来获取图片的低频信息。
def pHash(img):
# 感知哈希算法
# 缩放32*32
img = cv2.resize(img, (32, 32)) # , interpolation=cv2.INTER_CUBIC
# 转换为灰度图
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 将灰度图转为浮点型,再进行dct变换,cv2.dct()是离弦余弦变换
dct = cv2.dct(np.float32(gray))
# opencv实现的掩码操作
dct_roi = dct[0:8, 0:8]
hash = []
avreage = np.mean(dct_roi)
for i in range(dct_roi.shape[0]):
for j in range(dct_roi.shape[1]):
if dct_roi[i, j] > avreage:
hash.append(1)
else:
hash.append(0)
return hash
(3)差值哈希算法(DHash)
比pHash,dHash的速度要快的多,相比aHash,dHash在效率几乎相同的情况下的效果要更好,它是基于渐变实现的。
def dHash(img):
# 差值哈希算法
# 缩放8*8
img = cv2.resize(img, (9, 8))
# 转换灰度图
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
hash = ''
# 每行前一个像素大于后一个像素为1,相反为0,生成哈希
for i in range(8):
for j in range(8):
if gray[i, j] > gray[i, j + 1]:
hash_str = hash + '1'
else:
hash_str = hash + '0'
return hash_str
汉明距离计算两个图像的哈希差值
def cmpHash(hash1,hash2):
n=0
#hash长度不同则返回-1代表传参出错
if len(hash1)!=len(hash2):
return -1
#遍历判断
for i in range(len(hash1)):
#不相等则n计数+1,n最终为相似度
if hash1[i]!=hash2[i]:
n=n+1
return n
MD5
粗暴的md5比较 返回是否完全相同
def md5_similarity(img1_path, img2_path):
file1 = open(img1_path, "rb")
file2 = open(img2_path, "rb")
md = hashlib.md5()
md.update(file1.read())
res1 = md.hexdigest()
md = hashlib.md5()
md.update(file2.read())
res2 = md.hexdigest()
return res1 == res2
余弦相似度
把图片表示成一个向量,两个向量夹角的余弦值作为衡量两个个体间差异的大小。
欧氏距离
衡量的是多维空间中各个点之间的绝对距离。
借助三维坐标系来看下欧氏距离和余弦距离的区别:
【精选】图像相似度匹配——距离大全_pairwise_distances图像距离-CSDN博客