0
点赞
收藏
分享

微信扫一扫

计算机视觉 - 图像相似度

在计算机视觉中如何识别两张图片是否相似,可以通过图像的像素值,根据颜色特征来识别是否为相似图片


计算图片的相似度方法

  • ​​1.像素方差​​
  • ​​1.1缩放图片​​
  • ​​1.2灰度处理​​
  • ​​1.3计算图像每行的平均值​​
  • ​​1.4计算方差​​
  • ​​1.5比较方差​​
  • ​​2.哈希值计算​​
  • ​​2.1平均值哈希​​
  • ​​2.1.1图片缩放成8*8​​
  • ​​2.1.2灰度化图像G​​
  • ​​2.1.3计算整个灰度图像的像素平均值avg​​
  • ​​2.1.4计算hash图像H​​
  • ​​2.2感知哈希​​
  • ​​2.2.1图片缩放32*32​​
  • ​​2.2.2灰度化图像计算机视觉 - 图像相似度_方差
  • ​​2.2.3计算得到图像G的离散余弦变换的图像计算机视觉 - 图像相似度_汉明距离_02
  • ​​2.2.4取计算机视觉 - 图像相似度_汉明距离_02左上角8*8子图像计算机视觉 - 图像相似度_方差_04,计算这个图像中所有像素的平均值,假设其值为a​​
  • ​​2.2.5计算hash图像H​​
  • ​​2.3差异值哈希​​
  • ​​2.3.1缩放图片9*8​​
  • ​​2.3.2灰度化​​
  • ​​2.3.3差异值计算​​
  • ​​2.3.4计算hash图像H​​
  • ​​2.3汉明距离计算​​
  • ​​3.余弦距离计算​​
  • ​​4.直方图计算​​

1.像素方差

1.1缩放图片

1.2灰度处理

1.3计算图像每行的平均值

1.4计算方差

计算所有行的平均值,并以此计算所有行的方差和
计算机视觉 - 图像相似度_汉明距离_05
其中计算机视觉 - 图像相似度_汉明距离_06

1.5比较方差

代码中先使用yolov模型对图片进行了目标检测,提取出检测部分的图像,然后在对图像做相似度处理。

import cv2 as cv
import matplotlib.pyplot as plt
from yolo.yolo import yolo_detect

def detect(data):
x,y,w,h=yolo_detect(data)
image=cv.imread(data,cv.IMREAD_UNCHANGED)
print(x,y,w,h)
img=image[x:x+w,y:y+h]

return img


def imgavg(img):
sidelength=30
#缩放
img=cv.resize(img,(sidelength,sidelength),interpolation=cv.INTER_CUBIC)
#灰度化
gray=cv.cvtColor(img,cv.COLOR_BGR2GRAY)
#每行平均值
avglist=[]
for i in range(sidelength):
avg=sum(gray[i])/len(gray[i])
avglist.append(avg)

return avglist

def variance(avglist):
avg=sum(avglist)/len(avglist)

s=0
for i in avglist:
s+=(i-avg)*(i-avg)/len(avglist)

return s

data1='data/car1.jpg'
image1=cv.imread(data1,cv.IMREAD_UNCHANGED)
data2='data/car2.jpg'
image2=cv.imread(data2,cv.IMREAD_UNCHANGED)

img1=detect(data1)
img2=detect(data2)

avg1=imgavg(img1)
avg2=imgavg(img2)

print("两图片方差:%s"%(abs(variance(avg1)-variance(avg2))))
x=range(30)
plt.figure("兰博基尼")

plt.subplot(2,2,1)
plt.imshow(image1)
plt.subplot(2,2,2)
plt.plot(x,avg1,marker="*",label="$car1$")
plt.plot(x,avg2,marker="*",label="$car2$")
plt.legend()
plt.subplot(2,2,3)
plt.imshow(image2)
plt.legend()
plt.show()

计算机视觉 - 图像相似度_汉明距离_07

2.哈希值计算

2.1平均值哈希

2.1.1图片缩放成8*8

image=cv.resize(img,(8,8),interpolation=cv.INTER_CUBIC)

2.1.2灰度化图像G

gray=cv.cvtColor(image,cv.COLOR_BGR2GRAY)

2.1.3计算整个灰度图像的像素平均值avg

s=0
for i in range(8):
for j in range(8):
s=s+gray[i,j]
avg=s/64

2.1.4计算hash图像H

初始化一张尺寸大小与灰度图像一样的hash图像,其中所有值为0,一行一行遍历图像计算机视觉 - 图像相似度_计算机视觉_08
如果图像中像素计算机视觉 - 图像相似度_灰度_09,则hash图像计算机视觉 - 图像相似度_灰度_10
如果图像中像素计算机视觉 - 图像相似度_计算机视觉_11,则hash图像计算机视觉 - 图像相似度_汉明距离_12
得到图片的hash值后,一行行展开,得到一个二进制数,将二进制数转化为十六进制数,比较两张图片的十六七进制数的汉明距离,通常认为汉明距离小于10的一组图片为相似图片。
汉明距离:两个等长字符串之间的汉明距离是两个字符串对应位置的不同字符的个数

