国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 學(xué)院 > 開(kāi)發(fā)設(shè)計(jì) > 正文

圖像指紋的重復(fù)識(shí)別

2019-11-14 17:14:12
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

在google上面搜索圖像識(shí)別的時(shí)候,搜到一篇好文章,在這里翻譯一下,所有版權(quán)來(lái)源于https://realpython.com/blog/python/fingerPRinting-images-for-near-duplicate-detection/,作者源代碼:https://github.com/realpython/image-fingerprinting/blob/master/code/output.csv雖然英語(yǔ)過(guò)了六級(jí),但是仍然有很多專(zhuān)業(yè)術(shù)語(yǔ)不懂,翻譯水平也只能是湊合而已。

注:本文寫(xiě)作的目的是這篇文章的作者發(fā)現(xiàn)建立網(wǎng)站的時(shí)候,很多用戶(hù)用相同的頭像,這導(dǎo)致識(shí)別度降低,為了防止用戶(hù)上傳相同的圖片作為自己的頭像以及上傳不當(dāng)?shù)膱D像文件,作者研究了這個(gè)圖像指紋的問(wèn)題。(等我翻譯完成竟然發(fā)現(xiàn)網(wǎng)上已經(jīng)有人翻譯好了http://python.jobbole.com/81277/,自愧不如)

不妨想一想,每一個(gè)人都有屬于他自己的指紋一樣,指紋能夠識(shí)別人,那么圖片的指紋也可以用來(lái)識(shí)別圖片。

現(xiàn)在用三個(gè)階段來(lái)實(shí)現(xiàn)算法:

  1.將一組不合適的圖像指紋計(jì)算出來(lái),然后將這些圖像指紋存入數(shù)據(jù)庫(kù)中。

  2.當(dāng)用戶(hù)上傳一個(gè)新的客戶(hù)資料中的頭像時(shí),我們將會(huì)將其與數(shù)據(jù)庫(kù)中的圖像指紋進(jìn)行對(duì)比。如果發(fā)現(xiàn)數(shù)據(jù)庫(kù)中任意一個(gè)頭像指紋與該用戶(hù)上傳的圖像符合,管理員將會(huì)阻止用戶(hù)上傳該圖像作為自己的頭像。 

  3.依次類(lèi)推,識(shí)別出色情圖片,根據(jù)色情圖片的指紋創(chuàng)建一個(gè)收集色情圖片指紋的數(shù)據(jù)庫(kù),用來(lái)防止用戶(hù)上傳色情圖片。

我們的程序并不是完美的,有效的。即使效率緩慢但是目的終究是達(dá)到了,雖然沒(méi)有完全的解決問(wèn)題,但是減少了用戶(hù)上傳的80%以上的不當(dāng)文件。

那么接下來(lái)最大的問(wèn)題是如何創(chuàng)建圖像指紋?

請(qǐng)繼續(xù)閱讀并找出答案。。。

我們接下來(lái)需要做什么?

我們將利用圖像指紋進(jìn)行重復(fù)識(shí)別,一般稱(chēng)這種技術(shù)為“圖像感知哈希法”或者“圖像哈希法”。

什么是圖像指紋或者說(shuō)什么是圖像哈希?

圖像哈希的過(guò)程是通過(guò)檢測(cè)圖像的內(nèi)容,然后構(gòu)造一個(gè)值,該值在這些圖像內(nèi)容的基礎(chǔ)上唯一的標(biāo)志這個(gè)圖像

如下圖所示:

在給定的輸入的圖像中, 我們將使用一個(gè)散列函數(shù),并基于圖像視覺(jué)上的外觀計(jì)算它的“圖像散列”值,相似的頭像,它的散列值應(yīng)該也是相似的。使用圖像哈希算法可以大大簡(jiǎn)化重復(fù)圖像檢測(cè)的程序。

在這里,我們將使用“difference hash”,或者僅僅使用dHash算法來(lái)計(jì)算我們的圖像指紋。簡(jiǎn)單來(lái)說(shuō),dHash著力探究相鄰像素之間的區(qū)別。哈希值是在這個(gè)基礎(chǔ)上被創(chuàng)建出來(lái)的。

為什么我們不直接使用md5,sha-1等等算法?

不幸的是,我們不能在本例中使用加密散列算法。這是由于加密散列算法本身的性質(zhì)——輸入文件中非常微小的變化都會(huì)造成顯著不同的哈希值。在本次圖像指紋的案例中,是希望類(lèi)似圖片的輸入能得到類(lèi)似哈希值的輸出。

圖像指紋能應(yīng)用在哪些領(lǐng)域?

就如同上面的例子,你可以用圖像指紋來(lái)管理你的不合適的圖像數(shù)據(jù)庫(kù),當(dāng)用戶(hù)嘗試上傳此類(lèi)圖像的時(shí)候你可以提醒他們。

你可以建立一個(gè)類(lèi)似于TinEye的搜索引擎,用來(lái)跟蹤圖片,并且找出類(lèi)似圖片出現(xiàn)的網(wǎng)頁(yè)。

你甚至可以通過(guò)使用圖像指紋識(shí)別來(lái)管理你的個(gè)人相集。想象一下,你有一個(gè)存儲(chǔ)你個(gè)人圖片的硬盤(pán),但是需要一種方法備份部分修剪的圖片,并能夠保持唯一的副本——圖像指紋可以幫你做到。

簡(jiǎn)單來(lái)說(shuō),你可以在任何與圖像重復(fù)副本檢測(cè)的地方使用圖像指紋或者圖像散列方法。

我們需要哪些庫(kù)?

為了制作我們的圖像指紋識(shí)別方案,將會(huì)用的以下三個(gè)python庫(kù):

  • PIL/Pillow用來(lái)讀取或者加載圖像
  • ImageHash,其中包含dHash算法的實(shí)現(xiàn)
  • 以及Numpy/Scipy,計(jì)算圖像散列

你也可以通過(guò)如下命令搭建所有環(huán)境(python2.7):

$ pip install pillow imagehash

第一步:創(chuàng)建圖像指紋數(shù)據(jù)集

我們并不打算使用我日常在約會(huì)網(wǎng)站上遇到的色情圖片,我已經(jīng)找到了一個(gè)我們可以使用的數(shù)據(jù)集。

對(duì)于計(jì)算機(jī)視覺(jué)研究人員來(lái)講,CALTECH-101數(shù)據(jù)集是個(gè)傳奇。它包含7500+張來(lái)自101個(gè)目錄的圖片,包括人、摩托車(chē)和飛機(jī)。

我從這7500張圖片中隨機(jī)抽取了17張。

然后從這17張隨機(jī)抽選的圖片中,我通過(guò)隨機(jī)調(diào)整圖片的尺寸創(chuàng)建了N個(gè)新的圖像。我們的目標(biāo)是找到這些近乎重復(fù)的圖像,這就像是大海撈針。

并且,由于圖片除了寬高尺寸外都是相同的,由于他們都沒(méi)有相同的尺寸,我們不能簡(jiǎn)單的使用MD5校驗(yàn),更重要的是內(nèi)容類(lèi)似的圖片可能具有顯著不同的哈希值,原因已解釋?zhuān)喾?,我們可以使用圖像散列,因?yàn)轭?lèi)似的圖片擁有相似的哈希指紋。

