两个图像之间的直方图比较

Histogram comparison between two images

我是直方图比较的新手。

此代码使用这些图像进行直方图比较。结果令人印象深刻,为 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)

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

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

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
----------------------------------------

您只需提高 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)