Python计算图像相似度并圈出不同处

Python计算图像相似度并圈出不同处

SSIM

1

from skimage.measure import compare_ssim
import cv2
import numpy as np

class CompareImage():
    def compare_image(self, path_image1, path_image2):
        imageA = cv2.imread(path_image1)
        imageB = cv2.imread(path_image2)
        imageB = np.resize(imageB, (imageA.shape[0], imageA.shape[1], imageA.shape[2]))
        grayA = cv2.cvtColor(imageA, cv2.COLOR_BGR2GRAY)
        grayB = cv2.cvtColor(imageB, cv2.COLOR_BGR2GRAY)
        (score, diff) = compare_ssim(grayA, grayB, full=True)
        print("SSIM: {}".format(score))
        return score


compare_image = CompareImage()
compare_image.compare_image("1.jpg", "2.jpg")

2

from skimage.measure import compare_ssim
import numpy as np
import imageio

img1 = imageio.imread('1.jpg')
img2 = imageio.imread('2.jpg')
img2 = np.resize(img2, (img1.shape[0], img1.shape[1], img1.shape[2]))
#print(img2.shape)
#print(img1.shape)
ssim = compare_ssim(img1, img2, multichannel=True)
print(ssim)


hash

import cv2
import time
import numpy as np


# 均值哈希算法
def aHash(img):
    img = cv2.resize(img, (8, 8))
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    np_mean = np.mean(gray)  # 求numpy.ndarray平均值
    ahash_01 = (gray > np_mean) + 0  # 大于平均值=1,否则=0
    ahash_list = ahash_01.reshape(1, -1)[0].tolist()  # 展平->转成列表
    ahash_str = ''.join([str(x) for x in ahash_list])
    return ahash_str


def pHash(img):
    img = cv2.resize(img, (32, 32))  # 默认interpolation=cv2.INTER_CUBIC
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    dct = cv2.dct(np.float32(gray))
    dct_roi = dct[0:8, 0:8]  # opencv实现的掩码操作
    avreage = np.mean(dct_roi)
    phash_01 = (dct_roi > avreage) + 0
    phash_list = phash_01.reshape(1, -1)[0].tolist()
    phash_str = ''.join([str(x) for x in phash_list])
    return phash_str


def dHash(img):
    img = cv2.resize(img, (9, 8))
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    # 每行前一个像素大于后一个像素为1,相反为0,生成哈希
    hash_str0 = []
    for i in range(8):
        hash_str0.append(gray[:, i] > gray[:, i + 1])
    hash_str1 = np.array(hash_str0) + 0
    hash_str2 = hash_str1.T
    hash_str3 = hash_str2.reshape(1, -1)[0].tolist()
    dhash_str = ''.join([str(x) for x in hash_str3])
    return dhash_str


def hammingDist(s1, s2):
    assert len(s1) == len(s2)
    return sum([ch1 != ch2 for ch1, ch2 in zip(s1, s2)])


# 通过得到RGB每个通道的直方图来计算相似度
def classify_hist_with_split(image1, image2, size=(256, 256)):
    # 将图像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 += calculate(im1, im2)
    sub_data = sub_data / 3
    return sub_data


