Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/image/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
python+;opencv-如何正确比较图像(通过直方图)?_Python_Image_Opencv_Comparison_Histogram - Fatal编程技术网

python+;opencv-如何正确比较图像(通过直方图)?

python+;opencv-如何正确比较图像(通过直方图)?,python,image,opencv,comparison,histogram,Python,Image,Opencv,Comparison,Histogram,我有一堆图片(来自M.C.Escher收藏),我想整理,所以我想做的第一步是将它们分组,通过比较它们(你知道,有些有不同的分辨率/形状,等等) 我写了一个非常残酷的剧本: *读文件 *计算它们的直方图 *比较它们 但是比较的质量确实很低,就像有些文件匹配完全不同一样 看看我到目前为止写的东西: 准备直方图 文件\u hist={} 对于枚举中的i,f(文件): 尝试: 帧=cv2.imread(f) frame=cv2.CVT颜色(frame,cv2.COLOR\u BGR2GRAY) hist

我有一堆图片(来自M.C.Escher收藏),我想整理,所以我想做的第一步是将它们分组,通过比较它们(你知道,有些有不同的分辨率/形状,等等)

我写了一个非常残酷的剧本: *读文件 *计算它们的直方图 *比较它们

但是比较的质量确实很低,就像有些文件匹配完全不同一样

看看我到目前为止写的东西:

准备直方图

文件\u hist={}
对于枚举中的i,f(文件):
尝试:
帧=cv2.imread(f)
frame=cv2.CVT颜色(frame,cv2.COLOR\u BGR2GRAY)
hist=cv2.calcHist([frame],[0],无[4096],[04096])
cv2.规范化(hist,hist,alpha=0,beta=1,norm\u type=cv2.norm\u MINMAX)
文件\u hist[f]=hist
例外情况除外,如e:
打印('错误:',f,e)
比较直方图

pairs=list(itertools.compositions(files\u hist.keys(),2))
对于枚举(成对)中的i(f1,f2):
correl=cv2.compareHist(文件历史[f1]、文件历史[f2]、cv2.HISTCMP\u correl)
如果相关系数>=0.999:
打印('MATCH:',correl,f1,f2)
现在,例如,我得到了这两个文件的匹配项:

m、 (1933).jpg

m、 (1931).jpg

使用上面的代码,它们的相关性是
0.999669595530539
(因此它们实际上是相同的:()

我做错了什么?如何改进代码以避免这种错误匹配


谢谢!

直方图不是比较图像的好方法,例如,在黑白图像中,如果它们具有相同数量的黑色像素,则直方图将是相同的,而不管图像中的像素分布如何(这就是为什么您提到的图像被分类为几乎相等)

有更好的方法量化图像之间的差异,提到了一个好的选择:

  • 将两个图像加载为数组(scipy.misc.imread)并计算元素差异(逐像素)。计算差异的范数
编辑:

回答一些问题:

我认为每像素的零范数是0.0-1.0,值接近0.0意味着“图像相同”,对吗

接近0.0的值表示像素相同。要将图像作为一个整体进行比较,需要对所有像素进行求和。如果求和值接近0.0,则表示图像几乎相同

如果两个图像大小不同怎么办

这是一个很好的方法。要计算范数差,图像必须具有相同的大小。我认为有两种方法可以实现这一点:

  • 第一种方法是将一个图像的大小调整为另一个图像的形状,问题是这会导致图像失真

  • 第二种方法是用零填充较小的图像,直到大小匹配为止

obs:如果按像素标准求和,则图像中的像素数将介于零和像素数之间。如果比较多个图像,这可能会造成混淆。例如,假设您比较图像a和B,并且两个图像的形状均为50x50(因此,图像有2500个像素);接近2500的值表示图像完全不同。现在假设您比较图像C和D,并且两者的形状都为1000x1000,在这种情况下,2500这样的值表示图像相似。要解决此问题,您可以将像素总和除以图像中的像素数,这将导致一个介于0.0和1000之间的值1.0,0.0表示图像相同,1.0表示图像完全不同


是的,这是我在比较两个大小不同的图像时收到的错误
diff=image1-image2 ValueError:操作数无法与形状一起广播(850534)(663650)


这是因为图像具有不同的形状。调整大小或填充可以避免此错误(如上所述)。

您可以尝试使用
cv::norm()
使用
NORM_L2
方法比较两幅图像,这是比较的目的。找到相似的图像?找到重复的,其他的?目的是找到重复的,是的,这是主要目的(我还有另一个项目,比较视频,在特定的时间间隔抓取帧并进行比较)谢谢Heitor!这是一个非常有趣的方法,我只是继续尝试一下。一些问题:*我认为每像素的零范数将是0.0-1.0值,值接近0.0表示“图像相同”,对吗?*如果两个图像大小不同怎么办?每像素的零范数将稍微偏离,不是吗(因为它使用了
img1.size
)?是的,这是我在比较两个大小不同的图像时收到的错误``diff=image1-image2 ValueError:操作数无法与形状一起广播(850534)(663650)“``我还使用了和中的注释中提到的略读功能,但仍然不走运:要么匹配很少(即使图像“明显”相同),要么匹配太宽:(