「乾貨」教你如何用OpenCV快速尋找影象差異處

dicksonjyl560101發表於2019-08-10
「乾貨」教你如何用OpenCV快速尋找影象差異處


如何使用結構相似性指數(SSIM)將兩個影象與Python進行比較。

使用這種方法,我們能夠輕鬆確定兩個影象是否相同或由於輕微的影象處理,壓縮偽像或有目的的篡改而產生差異。

今天我們將擴充套件SSIM方法,以便我們可以使用OpenCV和Python視覺化影象之間的差異。具體來說,我們將在兩個不同的輸入影象中的區域周圍繪製邊界框。


與OpenCV和Python的影象差異

為了計算兩個影象之間的差異,我們將利用結構相似性指數,由Wang等人首先介紹。在2004年的論文中,影象質量評估:從錯誤可見性到結構相似性。此方法已在scikit-image 庫中實現以進行影象處理。

訣竅是學習如何根據(x,y) -座標位置精確確定影象差異的位置。

為此,我們首先需要確保我們的系統具有Python,OpenCV,scikit-image和imutils。

您可以使用我的OpenCV安裝教程學習如何在系統上配置和安裝Python和OpenCV 。

如果您還沒有 scikit - 已安裝/升級映像,請通過以下方式升級:



 $ pip install --upgrade scikit-image

當你在這裡時,繼續安裝/升級 imutils :



$ pip install --upgrade imutils

現在我們的系統已經準備好了先決條件,讓我們繼續。

計算影象差異

你能發現這兩個影象之間的區別嗎?


「乾貨」教你如何用OpenCV快速尋找影象差異處


圖1:手動檢查兩個輸入影象(源)之間的差異

如果您花一秒鐘研究這兩張信用卡,您會注意到MasterCard徽標出現在 左側影象上,但已從右側影象中刪除 。

您可能已經立即注意到這種差異,或者可能已經花了幾秒鐘。無論哪種方式,這都證明了比較影象差異的一個重要方面 - 有時影象差異是微妙的 - 如此微妙以至於肉眼難以立即理解差異(我們將在本博文後面看到這樣一個影象的例子)。

那麼為什麼計算影象差異如此重要呢?

一個例子是 網路釣魚。攻擊者可以稍微操縱影象,以欺騙不驗證URL的毫無戒心的使用者,使他們認為他們正在登入他們的銀行網站 - 後來發現這是一個騙局。

將網頁上的徽標和已知使用者介面(UI)元素與現有資料集進行比較有助於減少網路釣魚攻擊(非常感謝Chris Cleveland傳遞 PhishZoo:通過檢視網路釣魚網站作為應用計算機視覺預防的示例來檢測網路釣魚網站網路釣魚)。

開發網路釣魚檢測系統顯然比簡單的影象差異複雜得多,但我們仍然可以應用這些技術來確定是否已經操縱了給定的影象。

現在,讓我們計算兩個影象之間的差異,並使用OpenCV,scikit-image和Python並排檢視差異。

開啟一個新檔案並將其命名為 image_diff .py ,並插入以下程式碼:



# import the necessary packages

from skimage.measure import compare_ssim
import argparse
import imutils
import cv2

# construct the argument parse and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-f", "--first", required=True,
help="first input image")
ap.add_argument("-s", "--second", required=True,
help="second")
args = vars(ap.parse_args())
# load the two input images
imageA = cv2.imread(args["first"])
imageB = cv2.imread(args["second"])

# convert the images to grayscale
grayA = cv2.cvtColor(imageA, cv2.COLOR_BGR2GRAY)
grayB = cv2.cvtColor(imageB, cv2.COLOR_BGR2GRAY)
# compute the Structural Similarity Index (SSIM) between the two
# images, ensuring that the difference image is returned
(score, diff) = compare_ssim(grayA, grayB, full=True)
diff = (diff * 255).astype("uint8")
print("SSIM: {}".format(score))
# threshold the difference image, followed by finding contours to
# obtain the regions of the two input images that differ
thresh = cv2.threshold(diff, 0, 255,
cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]
cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)
# loop over the contours
for c in cnts:
# compute the bounding box of the contour and then draw the
# bounding box on both input images to represent where the two
# images differ
(x, y, w, h) = cv2.boundingRect(c)
cv2.rectangle(imageA, (x, y), (x + w, y + h), (0, 0, 255), 2)
cv2.rectangle(imageB, (x, y), (x + w, y + h), (0, 0, 255), 2)

# show the output images
cv2.imshow("Original", imageA)
cv2.imshow("Modified", imageB)
cv2.imshow("Diff", diff)
cv2.imshow("Thresh", thresh)
cv2.waitKey(0)

