OpenCV检查图像是否相似

参考:
https://stackoverflow.com/questions/11541154/checking-images-for-similarity-with-opencv


1、比较直方图

最简单和最快速的方法之一。 建议几十年前作为一种手段来找到图片相似之处。 这个想法是,一个森林将有很多的绿色,人脸很多粉红色,或其他颜色。 所以,如果你将两幅图片的森林进行比较,你会得到直方图之间的一些相似之处,因为两者都有很多的绿色。

缺点:这太简单了。 香蕉和海滩看起来是一样的,因为两者都是黄色的。

OpenCV方法:compareHist()


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

img=cv2.imread("messi5.jpg")

# Comparing histograms
H1=cv2.calcHist([img],[1],None,[256],[0,256]) # 统计第2个波段
H1=cv2.normalize(H1,H1,0,1,cv2.NORM_MINMAX,-1) # 归一化
H2=cv2.calcHist([img],[2],None,[256],[0,256])
H2=cv2.normalize(H2,H2,0,1,cv2.NORM_MINMAX,-1)

Similarity=cv2.compareHist(H1,H2,0) # 比较直方图
print(Similarity) # 0.55

plt.subplot(2,1,1);plt.plot(H1)
plt.subplot(2,1,2);plt.plot(H2)
plt.show()

2、模板匹配

这里的一个很好的例子是matchTemplate找到好匹配。 它将搜索图像与正在搜索的图像进行卷积。 通常用于查找更大的图像部分。

缺点:只有相同的图像,相同的尺寸和方向才能返回良好的效果。
OpenCV方法:matchTemplate()


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

img = cv2.imread('messi5.jpg',1)
img2 = img.copy()
template = cv2.imread('messi_face.jpg',1)
template=cv2.resize(template,None,fx=1.5,fy=2)
h, w,c = template.shape

# All the 6 methods for comparison in a list
methods = ['cv2.TM_CCOEFF', 'cv2.TM_CCOEFF_NORMED', 'cv2.TM_CCORR',
            'cv2.TM_CCORR_NORMED', 'cv2.TM_SQDIFF', 'cv2.TM_SQDIFF_NORMED']


# Apply template Matching
res = cv2.matchTemplate(img,template,cv2.TM_CCOEFF)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
top_left = max_loc
bottom_right = (top_left[0] + h, top_left[1] + w)

cv2.rectangle(img,top_left, bottom_right, 255, 2)

plt.subplot(121),plt.imshow(res,cmap = 'gray')
plt.title('Matching Result'), plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(img,cmap = 'gray')
plt.title('Detected Point'), plt.xticks([]), plt.yticks([])
plt.suptitle("TM_CCOEFF")

plt.show()

附加

参考:https://stackoverflow.com/questions/8218997/how-to-detect-the-sun-from-the-space-sky-in-opencv/8221251#8221251

霍夫圆变换找太阳

# -*- coding: UTF-8 -*-
import cv2
import numpy as np

image=cv2.imread("b2gUH.png")

# Color to Gray
gray=cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)

# color threshold
_,gray=cv2.threshold(gray,150,255,cv2.THRESH_BINARY)

# Morphologic open for 2 times
dst=cv2.morphologyEx(gray,cv2.MORPH_OPEN,None,iterations=2)


# 使用霍夫圆变换
circles = cv2.HoughCircles(dst,cv2.HOUGH_GRADIENT,12,dst.shape[1]/2,
                            param1=50,param2=30,minRadius=0,maxRadius=0)

circles = np.uint16(np.around(circles))
for i in circles[0,:]:
    # draw the outer circle
    cv2.circle(image,(i[0],i[1]),i[2],(0,255,0),2)
    # draw the center of the circle
    cv2.circle(image,(i[0],i[1]),2,(0,0,255),3)


cv2.imshow("dst",image)
cv2.waitKey(0)
cv2.destroyAllWindows()

模板匹配找太阳

# -*- coding: UTF-8 -*-

import cv2
import numpy as np

# Load image and template
img=cv2.imread("b2gUH.png")
templ =cv2.imread("sun.png")

# Create the result matrix
result_cols = img.shape[1] - templ.shape[1] + 1;
result_rows = img.shape[0] - templ.shape[0] + 1;

result=np.zeros([result_rows,result_cols],np.float32)

# Do the Matching and Normalize
result=cv2.matchTemplate(img,templ,cv2.TM_CCOEFF)
cv2.normalize(result,result,0,1,cv2.NORM_MINMAX,-1)

min_val, max_val, min_loc, max_loc=cv2.minMaxLoc(result)

top_left = max_loc
bottom_right = (top_left[0] + templ.shape[0], top_left[1] + templ.shape[1])

cv2.rectangle(img,top_left,bottom_right,(0, 255, 0),2,cv2.LINE_AA)
cv2.rectangle(result,top_left,bottom_right,(0, 255, 0),2,cv2.LINE_AA)

cv2.imshow("img",img)
cv2.imshow("result",result)
cv2.waitKey(0)
cv2.destroyAllWindows()

3、特征匹配

被认为是最有效的图像搜索方法之一。 从图像中提取许多特征,以确保即使旋转/缩放/倾斜也能再次识别相同的特征。 以这种方式提取的特征可以与其他图像特征集匹配。 另一个在第一个图像中具有高比例特征的图像很可能描绘了同一个对象/场景。 它可以用来查找图片之间拍摄角度的相对差异,或重叠的数量。

这里有一些OpenCV的教程/示例,还有一个很好的视频。 整个OpenCV模块(features2d)专门用于它。
缺点:可能会很慢。 这并不完美。
http://answers.opencv.org/question/877/how-to-match-2-hog-for-object-detection/#882

4、方法总结

import cv2

class CompareImage(object):

    def __init__(self, image_1_path, image_2_path):
        self.minimum_commutative_image_diff = 0.25
        self.image_1_path = image_1_path
        self.image_2_path = image_2_path

    def compare_image(self):
        image_1 = cv2.imread(self.image_1_path, 0)
        image_2 = cv2.imread(self.image_2_path, 0)
        img_hist_diff, img_template_diff, commutative_image_diff = self.get_image_difference(image_1, image_2)

        if img_hist_diff<0.3 and img_template_diff<0.3:
            if commutative_image_diff < self.minimum_commutative_image_diff:
                print("Matched")
                return commutative_image_diff
        return 10000 # random failure value

    @staticmethod
    def get_image_difference(image_1, image_2):
        first_image_hist = cv2.calcHist([image_1], [0], None, [256], [0, 256])
        second_image_hist = cv2.calcHist([image_2], [0], None, [256], [0, 256])

        img_hist_diff = 1-cv2.compareHist(first_image_hist, second_image_hist,0)
        img_template_probability_match = cv2.matchTemplate(first_image_hist, second_image_hist, cv2.TM_CCOEFF_NORMED)[0][0]
        img_template_diff = 1 - img_template_probability_match

        # taking only 10% of histogram diff, since it's less accurate than template method
        commutative_image_diff = (img_hist_diff / 10) + img_template_diff
        return [img_hist_diff,img_template_diff,commutative_image_diff]


if __name__ == '__main__':
    compare_image = CompareImage('E:/07/L15-3345E-2311N.tif', 'E:/08/L15-3345E-2311N.tif')
    image_difference = compare_image.compare_image()
    print(image_difference)
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值