Answers:
这是一个巨大的话题,从3行代码到整本研究杂志的答案。
我将概述最常见的此类技术及其结果。
最简单,最快的方法之一。几十年前作为寻找图片相似性的方法而提出。这个想法是,森林将有很多绿色,而人的脸会有很多粉红色,或者其他。因此,如果将两张图片与森林进行比较,则直方图之间会有些相似之处,因为两者中都有很多绿色。
缺点:太简单了。香蕉和沙滩看起来一样,都是黄色。
OpenCV方法:compareHist()
这里的一个很好的例子matchTemplate找到了很好的match。它会将搜索图像与要搜索的图像卷积在一起。通常用于在较大的图像中找到较小的图像部分。
缺点:只有相同的图像,相同的尺寸和方向,它才能返回良好的效果。
OpenCV方法:matchTemplate()
被认为是进行图像搜索的最有效方法之一。从图像中提取许多特征,以确保即使旋转,缩放或倾斜也可以再次识别相同的特征。以此方式提取的特征可以与其他图像特征集进行匹配。具有匹配第一个特征的大部分特征的另一幅图像被视为描绘了同一场景。
通过找到两组点之间的单应性,您还可以找到原始图片之间的拍摄角度或重叠量的相对差异。
有许多OpenCV的教程/样本对这个的,和一个不错的视频在这里。整个OpenCV模块(features2d)专用于它。
缺点:可能会很慢。这不是完美的。
在OpenCV问答网站上,我谈论的是特征描述符之间的差异,当比较整个图像和纹理描述符(用于识别图像中的人脸或汽车)时,这非常好。
absdiff
codota.com/code/java/methods/org.opencv.core.Core/absdiff 阈值化结果产生一个遮罩,使您可以突出显示因场景而异的区域。
如果要匹配相同的图像(相同的尺寸/方向)
// 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
}
山姆的解决方案应该足够了。我使用了直方图差异和模板匹配的组合,因为没有一种方法在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))
在定义了两个标准图片(或矩阵)之后,您可以对要比较的图片的乘法求和:
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
请注意,如果您有彩色图片,则必须在所有三个维度上执行此操作,或者只是比较灰度版本。我经常不得不将大量图片与任意内容进行比较,这是一种非常快捷的方法。