那么現(xiàn)在開(kāi)始編寫(xiě)關(guān)于數(shù)據(jù)集的代碼,并將其命名為index.py:

 

 1 # coding=utf-8 2 # 導(dǎo)入必要的包 3 import argparse 4 import shelve
import imagehash
5 import glob 6 from PIL import Image 7 8 # 構(gòu)建參數(shù)解析,并分析參數(shù) 9 ap = argparse.ArgumentParser()10 ap.add_argument("-d", "--dataset", required=True,11 help="照片數(shù)據(jù)集的路徑")12 ap.add_argument("-s", "--shelve",required=True,13 help="shelve數(shù)據(jù)集的輸出")14 args = vars(ap.parse_args())15 16 # 打開(kāi)shelve數(shù)據(jù)集17 db = shelve.open(args["shelve"], writeback=True)

 

首先,我們要做的就是導(dǎo)入我們需要的包。我們將使用PIL或者Pillow模塊中的Image類(lèi)從磁盤(pán)中加載圖片。然后用圖像指紋庫(kù)來(lái)構(gòu)建感性序列。

根據(jù)上面的代碼可知,argparse用于解析命令行參數(shù),shelve用來(lái)做python的子典型數(shù)據(jù)庫(kù),并將其存儲(chǔ)在磁盤(pán)上,glob將用來(lái)更加輕易的收集圖片的路徑位置。

