1、图片缩放为10×10(缩放比例因图片大小而异)
2、读取每一点灰度化后的像素
3、计算每一行的像素平均值
4、生成特征序列。
把每一点的像素与所在行的像素平均值作比较
5、对比两张图片的特征序列
from PIL import Image
def hash_img(img):#计算图片的特征序列
a=[]#存储图片的像素
hash_img=''#特征序列
width,height=10,10#图片缩放大小
img=img.resize((width,height))#图片缩放为width×height
for y in range(img.height):
b=[]
for x in range(img.width):
pos=x,y
color_array = img.getpixel(pos)#获得像素
color=sum(color_array)/3#灰度化
b.append(int(color))
a.append(b)
for y in range(img.height):
avg=sum(a[y])/len(a[y])#计算每一行的像素平均值
for x in range(img.width):
if a[y][x]>=avg:#生成特征序列,如果此点像素大于平均值则为1,反之为0
hash_img+='1'
else:
hash_img+='0'
return hash_img
def similar(img1,img2): #求相似度
hash1=hash_img(img1) #计算img1的特征序列
hash2=hash_img(img2) #计算img2的特征序列
differnce=0
for i in range(len(hash1)):
differnce+=abs(int(hash1[i])-int(hash2[i]))
similar=1-(differnce/len(hash1))
return similar
img1=Image.open('1.png')
img2=Image.open('2.png')
print('%.1f%%' % (similar(img1,img2) * 100))
img1=Image.open('1.png')
img2=Image.open('2.png')
print('%.1f%%' % (similar(img1,img2) * 100))
img3=Image.open('3.png')
img4=Image.open('4.png')
print('%.1f%%' % (similar(img3,img4) * 100))
输出:
61.0%
89.0%
1.png和2.png的相似度为61%
3.png和4.png的相似度为89%
判断两个像素是否相同
abs(piex1[0] - piex2[0]) < threshold
abs(piex1[1]- piex2[1]) < threshold
abs(piex1[2] - piex2[2]) < threshold
from PIL import Image
import time
def pixel_equal(image1, image2, x, y):
"""
判断两个像素是否相同
:param image1: 图片1
:param image2: 图片2
:param x: 位置x
:param y: 位置y
:return: 像素是否相同
"""
# 取两个图片像素点
piex1 = image1.load()[x, y]
piex2 = image2.load()[x, y]
threshold = 10
# 比较每个像素点的RGB值是否在阈值范围内,若两张图片的RGB值都在某一阈值内,则我们认为它的像素点是一样的
if abs(piex1[0] - piex2[0]) < threshold and abs(piex1[1]- piex2[1]) < threshold and abs(piex1[2] - piex2[2]) < threshold:
return True
else:
return False
def compare(image1, image2):
"""
进行比较
:param image1:图片1
:param image2: 图片2
:return:
"""
left = 0 # 坐标起始位置
right_num = 0 # 记录相同像素点个数
false_num = 0 # 记录不同像素点个数
all_num = 0 # 记录所有像素点个数
for i in range(left, image1.size[0]):
for j in range(image1.size[1]):
if pixel_equal(image1, image2, i, j):
right_num += 1
else:
false_num += 1
all_num += 1
same_rate = right_num / all_num # 相同像素点比例
nosame_rate = false_num / all_num # 不同像素点比例
print("same_rate: ", same_rate)
print("nosame_rate: ", nosame_rate)
if __name__ == "__main__":
t1 = time.time()
image1 = Image.open("./out0321_320.jpg")
image2 = Image.open("./out0321_640.jpg")
compare(image1, image2)
t2 = time.time()
print("t=", t2-t1)
def ssim(img1, img2):
width = img1.shape[1]
win_size = int(width/2-((width/2) % 2)+1)
out = structural_similarity(img1, img2, win_size=win_size, multichannel=True)
return out if out > 0 else 0
相似度度量(Similarity),即计算个体间的相似程度
平均hash:
def aHash(img, shape=(10, 10)):
# 缩放为10*10
img = cv2.resize(img, shape)
# 转换为灰度图
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# s为像素和初值为0,hash_str为hash值初值为''
s = 0
hash_str = ''
# 遍历累加求像素和
for i in range(shape[0]):
for j in range(shape[1]):
s = s + gray[i, j]
# 求平均灰度
avg = s / 100
# 灰度大于平均值为1相反为0生成图片的hash值
for i in range(shape[0]):
for j in range(shape[1]):
if gray[i, j] > avg:
hash_str = hash_str + '1'
else:
hash_str = hash_str + '0'
return hash_str
感知hash:
def pHash(img, shape=(10, 10)):
# 缩放32*32
img = cv2.resize(img, (32, 32)) # , interpolation=cv2.INTER_CUBIC
# 转换为灰度图
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 将灰度图转为浮点型,再进行dct变换
dct = cv2.dct(np.float32(gray))
# opencv实现的掩码操作
dct_roi = dct[0:10, 0:10]
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
比较hash指获取相似度:
def cmpHash(hash1, hash2, shape=(10, 10)):
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/(shape[0]*shape[1])
def ORB_siml(img1, img2, params):
# 初始化ORB检测器
orb = cv2.ORB_create(nfeatures=200)
kp1, des1 = orb.detectAndCompute(img1, None)
kp2, des2 = orb.detectAndCompute(img2, None)
# 使用汉明距离对特侦点距离进行计算
bf = cv2.BFMatcher(cv2.NORM_HAMMING)
# 使用knn算法进行匹配
matches = bf.knnMatch(des1, trainDescriptors=des2, k=2)
# 去除模糊的匹配
good = [(m, n) for (m, n) in matches if m.distance < 0.95 * n.distance and m.distance < 70]
# 绘制匹配的关键点
# img3 = cv2.drawMatchesKnn(img1, kp1, img2, kp2, good, img2, flags=2)
similary = len(good) / len(matches)
return similary
基于moilenetv2模型的转换和使用:
import torch
import torchvision
import onnx
import onnxruntime as ort
from torchvision import transforms
from PIL import Image
import numpy as np
mobilev2 = torchvision.models.mobilenet_v2(pretrained=True)
new_classifier = torch.nn.Sequential(*list(mobilev2.children())[-1][:1])
mobilev2.classifier = new_classifier
mobilev2.eval()
torch.save(mobilev2 , "./mobilev2_1280.pt")
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
mobilev2_1280 = torch.load('mobilev2_1280.pt')
mobilev2_1280.to(device)
mobilev2_1280.eval()
img_dir = r'/home/whh/whh_train/Classification/000000.jpg'
img = Image.open(img_dir)
trans = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
cudaimg = trans(img)
cudaimg.unsqueeze_(dim=0)
cudaimg=cudaimg.cuda()
tensorimg = trans(img)
tensorimg = tensorimg[None,:]
out_1280 = mobilev2_1280(cudaimg)