【问题标题】:Histogram comparison between two images两幅图像之间的直方图比较
【发布时间】:2021-04-29 18:21:17
【问题描述】:

我是直方图比较的新手。

此代码使用这些图像进行直方图比较。结果令人印象深刻,为 0.99%,但我认为由于背景颜色,结果为 99%。谁能告诉我如何忽略白色并比较实际的水果。

以下代码被发现here

# Load the images
img1 = cv2.imread('D:/downloads/app1.jpg')
img2 = cv2.imread('D:/downloads/app2.jpg')

# Convert it to HSV
img1_hsv = cv2.cvtColor(img1, cv2.COLOR_BGR2HSV)
img2_hsv = cv2.cvtColor(img2, cv2.COLOR_BGR2HSV)

# Calculate the histogram and normalize it
hist_img1 = cv2.calcHist([img1_hsv], [0,1], None, [180,256], [0,180,0,256])
cv2.normalize(hist_img1, hist_img1, alpha=0, beta=1, norm_type=cv2.NORM_MINMAX);
hist_img2 = cv2.calcHist([img2_hsv], [0,1], None, [180,256], [0,180,0,256])
cv2.normalize(hist_img2, hist_img2, alpha=0, beta=1, norm_type=cv2.NORM_MINMAX);

# find the metric value
metric_val = cv2.compareHist(hist_img1, hist_img2, cv2.HISTCMP_BHATTACHARYYA)

【问题讨论】:

  • 在 cv2.calcHist() 中使用蒙版图像,这样它就不会计算白色像素。您可以通过对图像进行阈值处理来制作蒙版。见docs.opencv.org/4.1.1/d6/dc7/…
  • 请注意,在 HSV 颜色空间中,白色和黑色以及所有灰色与红色的色调相同。您可能在 BGR 或其他一些色彩空间(如 LAB)中产生了更好的结果。但无论您使用哪种色彩空间,蒙版都会有所帮助。

标签: python opencv histogram cv2


【解决方案1】:

按照 Fred 的建议使用一些遮罩似乎是最干净的解决方案,但 Fred 关于 HSV 颜色空间的评论在这里更为重要!但是,首先,0.99... 报告的度量值(也在链接文章中)是使用cv2.HISTCMP_CORREL 获得的,而不是使用cv2.HISTCMP_BHATTACHARYYA

现在,让我们坚持使用 OpenCV 常见的 BGR 颜色空间,并调整代码:

import cv2

# Load the images
img1 = cv2.imread('app1.png')
img2 = cv2.imread('app2.png')

# Calculate the histograms, and normalize them
hist_img1 = cv2.calcHist([img1], [0, 1, 2], None, [256, 256, 256], [0, 256, 0, 256, 0, 256])
cv2.normalize(hist_img1, hist_img1, alpha=0, beta=1, norm_type=cv2.NORM_MINMAX)
hist_img2 = cv2.calcHist([img2], [0, 1, 2], None, [256, 256, 256], [0, 256, 0, 256, 0, 256])
cv2.normalize(hist_img2, hist_img2, alpha=0, beta=1, norm_type=cv2.NORM_MINMAX)

# Find the metric value
metric_val = cv2.compareHist(hist_img1, hist_img2, cv2.HISTCMP_CORREL)
print(metric_val)
# 0.9995753648895891

指标值仍然是 99.9 %。

所以,现在,让我们通过手动设置hist_imgx[255, 255, 255] = 0 来忽略所有白色像素:

import cv2

# Load the images
img1 = cv2.imread('app1.png')
img2 = cv2.imread('app2.png')

# Calculate the histograms, set bin for (255, 255, 255) to 0, and normalize them
hist_img1 = cv2.calcHist([img1], [0, 1, 2], None, [256, 256, 256], [0, 256, 0, 256, 0, 256])
hist_img1[255, 255, 255] = 0
cv2.normalize(hist_img1, hist_img1, alpha=0, beta=1, norm_type=cv2.NORM_MINMAX)
hist_img2 = cv2.calcHist([img2], [0, 1, 2], None, [256, 256, 256], [0, 256, 0, 256, 0, 256])
hist_img2[255, 255, 255] = 0
cv2.normalize(hist_img2, hist_img2, alpha=0, beta=1, norm_type=cv2.NORM_MINMAX)

# Find the metric value
metric_val = cv2.compareHist(hist_img1, hist_img2, cv2.HISTCMP_CORREL)
print(metric_val)
# 0.6199666001215806

而且,指标值下降到 62 %!

所以,你的假设似乎是正确的,白色背景扭曲了整个直方图比较。

----------------------------------------
System information
----------------------------------------
Platform:      Windows-10-10.0.16299-SP0
Python:        3.9.1
PyCharm:       2021.1.1
OpenCV:        4.5.1
----------------------------------------

【讨论】:

  • 完美!我在找什么:)。它导致 99% 有点奇怪,这就是为什么我想在没有白色背景的情况下测试它。
  • 只是一个简单的问题。你能 plt.plot 那些直方图吗?
  • 你得到一个尺寸为[256, 256, 256]的NumPy数组,因为你有一些joint histogram用于所有三个通道。我可以想到 3 维、彩色编码的“图”,也许是散点图。如果您想到三个单图,则需要计算每个通道的三个边缘直方图。
  • @HansHirse 将白色计数设置为零是比屏蔽更简单的方法。不错!
  • 请忘记我所说的关于 3 维图的内容。您需要一些查看器来查看 3 维体积数据 - 最好,您可以滚动浏览所有三个轴,例如用于 CT 或 MRI 扫描的 DICOM 查看器。
【解决方案2】:

您只需要提高 HSV 蒙版的最小饱和度值即可有效地掩盖所有白色背景:

import cv2
import numpy as np

def get_masked(img):
    img_hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
    lower = np.array([0, 50, 0])
    upper = np.array([179, 255, 255])
    mask = cv2.inRange(img_hsv, lower, upper)
    return cv2.bitwise_and(img, img, mask=mask)

img1 = cv2.imread("apple1.png")
img2 = cv2.imread("apple2.png")

cv2.imshow("Apple 1", get_masked(img1))
cv2.imshow("Apple 2", get_masked(img2))

cv2.waitKey(0)

【讨论】:

    猜你喜欢
    • 2016-10-30
    • 2012-09-26
    • 1970-01-01
    • 1970-01-01
    • 2016-03-29
    • 2015-05-01
    • 2020-12-14
    • 2012-04-16
    • 2016-12-11
    相关资源
    最近更新 更多