Go語言如何判斷兩張圖片的相似度
在介紹技術(shù)細節(jié)前,我們先來看看圖片對比在哪些場景下可以用得到:
- 圖片去重:自動刪除重復圖片,為存儲空間"瘦身"。想象你是一個社交媒體平臺的運營,每天要處理數(shù)萬張圖片。重復圖片不僅占用存儲空間,還會影響用戶體驗。
- 內(nèi)容審核:一些平臺需要篩選相似或重復的內(nèi)容,防止版權(quán)侵犯和內(nèi)容垃圾。
- 版權(quán)維 權(quán):檢測圖片有無被未經(jīng)授權(quán)使用的情況,比如,攝影師和設(shè)計師需要知道自己的作品是否被未經(jīng)授權(quán)使用。
- 相似圖片搜索:網(wǎng)盤、云存儲服務需要幫助用戶清理重復文件。
在這些場景中,圖片對比技術(shù)可以幫我們自動化處理大量圖片,提高工作效率。
但是,圖片對比可不像字符那樣可以直接使用等于號=
直接對比,那么,我們有哪些對比方式呢?
方法一:MD5指紋對比 - 精確匹配
MD5 是一種信息摘要算法,可以將任意長度的數(shù)據(jù)映射為固定長度的字符串。對于圖片文件,我們可以將其計算出一個獨一無二的 MD5 值,就像一個數(shù)字指紋,可以用來精確比對兩個文件(不僅僅是圖片)是否完全相同。
下面是使用 Go 語言計算圖片 MD5 值的示例代碼:
package main import ( "crypto/md5" "fmt" "io" "os" ) // calculateMD5 計算文件的MD5值 // 為圖片頒發(fā)獨一無二的“身份證” func calculateMD5(filePath string) (string, error) { // 打開文件 file, err := os.Open(filePath) if err != nil { return "", fmt.Errorf("無法打開文件:%v", err) } defer file.Close() // 創(chuàng)建MD5哈希器 hash := md5.New() // 將文件內(nèi)容復制到哈希器中 if _, err := io.Copy(hash, file); err != nil { return "", fmt.Errorf("計算MD5時出錯:%v", err) } // 返回MD5字符串 return fmt.Sprintf("%x", hash.Sum(nil)), nil } func main() { // 比較兩張圖片 md51, err := calculateMD5("image1.jpg") if err != nil { fmt.Println("圖片1處理失敗:", err) return } md52, err := calculateMD5("image2.jpg") if err != nil { fmt.Println("圖片2處理失敗:", err) return } // 對比結(jié)果 if md51 == md52 { fmt.Println("圖片完全相同") } else { fmt.Println("圖片不同") } }
代碼解讀:
- 我們定義了一個
calculateMD5
函數(shù),傳入文件路徑,返回計算出的 MD5 字符串。 - 函數(shù)中先打開文件,創(chuàng)建一個 MD5 哈希器
hash
。 - 通過
io.Copy
將文件內(nèi)容寫入哈希器中,計算出 MD5 值。 - 最后將 MD5 字節(jié)數(shù)組格式化為字符串返回。
- 在
main
函數(shù)中,我們計算兩個圖片文件的 MD5 值,比對它們是否相等,輸出結(jié)果。
MD5 比對的特點:
- 速度快、計算簡單
- 可精確判斷兩個文件是否完全相同(只要是文件,都可以通過這種方式進行判斷是否一樣)
- 無法檢測內(nèi)容相似但不完全相同的圖片
- 圖片稍有改動(如添加水印)就會導致 MD5 值完全不同
所以 MD5 比對適合用于檢測完全相同的圖片,如文件去重等場景。如果兩張圖片只是稍作修改(如調(diào)整亮度、旋轉(zhuǎn)等),MD5 就無能為力了。
方法二:圖像哈希對比
圖像哈希(Image Hashing)是一類可以比較圖片相似程度的算法。其基本原理是:將圖片縮小、簡化為一個哈希值,然后比較不同圖片哈希值的差異度,來判斷它們的相似程度。
常見的圖像哈希算法有:
- 平均哈希(Average Hash)
- 感知哈希(Perceptual Hash)
- 差異哈希(Difference Hash)
- 小波哈希(Wavelet Hash)
這里我們以第三方包為例:
首先先安裝這個包
go get github.com/corona10/goimagehash
然后我們來嘗試實現(xiàn)一個圖片相似度比對:
package main import ( "fmt" "image/png" "os" "github.com/corona10/goimagehash" ) // compareImageSimilarity 比較圖片相似度 func compareImageSimilarity(image1Path, image2Path string) error { file1, err := os.Open(image1Path) if err != nil { return fmt.Errorf("打開圖片1失?。?v", err) } defer file1.Close() file2, err := os.Open(image2Path) if err != nil { return fmt.Errorf("打開圖片2失敗:%v", err) } defer file2.Close() // 加載圖片 img1, err := png.Decode(file1) if err != nil { return fmt.Errorf("加載圖片1失?。?v", err) } img2, err := png.Decode(file2) if err != nil { return fmt.Errorf("加載圖片2失?。?v", err) } // 生成平均哈希 avgHash1, err := goimagehash.AverageHash(img1) if err != nil { return fmt.Errorf("生成圖片1哈希失敗:%v", err) } avgHash2, err := goimagehash.AverageHash(img2) if err != nil { return fmt.Errorf("生成圖片2哈希失敗:%v", err) } // 計算差異哈希 diffHash1, err := goimagehash.DifferenceHash(img1) if err != nil { return fmt.Errorf("生成圖片1差異哈希失?。?v", err) } diffHash2, err := goimagehash.DifferenceHash(img2) if err != nil { return fmt.Errorf("生成圖片2差異哈希失敗:%v", err) } // 計算漢明距離 avgDistance, err := avgHash1.Distance(avgHash2) if err != nil { return fmt.Errorf("計算平均哈希距離失?。?v", err) } diffDistance, err := diffHash1.Distance(diffHash2) if err != nil { return fmt.Errorf("計算差異哈希距離失敗:%v", err) } // 打印相似度 fmt.Printf("平均哈希距離:%d\n", avgDistance) fmt.Printf("差異哈希距離:%d\n", diffDistance) // 判斷相似程度 if avgDistance == 0 && diffDistance == 0 { fmt.Println("兩張圖一樣") } else if avgDistance <= 5 || diffDistance <= 5 { fmt.Println("圖片高度相似") } else if avgDistance <= 10 || diffDistance <= 10 { fmt.Println("圖片相似") } else { fmt.Println("圖片差異較大") } return nil } func main() { err := compareImageSimilarity("img.png", "img_1.png") if err != nil { fmt.Println("圖片對比出錯:", err) } }
圖像哈希的特點:
- 可以比較圖片內(nèi)容的相似程度
- 對圖片的縮放、旋轉(zhuǎn)、亮度變化等稍微魯棒
- 計算難度適中,可應用于相似圖片搜索等場景
- 仍無法識別完全不同但語義相似的圖片(比如同一物體不同角度的照片)
它們各有特點和適用場景:
MD5指紋:簡單快速,適合精確匹配完全相同的圖片。 圖像哈希:可以比較圖片的相似程度,在相似圖片搜索等場景下很有用。
當然,這只是圖像相似度算法的冰山一角。在實際應用中,我們還需要考慮性能、精度、復雜度等因素,選擇最適合的方案。
圖像識別領(lǐng)域在不斷發(fā)展,一些前沿技術(shù)如機器學習、深度神經(jīng)網(wǎng)絡等,為圖片相似度判斷帶來了更多的可能性,值得我們?nèi)W習和探索。
到此這篇關(guān)于Go語言如何判斷兩張圖片的相似度的文章就介紹到這了,更多相關(guān)Go判斷圖片相似度內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Go語言k8s?kubernetes使用leader?election實現(xiàn)選舉
這篇文章主要為大家介紹了Go語言?k8s?kubernetes?使用leader?election選舉,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-10-10golang使用iconv報undefined:XXX的問題處理方案
這篇文章主要介紹了golang使用iconv報undefined:XXX的問題處理方案,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-03-03Go語言標準庫sync.Once使用場景及性能優(yōu)化詳解
這篇文章主要為大家介紹了Go語言標準庫sync.Once使用場景及性能優(yōu)化詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-12-12