检查图像是否与OpenCV相似

OpenCV支持两个图像的比较,返回一些值(可能是一个百分比),表明这些图像有多相似? 例如,如果两次传递相同的图像,则返回100%,如果图像完全不同,则返回0%。

我已经在StackOverflow上阅读了很多类似的主题。 我也做了一些谷歌search。 可悲的是我不能拿出一个满意的答案。

这是一个非常大的话题,从三行代码到整个研究杂志的答案。

我将概述最常见的这种技术及其结果。

比较直方图

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

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

OpenCV方法:compareHist()

模板匹配

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

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

function匹配

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

这里有一些OpenCV的教程/示例,还有一个很好的video。 整个OpenCV模块(features2d)专门用于它。
缺点:可能会很慢。 这并不完美。

  • 你可以在这里find更详细的信息和其他类似的技术: http : //answers.opencv.org/question/877/how-to-match-2-hog-for-object-detection/#882

如果为了匹配相同的图像(相同的尺寸/方向)

// Compare two images by getting the L2 error (square-root of sum of squared error). double getSimilarity( const Mat A, const Mat B ) { if ( A.rows > 0 && A.rows == B.rows && A.cols > 0 && A.cols == B.cols ) { // Calculate the L2 relative error between images. double errorL2 = norm( A, B, CV_L2 ); // Convert to a reasonable scale, since L2 error is summed across all pixels of the image. double similarity = errorL2 / (double)( A.rows * A.cols ); return similarity; } else { //Images have a different size return 100000000.0; // Return a bad value } 

资源

山姆的解决scheme应该是足够的。 我已经使用了直方图差异和模板匹配的组合,因为没有一种方法在100%的时间里为我工作。 虽然我已经不太重视直方图的方法。 以下是我用简单的python脚本实现的方法。

 import cv2 class CompareImage(object): def __init__(self, image_1_path, image_2_path): self.minimum_commutative_image_diff = 1 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) commutative_image_diff = self.get_image_difference(image_1, image_2) 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 = cv2.compareHist(first_image_hist, second_image_hist, cv2.HISTCMP_BHATTACHARYYA) 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 commutative_image_diff if __name__ == '__main__': compare_image = CompareImage('image1/path', 'image2/path') image_difference = compare_image.compare_image() print image_difference 

有点脱离主题,但有用的是pythonic numpy方法。 它的强大和快速,但只是比较像素,而不是对象或图片包含的数据(它需要相同大小和形状的图像):

如果没有openCV和任何用于计算机视觉的库,一个非常简单而快速的方法是通过规范图片数组

 import numpy as np picture1 = np.random.rand(100,100) picture2 = np.random.rand(100,100) picture1_norm = picture1/np.sqrt(np.sum(picture1**2)) picture2_norm = picture2/np.sqrt(np.sum(picture2**2)) 

在定义两个规范图片(或matrix)之后,您可以将您想要比较的图片相乘的总和相加:

1)如果您比较相似的图片,总和将返回1:

 In[1]: np.sum(picture1_norm**2) Out[1]: 1.0 

2)如果他们不相似,你会得到一个介于0和1之间的值(如果乘以100,则为一个百分比):

 In[2]: np.sum(picture2_norm*picture1_norm) Out[2]: 0.75389941124629822 

请注意,如果您有彩色图片,则必须在所有三维中进行此操作,或仅比较灰度版本。 我经常需要比较大量的图片与任意内容,这是一个非常快速的方式来这样做。