Go語言如何判斷兩張圖片的相似度
在介紹技術細節(jié)前,我們先來看看圖片對比在哪些場景下可以用得到:
- 圖片去重:自動刪除重復圖片,為存儲空間"瘦身"。想象你是一個社交媒體平臺的運營,每天要處理數(shù)萬張圖片。重復圖片不僅占用存儲空間,還會影響用戶體驗。
- 內(nèi)容審核:一些平臺需要篩選相似或重復的內(nèi)容,防止版權侵犯和內(nèi)容垃圾。
- 版權維 權:檢測圖片有無被未經(jīng)授權使用的情況,比如,攝影師和設計師需要知道自己的作品是否被未經(jīng)授權使用。
- 相似圖片搜索:網(wǎng)盤、云存儲服務需要幫助用戶清理重復文件。
在這些場景中,圖片對比技術可以幫我們自動化處理大量圖片,提高工作效率。
但是,圖片對比可不像字符那樣可以直接使用等于號=直接對比,那么,我們有哪些對比方式呢?
方法一: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
}
// 對比結果
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 值,比對它們是否相等,輸出結果。
MD5 比對的特點:
- 速度快、計算簡單
- 可精確判斷兩個文件是否完全相同(只要是文件,都可以通過這種方式進行判斷是否一樣)
- 無法檢測內(nèi)容相似但不完全相同的圖片
- 圖片稍有改動(如添加水印)就會導致 MD5 值完全不同
所以 MD5 比對適合用于檢測完全相同的圖片,如文件去重等場景。如果兩張圖片只是稍作修改(如調(diào)整亮度、旋轉等),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)容的相似程度
- 對圖片的縮放、旋轉、亮度變化等稍微魯棒
- 計算難度適中,可應用于相似圖片搜索等場景
- 仍無法識別完全不同但語義相似的圖片(比如同一物體不同角度的照片)
它們各有特點和適用場景:
MD5指紋:簡單快速,適合精確匹配完全相同的圖片。 圖像哈希:可以比較圖片的相似程度,在相似圖片搜索等場景下很有用。
當然,這只是圖像相似度算法的冰山一角。在實際應用中,我們還需要考慮性能、精度、復雜度等因素,選擇最適合的方案。
圖像識別領域在不斷發(fā)展,一些前沿技術如機器學習、深度神經(jīng)網(wǎng)絡等,為圖片相似度判斷帶來了更多的可能性,值得我們?nèi)W習和探索。
到此這篇關于Go語言如何判斷兩張圖片的相似度的文章就介紹到這了,更多相關Go判斷圖片相似度內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Go語言k8s?kubernetes使用leader?election實現(xiàn)選舉
這篇文章主要為大家介紹了Go語言?k8s?kubernetes?使用leader?election選舉,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-10-10
golang使用iconv報undefined:XXX的問題處理方案
這篇文章主要介紹了golang使用iconv報undefined:XXX的問題處理方案,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-03-03
Go語言標準庫sync.Once使用場景及性能優(yōu)化詳解
這篇文章主要為大家介紹了Go語言標準庫sync.Once使用場景及性能優(yōu)化詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-12-12