# 计算单通道的直方图的相似值
def calculate(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


if __name__ == '__main__':
    raw_img1 = '12.jpg'
    raw_img2 = '13.jpg'
    img1 = cv2.imread(raw_img1)
    img2 = cv2.imread(raw_img2)
    start = time.time()
    ahash_str1 = aHash(img1)
    ahash_str2 = aHash(img2)
    phash_str1 = pHash(img1)
    phash_str2 = pHash(img2)
    dhash_str1 = dHash(img1)
    dhash_str2 = dHash(img2)
    a_score = 1 - hammingDist(ahash_str1, ahash_str2) * 1. / (32 * 32 / 4)
    p_score = 1 - hammingDist(phash_str1, phash_str2) * 1. / (32 * 32 / 4)
    d_score = 1 - hammingDist(dhash_str1, dhash_str2) * 1. / (32 * 32 / 4)
    n = classify_hist_with_split(img1, img2)
    print('三直方图算法相似度:', n)
end = time.time()
print('a_score:{},p_score:{},d_score{}'.format(a_score, p_score, d_score))
print("Total Spend time:", str((end - start) / 60)[0:6] + "分钟")

直方图

1

import matplotlib.pyplot as plt
import cv2
img = cv2.imread("12.jpg")
img1 = cv2.imread("13.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直方图展示
plt.subplot(2, 1, 1)
plt.plot(H1)
plt.subplot(2, 1, 2)
plt.plot(H2)
plt.show()

2

from PIL import Image


def make_regalur_image(img, size=(256, 256)):
    return img.resize(size).convert('RGB')


def hist_similar(lh, rh):
    assert len(lh) == len(rh)
    return sum(1 - (0 if l == r else float(abs(l - r)) / max(l, r)) for l, r in zip(lh, rh)) / len(lh)


def calc_similar(li, ri):
    return hist_similar(li.histogram(), ri.histogram())


if __name__ == '__main__':
    img1 = Image.open('12.jpg')
    img1 = make_regalur_image(img1)
    img2 = Image.open('13.jpg')
    img2 = make_regalur_image(img2)
    print(calc_similar(img1, img2))

3

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt


def create_rgb_hist(image):
    """"创建 RGB 三通道直方图(直方图矩阵)"""
    h, w, c = image.shape
    # 创建一个(16*16*16,1)的初始矩阵,作为直方图矩阵
    # 16*16*16的意思为三通道每通道有16个bins
    rgbhist = np.zeros([16 * 16 * 16, 1], np.float32)
    bsize = 256 / 16
    for row in range(h):
        for col in range(w):
            b = image[row, col, 0]
            g = image[row, col, 1]
            r = image[row, col, 2]
            # 人为构建直方图矩阵的索引,该索引是通过每一个像素点的三通道值进行构建
            index = int(b / bsize) * 16 * 16 + int(g / bsize) * 16 + int(r / bsize)
            # 该处形成的矩阵即为直方图矩阵
            rgbhist[int(index), 0] += 1
    plt.ylim([0, 10000])
    plt.grid(color='r', linestyle='--', linewidth=0.5, alpha=0.3)
    return rgbhist


def hist_compare(image1, image2):
    """直方图比较函数"""
    # 创建第一幅图的rgb三通道直方图(直方图矩阵)
    hist1 = create_rgb_hist(image1)
    # 创建第二幅图的rgb三通道直方图(直方图矩阵)
    hist2 = create_rgb_hist(image2)
    # 进行三种方式的直方图比较
    match1 = cv.compareHist(hist1, hist2, cv.HISTCMP_BHATTACHARYYA)
    match2 = cv.compareHist(hist1, hist2, cv.HISTCMP_CORREL)
    match3 = cv.compareHist(hist1, hist2, cv.HISTCMP_CHISQR)
    print("巴氏距离:%s, 相关性:%s, 卡方:%s" % (match1, match2, match3))


src1 = cv.imread("q.jpg")
cv.imshow("diff1", src1)
src2 = cv.imread("q2.jpg")
cv.imshow("diff2", src2)
plt.subplot(1, 2, 1)
plt.title("diff1")
plt.plot(create_rgb_hist(src1))
plt.subplot(1, 2, 2)
plt.title("diff2")
plt.plot(create_rgb_hist(src2))
hist_compare(src1, src2)
plt.show()
cv.waitKey(0)
cv.destroyAllWindows()

圈出不同处

1

from skimage.measure import compare_ssim
import imutils
import cv2
import numpy as np

imageA = cv2.imread("11.jpg")
imageB = cv2.imread("12.jpg")
imageB = np.resize(imageB, (imageA.shape[0], imageA.shape[1], imageA.shape[2]))
grayA = cv2.cvtColor(imageA, cv2.COLOR_BGR2GRAY)
grayB = cv2.cvtColor(imageB, cv2.COLOR_BGR2GRAY)
(score, diff) = compare_ssim(grayA, grayB, full=True)
diff = (diff * 255).astype("uint8")
print("SSIM:{}".format(score))
print(diff)
thresh = cv2.threshold(diff, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]
cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if imutils.is_cv2() else cnts[1]
for c in cnts:
    (x, y, w, h) = cv2.boundingRect(c)
    cv2.rectangle(imageA, (x, y), (x + w, y + h), (0, 0, 255), 2)
    cv2.rectangle(imageB, (x, y), (x + w, y + h), (0, 0, 255), 2)
cv2.imshow("Modified", imageB)
#cv2.imwrite("haha2.png", imageB)
cv2.waitKey(0)

2

import cv2
from matplotlib import pyplot as plt
import numpy as np

def matchAB(fileA, fileB):
    # 读取图像数据
    imgA = cv2.imread(fileA)
    imgB = cv2.imread(fileB)
    # 转换成灰色
    grayA = cv2.cvtColor(imgA, cv2.COLOR_BGR2GRAY)
    grayB = cv2.cvtColor(imgB, cv2.COLOR_BGR2GRAY)
    # 获取图片A的大小
    height, width = grayA.shape
    # 取局部图像,寻找匹配位置
    result_window = np.zeros((height, width), dtype=imgA.dtype)
    for start_y in range(0, height - 100, 10):
        for start_x in range(0, width - 100, 10):
            window = grayA[start_y:start_y + 100, start_x:start_x + 100]
            match = cv2.matchTemplate(grayB, window, cv2.TM_CCOEFF_NORMED)
            _, _, _, max_loc = cv2.minMaxLoc(match)
            matched_window = grayB[max_loc[1]:max_loc[1] + 100, max_loc[0]:max_loc[0] + 100]
            result = cv2.absdiff(window, matched_window)
            result_window[start_y:start_y + 100, start_x:start_x + 100] = result
    # 用四边形圈出不同部分
    _, result_window_bin = cv2.threshold(result_window, 30, 255, cv2.THRESH_BINARY)
    _, contours, _ = cv2.findContours(result_window_bin, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    imgC = imgA.copy()
    for contour in contours:
        min = np.nanmin(contour, 0)
        max = np.nanmax(contour, 0)
        loc1 = (min[0][0], min[0][1])
        loc2 = (max[0][0], max[0][1])
        cv2.rectangle(imgC, loc1, loc2, 255, 2)
    plt.subplot(1, 3, 1), plt.imshow(cv2.cvtColor(imgA, cv2.COLOR_BGR2RGB)), plt.title('A'), plt.xticks([]), plt.yticks(
        [])
    plt.subplot(1, 3, 2), plt.imshow(cv2.cvtColor(imgB, cv2.COLOR_BGR2RGB)), plt.title('B'), plt.xticks([]), plt.yticks(
        [])
    plt.subplot(1, 3, 3), plt.imshow(cv2.cvtColor(imgC, cv2.COLOR_BGR2RGB)), plt.title('Answer'), plt.xticks(
        []), plt.yticks([])
    plt.show()

matchAB('11.jpg', '12.jpg')

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
图像相似计算计算两张图像之间的相似程度,通常用于图像检索、图像分类、图像匹配等领域。基于深度学习的图像相似计算方法可以获得更高的准确度和鲁棒性。 在pytorch深度学习框架下,一种常见的图像相似计算方法是使用卷积神经网络(Convolutional Neural Network,CNN)提取图像特征,然后计算特征向量之间的余弦相似度。 具体实现步骤如下: 1. 加载图像数据集,对图像进行预理,例如归一化、裁剪、缩放等。 2. 加载预训练的CNN模型,例如VGG、ResNet等。 3. 将每张图像输入CNN模型,提取图像特征。 4. 对于每张图像,将其特征向量进行归一化,例如使用L2范数。 5. 计算两张图像特征向量之间的余弦相似度,即可得到它们之间的相似程度。 下面是一个简单的示例代码: ```python import torch import torch.nn as nn import torchvision.models as models import torchvision.transforms as transforms from PIL import Image # 加载预训练的VGG模型 model = models.vgg16(pretrained=True) # 截断模型最后一层,只保留前面的特征提取层 model = nn.Sequential(*list(model.features.children())[:-1]) # 设置模型为评估模式 model.eval() # 图像理 img_transforms = transforms.Compose([ transforms.Resize((224, 224)), transforms.ToTensor(), transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) ]) # 加载测试图像 img1 = Image.open('test_img1.jpg') img2 = Image.open('test_img2.jpg') # 对测试图像进行预理 img1_tensor = img_transforms(img1).unsqueeze(0) img2_tensor = img_transforms(img2).unsqueeze(0) # 提取图像特征 feat1 = model(img1_tensor) feat2 = model(img2_tensor) # 归一化特征向量 feat1_norm = feat1 / torch.norm(feat1, p=2, dim=1, keepdim=True) feat2_norm = feat2 / torch.norm(feat2, p=2, dim=1, keepdim=True) # 计算余弦相似度 similarity = torch.mm(feat1_norm, feat2_norm.transpose(0, 1)) print(similarity.item()) ``` 注意,上述代码中使用的是VGG16模型,如果需要使用ResNet等其他预训练模型,只需将第2步中的模型替换为相应的模型即可。同时,如果需要计算多张图像之间的相似度,只需对每张图像分别进行上述步骤即可。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值