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