接著,分析命令行參數(shù)。第一,--dataset是我們輸入圖像的路徑目錄。第二,--shelve是通往shelve數(shù)據(jù)庫(kù)的輸出路徑。

接下來(lái),我們打開(kāi)shelve數(shù)據(jù)庫(kù)并對(duì)其進(jìn)行寫(xiě)入。db將會(huì)存儲(chǔ)我們的圖像哈希值。代碼如下:

 

 1 # 在圖像數(shù)據(jù)集中循環(huán) 2 for imagePath in glob.glob(args["dataset"] + "/*.jpg"): 3     # 加載圖片并計(jì)算哈希值的差異 4     image = Image.open(imagePath) 5     h = str(imagehash.dhash(image)) 6  7     # 提取路徑中的文件名并更新數(shù)據(jù)庫(kù) 8     # 用散列作為字典的鍵,文件名添加到值列表 9     filename = imagePath[imagePath.rfind("/") + 1:]10     db[h] = db.get(h, []) + [filename]11 12 # 關(guān)閉shelf數(shù)據(jù)集13 db.close()

這些就是我們大致需要的代碼工作了,從磁盤(pán)中加載圖像,并遍歷圖像數(shù)據(jù)集,然后創(chuàng)建圖像指紋。

現(xiàn)在我們觀察以下整個(gè)教程中最重要的兩條代碼:

1 filename = imagePath[imagePath.rfind("/") + 1:]2 db[h] = db.get(h, []) + [filename]

就像我一開(kāi)始在文章中提到的一樣,具有相同指紋的圖像被認(rèn)為是同樣的圖像。

因此,如果我們的目標(biāo)是找出相似圖片,我們需要?jiǎng)?chuàng)建一個(gè)擁有相同指紋值的圖像列表。

以上兩行代碼做的就是這個(gè)工作。

第一行提取圖像的文件名,第二行給圖像創(chuàng)建一個(gè)擁有相同哈希值的列表。

從數(shù)據(jù)庫(kù)中提取圖像指紋并創(chuàng)建我們的散列數(shù)據(jù)庫(kù),使用如下命令:

$ python index.py —dataset images —shelve db.shelve

該腳本將會(huì)運(yùn)行幾秒鐘,一旦完成就好產(chǎn)生一個(gè)文件,里面包含了圖像指紋—文件名對(duì)應(yīng)的鍵值對(duì)。

這個(gè)算法和我?guī)啄昵霸趧?chuàng)建約會(huì)網(wǎng)站時(shí)寫(xiě)的算法一樣,我們將不適合的圖片收集起來(lái),并計(jì)算他們的散列值,存入數(shù)據(jù)庫(kù)。當(dāng)用戶(hù)提交圖像的時(shí)候,我只有計(jì)算圖像的指紋,并將其與數(shù)據(jù)庫(kù)中的指紋進(jìn)行對(duì)比,用來(lái)判斷是否上傳被判無(wú)效的內(nèi)容。

下一步我將會(huì)告訴你如何執(zhí)行搜索,以確定圖片是否在數(shù)據(jù)庫(kù)中有類(lèi)似的散列值的圖像。

第二步:搜索數(shù)據(jù)庫(kù)

既然我們已經(jīng)創(chuàng)建了一個(gè)指紋圖像數(shù)據(jù)庫(kù),是時(shí)候來(lái)搜索數(shù)據(jù)庫(kù)了。

