OpenCV 比较图像

Ammar Ali 2024年2月15日
  1. 使用 OpenCV 的 norm() 函数比较图像
  2. 使用 OpenCV 的 compareHist() 函数比较图像
  3. OpenCV 的 calcHist()normalize() 函数的参数
OpenCV 比较图像

本教程将讨论使用 OpenCV 的 norm()compareHist() 函数比较图像。

使用 OpenCV 的 norm() 函数比较图像

如果我们要比较的两个图像具有相同的大小和方向,我们可以使用 OpenCV 的 norm() 函数。此函数查找两个图像的相同像素中存在的错误。

我们必须找到 L2 误差,也就是平方误差和的平方根,然后将其除以图像中存在的像素总数,以找出它们之间的相似性。

我们通过将行数乘以给定图像之一中存在的列数来获得像素总数。

例如,让我们使用 NumPyzeros() 函数创建两个相同的图像,并使用 norm() 函数找到它们的相似性。请参阅下面的代码。

import cv2
import numpy as np

height = 312
width = 312
A = np.zeros((height, width, 3), np.uint8)

B = np.zeros((height, width, 3), np.uint8)

errorL2 = cv2.norm(A, B, cv2.NORM_L2)
similarity = 1 - errorL2 / (height * width)
print("Similarity = ", similarity)

cv2.imshow("A", A)
cv2.imshow("B", B)
cv2.waitKey(0)

输出:

Similarity =  1.0

图像相似度 1

正如我们所见,两个图像是相同的。这就是为什么相似度是 1% 或 100%。

现在让我们在一张图像中添加一些颜色并与另一张图像进行比较。

例如,让我们将一半图像的颜色设置为红色,然后将其与另一张图像进行比较。请参阅下面的代码。

import cv2
import numpy as np

height = 312
width = 312
A = np.zeros((height, width, 3), np.uint8)

B = np.zeros((height, width, 3), np.uint8)
B[0 : width // 2, :, :] = (0, 0, 255)

errorL2 = cv2.norm(A, B, cv2.NORM_L2)
similarity = 1 - errorL2 / (height * width)
print("Similarity = ", similarity)

cv2.imshow("A", A)
cv2.imshow("B", B)
cv2.waitKey(0)

输出:

Similarity =  0.4220761884533025

使用范数的图像相似度

由于一张图像中的红色,相似度有所降低。

此方法仅在两个图像具有相同大小和方向时才有用;否则,此方法无用。

使用 OpenCV 的 compareHist() 函数比较图像

我们可以使用 OpenCV 的 compareHist() 函数找到两个图像之间的相似性。compareHist() 函数根据颜色比较两个图像的直方图。

此方法仅根据颜色比较图像,因此在我们不关心对象的形状或方向的地方很有用。

例如,一棵树和一片森林将具有 100% 的相似性,因为这两个图像都有许多绿色。

要使用 compareHist() 函数比较两个图像,我们必须使用 OpenCV 的 cvt.Color() 函数将图像转换为 HSV,然后使用 calcHist() 函数找到图像的直方图。

之后,我们可以使用 normalize() 函数对直方图进行归一化以进行比较。然后,我们必须在 compareHist() 函数中传递两个图像的归一化直方图以及比较方法。

compareHist() 函数将相似度作为浮点数返回。如果相似度为 1,则表示图像 100% 相同,如果接近 0,则表示两幅图像不相似。

例如,让我们使用其中包含多个水果的图像作为基础图像,并使用另外两个也包含单个水果的测试图像。

请参阅下面的代码。

import cv2 as cv
import numpy as np

base = cv.imread("Base.jpg")
test = cv.imread("test.jpg")
test2 = cv.imread("test2.jpg")

hsv_base = cv.cvtColor(base, cv.COLOR_BGR2HSV)
hsv_test = cv.cvtColor(test, cv.COLOR_BGR2HSV)
hsv_test2 = cv.cvtColor(test2, cv.COLOR_BGR2HSV)

h_bins = 50
s_bins = 60
histSize = [h_bins, s_bins]
h_ranges = [0, 180]
s_ranges = [0, 256]
ranges = h_ranges + s_ranges
channels = [0, 1]

hist_base = cv.calcHist([hsv_base], channels, None, histSize, ranges, accumulate=False)
cv.normalize(hist_base, hist_base, alpha=0, beta=1, norm_type=cv.NORM_MINMAX)
hist_test = cv.calcHist([hsv_test], channels, None, histSize, ranges, accumulate=False)
cv.normalize(hist_test, hist_test, alpha=0, beta=1, norm_type=cv.NORM_MINMAX)
hist_test2 = cv.calcHist(
    [hsv_test2], channels, None, histSize, ranges, accumulate=False
)
cv.normalize(hist_test2, hist_test2, alpha=0, beta=1, norm_type=cv.NORM_MINMAX)

compare_method = cv.HISTCMP_CORREL

base_base = cv.compareHist(hist_base, hist_base, compare_method)
base_test = cv.compareHist(hist_base, hist_test, compare_method)
base_test2 = cv.compareHist(hist_base, hist_test2, compare_method)

print("base_base Similarity = ", base_base)
print("base_test Similarity = ", base_test)
print("base_test2 Similarity = ", base_test2)

cv.imshow("base", base)
cv.imshow("test1", test)
cv.imshow("test2", test2)
cv.waitKey(0)

输出:

base_base Similarity =  1.0
base_test Similarity =  0.9850943125966266
base_test2 Similarity =  -0.00323646777704442

使用直方图比较图像

如输出所示,基本图像与基本图像的相似度为 1% 或 100%,因为两个图像相同。

test 图像与基本图像的相似度为 0.98 或 98%,因为 test 图像包含的香蕉也存在于基本图像中。

test2 图像与基本图像的相似度接近于 0,因为 test2 图像中存在的水果和颜色在基本图像中不存在。

OpenCV 的 calcHist()normalize() 函数的参数

在上面的代码中,calcHist() 函数的第一个参数是 HSV 颜色空间中的图像。第二个参数是我们想要用来查找直方图的给定图像的通道。

第三个参数用于传递掩码,如果我们想查找图像的一部分而不是整个图像的直方图,它会很有用。第四个参数是直方图的大小,它包含直方图箱的高度和大小。

第五个参数是 HSV 颜色空间的色调和饱和度范围。

normalize() 函数的第一个参数是我们想要标准化的源图像。

第二个参数是目标图像,创建具有我们所需尺寸或大小的输出图像。第三个参数是我们想要标准化图像的范围的下限值。

第四个参数是我们想要标准化图像的范围的上限值。第五个参数是归一化类型,如 cv2.NORM_INFcv2.NORM_L1cv2.NORM_MINMAX

每个归一化类型都使用其公式来计算归一化。第六个参数用于设置输出图像的数据类型。

第七个参数用于创建遮罩,当我们不想标准化整个图像时它很有用。相反,我们只想规范化图像的一部分。

我们可以在掩码中定义该部分,以便仅对掩码部分执行归一化。

我们在 compareHist() 函数中使用了相关方法,但也可以使用其他方法来比较直方图。

单击此链接了解有关直方图方法的更多详细信息。

作者: Ammar Ali
Ammar Ali avatar Ammar Ali avatar

Hello! I am Ammar Ali, a programmer here to learn from experience, people, and docs, and create interesting and useful programming content. I mostly create content about Python, Matlab, and Microcontrollers like Arduino and PIC.

LinkedIn Facebook

相关文章 - OpenCV Image