hash_str=''
for i in range(8):
for j in range(8):
if gray[i,j]>=avg:
hash_str+=hash_str+'1'
else:
hash_str+=hash_str+'0'
result = ''
for i in range(0, 64, 4):
result += ''.join('%x' % int(hash_str[i: i + 4], 2))
# print("hash值:",result)
return result

2.2感知哈希

2.2.1图片缩放32*32

image=cv.resize(img,(32,32),interpolation=cv.INTER_CUBIC)

2.2.2灰度化图像计算机视觉 - 图像相似度_汉明距离_13

gray=cv.cvtColor(image,cv.COLOR_BGR2GRAY)

2.2.3计算得到图像G的离散余弦变换的图像计算机视觉 - 图像相似度_灰度_14

h, w = img.shape[:2]
vis0 = np.zeros((h, w), np.float32)
vis0[:h, :w] = image


# DCT二维变换
# 离散余弦变换,得到dct系数矩阵
img_dct = cv.dct(cv.dct(vis0))

2.2.4取计算机视觉 - 图像相似度_灰度_14左上角8*8子图像计算机视觉 - 图像相似度_灰度_16,计算这个图像中所有像素的平均值,假设其值为a

img_dct.resize(8, 8)
# 把list变成一维list
img_list = np.array().flatten(img_dct.tolist())
#均值计算
avg=cv.mean(img_list)

2.2.5计算hash图像H

初始化一张尺寸大小与灰度图像一样的hash图像,其中所有值为0,一行一行遍历图像计算机视觉 - 图像相似度_灰度_14
如果图像中像素计算机视觉 - 图像相似度_灰度_18,则hash图像计算机视觉 - 图像相似度_灰度_10
如果图像中像素计算机视觉 - 图像相似度_灰度_20,则hash图像计算机视觉 - 图像相似度_汉明距离_12
得到图片的hash值后,一行行展开,得到一个二进制数,将二进制数转化为十六进制数,比较两张图片的十六七进制数的汉明距离,通常认为汉明距离小于10的一组图片为相似图片。
汉明距离:两个等长字符串之间的汉明距离是两个字符串对应位置的不同字符的个数

avg_list = ['0' if i < avg else '1' for i in img_list]
return ''.join(['%x' % int(''.join(avg_list[x:x + 4]), 2) for x in range(0, 64, 4)])

2.3差异值哈希

2.3.1缩放图片9*8

image = cv.resize(image, (9, 8), interpolation=cv2.INTER_CUBIC)

2.3.2灰度化

gray = cv.cvtColor(image, cv.COLOR_RGB2GRAY)

2.3.3差异值计算

当前行像素值与前一行像素值比较,如果大于前一行值,则计算机视觉 - 图像相似度_方差_22,,反之为0 从第二到第九行共8行,又因为矩阵有8列,所以得到一个8x8差分矩阵计算机视觉 - 图像相似度_计算机视觉_23

dhash_str = ''
for i in range(8):
for j in range(8):
if gray[i, j] > gray[i, j + 1]:
dhash_str = dhash_str + '1'
else:
dhash_str = dhash_str + '0'

2.3.4计算hash图像H

同上一样

result = ''
for i in range(0, 64, 4):
result += ''.join('%x' % int(dhash_str[i: i + 4], 2))
# print("hash值",result)
return result

2.3汉明距离计算

def campHash(hash1, hash2):
n = 0
# hash长度不同返回-1,此时不能比较
if len(hash1) != len(hash2):
return -1
# 如果hash长度相同遍历长度
for i in range(len(hash1)):
if hash1[i] != hash2[i]:
n = n + 1
return n

3.余弦距离计算

把图像看成是一个矩阵向量,通过计算矩阵之间的余弦距离来表达两张图片的相似度。

4.直方图计算

  • 通过cv2.calcHist()计算图像的直方图
  • 通过cv2.compareHist()来比较以下两张图之间的相似度
import matplotlib.pyplot as plt
import cv2
import numpy as py

img = cv2.imread("data/car1.jpg")
img1 = cv2.imread("data/car2.jpg")
# 计算图img的直方图
H1 = cv2.calcHist([img], [1], None, [256],[0,256])
H1 = cv2.normalize(H1, H1, 0, 1, cv2.NORM_MINMAX, -1) # 对图片进行归一化处理

# 计算图img2的直方图
H2 = cv2.calcHist([img1], [1], None, [256],[0,256])
H2 = cv2.normalize(H2, H2, 0, 1, cv2.NORM_MINMAX, -1)

# 利用compareHist()进行比较相似度
similarity = cv2.compareHist(H1, H2,0)
print(similarity)

# img和img1直方图展示
H=[H1,H2]
for i in range(2):
plt.subplot(2,1,1+i)
plt.plot(H[i])
plt.show()

计算机视觉 - 图像相似度_灰度_24
相似度:
0.14550932178252954


举报

相关推荐

0 条评论