打開(kāi)一個(gè)名字為search.py的新文件,開(kāi)始編寫(xiě)代碼:

 

 1 # coding=utf-8 2 # 導(dǎo)入必要的包 3 from PIL import Image 4 import imagehash 5 import argparse 6 import shelve 7  8 # 構(gòu)建參數(shù)解析,并分析參數(shù) 9 ap = argparse.ArgumentParser()10 ap.add_argument("-d", "--dataset", required=True,11                 help="照片數(shù)據(jù)集的路徑")12 ap.add_argument("-s", "--shelve",required=True,13                 help="shelve數(shù)據(jù)集的輸出")14 ap.add_argument("-q", "--query", required=True,15                 help="搜索圖像的路徑")16 args = vars(ap.parse_args())

 

像上次一樣,導(dǎo)入我們需要的包,然后解析命令行參數(shù)。接下來(lái)需要三次轉(zhuǎn)換,--dataset,它是原始圖片數(shù)據(jù)集的路徑,--shelve,存放鍵值對(duì)的數(shù)據(jù)庫(kù),以及--query,搜索或者上傳圖片的路徑。我們的目標(biāo)是根據(jù)上傳的圖片對(duì)數(shù)據(jù)庫(kù)進(jìn)行搜索類(lèi)似哈希值的圖片。

接下來(lái),寫(xiě)關(guān)于執(zhí)行搜索的代碼:

 1 # 打開(kāi)shelf數(shù)據(jù)集 2 db = shelve.open(args["shelf"]) 3  4 # 加載需要查詢(xún)的圖片,計(jì)算它的圖像差分散列值,并從數(shù)據(jù)庫(kù)中抓取類(lèi)似散列值得圖像 5 query = Image.open(args["query"]) 6 h = str(imagehash.dhash(query)) 7 filenames = db[h] 8 print("Found %d images" % (len(filenames))) 9 10 # 在圖像內(nèi)部循環(huán)11 for filename in filenames:12     image = Image.open(args["dataset"] + "/" + filename)13     image.show()14     15 # 關(guān)閉數(shù)據(jù)集16 db.close()

我們先打開(kāi)數(shù)據(jù)庫(kù),并從磁盤(pán)中加載圖片,計(jì)算圖像指紋,找出擁有相同指紋值得所有圖片。

如果存在任何相同哈希值的圖片,將會(huì)在圖片中循環(huán),依次展示這些圖片。

使用這些代碼,我們將會(huì)判斷是否上傳的圖片已經(jīng)存在于數(shù)據(jù)庫(kù)中。

結(jié)果

正如我在文章前段部分提到的,我已經(jīng)從CALTECH-101數(shù)據(jù)集中隨機(jī)采集了17張圖片,并通過(guò)一些小的尺寸上面的改動(dòng)創(chuàng)建了N張新圖片。

這些圖片的尺寸造成只有小部分的像素不同,因此不能使用MD5哈希算法(這一點(diǎn)將會(huì)在算法改進(jìn)中繼續(xù)探討)。想法我們需要利用圖像散列找到類(lèi)似的圖像。

打開(kāi)終端,并執(zhí)行以下命令:

$ python search.py —dataset images —shelve db.shelve —query images/84eba74d-38ae-4bf6-b8bd-79ffa1dad23a.jpg

 

如果不報(bào)錯(cuò)的話(huà)將會(huì)出現(xiàn)以下結(jié)果:

第一個(gè)結(jié)果

上面圖片的左邊就是輸入的圖像,我們將用這張圖片對(duì)數(shù)據(jù)集進(jìn)行搜索,找出擁有相同指紋的所有圖像。

值得肯定的是,在我們的數(shù)據(jù)集中有兩張圖片具有相同的指紋,如圖像右邊的兩張圖片所示。雖然從截圖上面查看并不很明顯,但是他們確實(shí)是具有相同內(nèi)容的不同尺寸的圖片。

讓我們嘗試輸入另外一張圖片:

$ python search.py —dataset images —shelve db.shelve —query images/9d355a22-3d59-465e-ad14-138a4e3880bc.jpg

結(jié)果如下:

第二次結(jié)果

perfect!

改進(jìn)算法

有很多方法可以改進(jìn)我們的算法,但是最重要的一種方法時(shí)考慮到散列是相似的并不是完全一樣的。

比如說(shuō),我們這次提交的圖片都是在尺寸上(向上或向下)調(diào)整了幾個(gè)百分點(diǎn)的大小,如果圖像調(diào)整比較大的話(huà),導(dǎo)致縱橫比改變,散列值將不會(huì)完全相同。

但是圖片將是類(lèi)似的。

為了找出相似并不相同的圖片,我們需要進(jìn)一步用到Hamming距離法。Hamming距離法可以計(jì)算出不同哈希值的像素位數(shù)。因此,兩個(gè)具有一位像素相差的圖像基本上比10位相差的的圖新更相似。

但是我們遇到第二個(gè)問(wèn)題,算法的擴(kuò)展性。

試想一下,有一張被輸入的圖像,并需要找到數(shù)據(jù)庫(kù)中所有類(lèi)似的圖像。那么我們可以計(jì)算輸入圖像和每一個(gè)數(shù)據(jù)庫(kù)圖像的Hamming距離。

隨著數(shù)據(jù)集的增大,將會(huì)導(dǎo)致更多的時(shí)間比較所有的哈希值。最后,我們的散列數(shù)據(jù)庫(kù)將會(huì)到達(dá)一定的規(guī)模以至于單純的線(xiàn)性比較是不實(shí)際的。

有一個(gè)解決方案就是,使用Kd樹(shù)分類(lèi)法或者VP樹(shù)分類(lèi),從線(xiàn)性搜索變成亞線(xiàn)性,減少搜索問(wèn)題的復(fù)雜性。

總結(jié)

在這篇文章中,我們學(xué)會(huì)了如何構(gòu)建和利用圖像散列法執(zhí)行近似圖像的檢測(cè)。圖像散列應(yīng)用在圖像視覺(jué)內(nèi)容研究中。

正如指紋可以識(shí)別人一樣,一個(gè)圖像的哈希值也可以唯一的標(biāo)志圖像。

使用我們的質(zhì)問(wèn)圖像知識(shí),再建立一個(gè)查找類(lèi)似圖像的系統(tǒng)無(wú)非是用的圖像的哈希算法。

編后語(yǔ)

ok,這就是昨天晚上和今天上午所翻譯的東西了,翻譯這篇博客讓我認(rèn)識(shí)到了自己語(yǔ)法的不足,例如數(shù)據(jù)庫(kù)的載入以及參數(shù)的解析的不熟悉等等。也使得我的心能夠在五一這種熱鬧的氣氛下安靜下來(lái)翻譯文章,分析算法,并從國(guó)際友人的字里行間感受他的熱情和思想,再次感謝作者。話(huà)說(shuō),今天用的流量出校器一直在燒流量,不知道是什么原因,畢竟昨天用的時(shí)候沒(méi)問(wèn)題,難道谷歌FQ需要消耗大量的流量?還是本身插件具有一定的吸附流量能力?估計(jì)最不可能的是我的電腦被人黑了吧,oh,my god!


發(fā)表評(píng)論 共有條評(píng)論
用戶(hù)名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 健康| 揭东县| 泾源县| 衡阳市| 安西县| 廉江市| 枣庄市| 永丰县| 景谷| 开阳县| 北安市| 泸西县| 仪征市| 合山市| 乌什县| 淮滨县| 寻甸| 满城县| 太原市| 汽车| 宁晋县| 大兴区| 新巴尔虎右旗| 杨浦区| 阿拉善右旗| 汾西县| 绍兴县| 左云县| 绥宁县| 蒙阴县| 瑞安市| 鄯善县| 延寿县| 色达县| 宜君县| 永春县| 莲花县| 普陀区| 乌鲁木齐市| 巨鹿县| 贵定县|