第2-5行顯示我們的進口。我們將使用 compare_ssim (來自scikit-image), argparse , imutils 和 cv2 (OpenCV)。

我們建立兩個命令列引數, - first 和 - second ,它們是我們希望比較的兩個相應輸入影象的路徑(第8-13行)。

接下來,我們將從磁碟載入每個影象並將其轉換為灰度:

我們載入我們的第一和第二影象, - 第一 和 - 第二 ,上 線16和17,它們儲存為 imageA 和 imageB 分別。


「乾貨」教你如何用OpenCV快速尋找影象差異處


然後我們在第20行和第21行將每個轉換為灰度。


「乾貨」教你如何用OpenCV快速尋找影象差異處


接下來,讓我們計算兩個灰度影象之間的結構相似性指數(SSIM)。

使用 scikit-image中的 compare_ssim函式,我們計算 得分 和差異影象 diff (第25行)。

所述 得分 表示兩個輸入影象之間的結構相似性指數。該值可以落在[-1,1]範圍內 ,值為1是“完美匹配”。

該 差異 的影象包含實際 影象的差異 ,我們希望以視覺化的兩個輸入影象之間。差異影象當前表示為[0,1]範圍內的浮點資料型別, 因此我們首先將陣列轉換為[0,255](第26行)範圍內的8位無符號整數, 然後我們才能進一步處理它使用OpenCV。

現在,讓我們找到輪廓,以便我們可以在標識為“不同”的區域周圍放置矩形:

在 第31行和第32行,我們 使用cv2對我們的差異影象進行 閾值 處理。THRESH_BINARY_INV 和 cv2 。THRESH_OTSU - 使用垂直條'或'符號,|同時應用這兩個設定 。有關Otsu雙峰閾值設定的詳細資訊,請參閱此OpenCV文件。

隨後我們 在 第33-35行找到了thresh的輪廓 。第35行的三元運算子 簡單地適應了各種版本的OpenCV中cv2.findContours返回簽名之間的差異。

下面圖4中的影象清楚地顯示了已被操縱的影象的ROI:


「乾貨」教你如何用OpenCV快速尋找影象差異處


圖4:使用閾值處理使用OpenCV和Python突出顯示影象差異。

從第38行開始 ,我們遍佈我們的輪廓, cnts 。首先,我們使用cv2計算輪廓周圍的邊界框 。boundingRect 函式。我們將相關的 (x,y )座標儲存為 x 和 y 以及矩形的寬度/高度為 w 和 h 。

然後我們使用這些值在每個影象上用cv2繪製一個紅色矩形 。矩形 (第43和44行)。

最後,我們用差異影象,差異影象和閾值影象顯示比較影象(第47-50行)。

我們打電話給 cv2 。waitKey 上 50線,直到按下一個鍵,這使得程式等待(此時指令碼將退出)。


「乾貨」教你如何用OpenCV快速尋找影象差異處


接下來,讓我們執行指令碼並視覺化一些影象差異。

視覺化影象差異

使用此指令碼和以下命令,我們可以快速輕鬆地突出顯示兩個影象之間的差異:



$ python image_diff.py --first images/original_02.png 

--second images/modified_02.png

正如您在圖6中看到的那樣,安全晶片和帳戶持有者的名稱都被刪除了:


「乾貨」教你如何用OpenCV快速尋找影象差異處


讓我們嘗試另一個計算影象差異的例子,這次是由傑拉爾德·R·福特總統(來源)撰寫的支票。

通過執行下面的命令並提供相關影象,我們可以看到這裡的差異更加微妙:



$ python image_diff.py --first images/original_03.png 

--second images/modified_03.png


「乾貨」教你如何用OpenCV快速尋找影象差異處


請注意圖7中的以下更改:

  • 貝蒂福特的名字被刪除了。
  • 支票號碼已刪除。
  • 日期旁邊的符號將被刪除。
  • 姓氏已刪除。

在像檢查這樣的複雜影象上,通常很難用肉眼找到 所有差異。幸運的是,我們現在可以使用Python,OpenCV和scikit-image製作的這個方便的指令碼輕鬆計算差異並視覺化結果。

摘要

我們學習瞭如何使用OpenCV,Python和scikit-image的結構相似性指數(SSIM)來計算影象差異。基於影象差異,我們還學習瞭如何在兩個影象中標記和視覺化不同區域

https://www.toutiao.com/a6722969226115547656/

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29829936/viewspace-2653270/,如需轉載,請註明出處,否則將追究法律責任。

相關文章