Atitit 判斷判斷一張圖片是否包含另一張小圖片
1. keyword1
2. 模板匹配是在圖像中尋找目標的方法之一(切割+圖像相似度計算)1
3. 匹配效果2
4. 圖片相似度的算法(感知哈希算法”(Perceptual hash algorithm)2
5. 性能結果2
6. 如何提升性能3
6.1. 可以采用簡化的算法。二次匹配法,先大概確定區域3
6.2. 切割圖片設置一個step3
7. 參考資料3
8. ------code3
圖像匹配
圖片是否另外一張圖片的一部分
如果是標准圖片,模板匹配就好
。Come On, Boy.我們一起來看看模板匹配到底是怎麼回事。
模板匹配的工作方式
模板匹配的工作方式跟直方圖的反向投影基本一樣,大致過程是這樣的:通過在輸入圖像上滑動圖像塊對實際的圖像塊和輸入圖像進行匹配。
假設我們有一張100x100的輸入圖像,有一張10x10的模板圖像,查找的過程是這樣的:
(1)從輸入圖像的左上角(0,0)開始,切割一塊(0,0)至(10,10)的臨時圖像;
(2)用臨時圖像和模板圖像進行對比,對比結果記為c;
(3)對比結果c,就是結果圖像(0,0)處的像素值;
(4)切割輸入圖像從(0,1)至(10,11)的臨時圖像,對比,並記錄到結果圖像;
(5)重復(1)~(4)步直到輸入圖像的右下角。
大家可以看到,直方圖反向投影對比的是直方圖,而模板匹配對比的是圖像的像素值;模板匹配比直方圖反向投影速度要快一些,但是我個人認為直方圖反向投影的魯棒性會更好。
效果不錯,基本可以確定查找到對應的區域坐標。。對於彩色圖片,可以使用色彩空間信息排除掉其他錯誤的匹配圖片,幾乎可以精確的確定一個圖片了。。
感知哈希算法”(Perceptual hash algorithm),它的作用是對每張圖片生成一個“指紋”(fingerprint)字符串,然後比較不同圖片的指紋。結果越接近,就說明圖片越相似。
下面是一個最簡單的實現:
第一步,縮小尺寸。將圖片縮小到8×8的尺寸,總共64個像素。這一步的作用是去除圖片的細節,只保留結構、明暗等基本信息,摒棄不同尺寸、比例帶來的圖片差異。
第二步,簡化色彩。將縮小後的圖片,轉為64級灰度。也就是說,所有像素點總共只有64種顏色。
第三步,計算平均值。計算所有64個像素的灰度平均值。
第四步,比較像素的灰度。將每個像素的灰度,與平均值進行比較。大於或等於平均值,記為1;小於平均值,記為。
第五步,計算哈希值。將上一步的比較結果,組合在一起,就構成了一個64位的整數,這就是這張圖片的指紋。組合的次序並不重要,只要保證所有圖片都采用同樣次序就行了。
得到指紋以後,就可以對比不同的圖片,看看64位中有多少位是不一樣的。在理論上,這等同於計算“漢明距離”。如果不相同的數據位不超過5,就說明兩張圖片很相似;如果大於10,就說明這是兩張不同的圖片。
在我機子上,語言java ,純java實現。匹配變換dct算法size 8
每次移動step=5 。。使用了並行庫。。
速度大概在120s。。懶得繼續調整性能了,主要是測試思路,不過總結了思路,暫時先用著,理想的目標應該在3秒內。。
這個是參考文章的說法大概70秒。。語言是c#調用opencv接口
模板匹配和直方圖反向投影的效率
總的來說,模板匹配和直方圖反向投影的效率都不高。在我的機器上,在1136*852大小的輸入圖像上匹配104*132的大小的模板圖像(都是單通道灰度圖像),大約需要700毫秒;而直方圖反向投影大約需要75000毫秒(1.25分鐘)。看來還需要繼續學習,尋找更好的處理方法
主要算法消耗在匹配小圖片上。。
。首先可以大幅度的就確定幾張疑似圖像坐標。。然後對疑似圖像進行高精度算法匹配,就可以幾乎匹配到唯一的一張。。如果圖片是彩色圖片,再使用顏色信息二次匹配相似度。。以及直方圖等算法補充來匹配。。
比如要尋找的圖片大小60*60,可以設置一個20%以內的不敬step來跳躍切割,可以大幅度提升性能, 60/0.05=12.。 可以立馬提升12倍的性能。。
然後大概選定了區域後,在使用精確移動step來切割圖片。
如何判斷一張圖片是否包含另一張小圖片?圖像匹配?-CSDN論壇-CSDN.NET-中國最大的IT技術社區.html
模板匹配(Match Template) - Wuya - 博客園.html
算法 - JPEG的DCT壓縮原理,誰能通俗易懂解釋一下? - SegmentFault.html
作者:: 綽號:老哇的爪子 ( 全名::Attilax Akbar Al Rapanui 阿提拉克斯 阿克巴 阿爾 拉帕努伊 )
漢字名:艾提拉(艾龍), EMAIL:[email protected]
轉載請注明來源: http://www.cnblogs.com/attilax/
private void t() throws IOException {
String big = "c:\\t.jpeg";
String lit = "c:\\lit.jpg";
// diff==484
BufferedImage lit_img = ImageIO.read(new File(lit));
int w2 = lit_img.getWidth();
int h2 = lit_img.getHeight();
imgx imgx = new imgx();
BufferedImage img = ImageIO.read(new File(big));
int width = img.getWidth();
int h = img.getHeight();
ImagePHash imagePHash = new ImagePHash(8, 8);
ImageReader ImageReader1 = imgx.ImgReader(new File(big));
String ext = filex.getExtName(big);
imgx.save(lit_img, "c:\\0tmpPic\\" + filex.getUUidName() + "." + ext, ext);
ExecutorService es=Executors.newFixedThreadPool(3);
lab: for (int i = 0; i < width; i = i + 5) {
for (int j = 0; j < h; j = j + 5) {
// BufferedImage tmp =
// (BufferedImage) imgx.cutImage_retImg(big,
// i, j, w2, h2);
n++;
int x = i;
int y = j;
int nowCount=n;
Runnable ra = () -> {
process(lit_img, w2, h2, imgx, imagePHash, ImageReader1, nowCount,
ext, x, y);
};
es.execute(ra);
}
}
es.shutdown();
}
private int process(BufferedImage lit_img, int w2, int h2, imgx imgx,
ImagePHash imagePHash, ImageReader ImageReader1, int n, String ext,
int i, int j) {
Rectangle rect = new java.awt.Rectangle(i, j, w2, h2);
BufferedImage tmp = imgx.cutImg(rect, ImageReader1);
int dis = imagePHash.distance(tmp, lit_img);
if (dis < 5) {
log.info(" count:" + String.valueOf(n) + " dis:"
+ String.valueOf(dis) + " rect:" + String.valueOf(i) + "_"
+ String.valueOf(j));
// break lab;
}
if (dis < 10) {
String out = "c:\\0tmpPic\\" + filex.getUUidName() + "." + ext;
imgx.save(tmp, out, ext);
log.info(" count:" + String.valueOf(n) + " dis:"
+ String.valueOf(dis) + " rect:" + String.valueOf(i) + "_"
+ String.valueOf(j) + " file:" + out);
}
int cnt = n;
if (cnt % 100 == 0) {
String count = String.valueOf(cnt);
log.info(" count:" + count + " dis:" + String.valueOf(dis)
+ " rect:" + String.valueOf(i) + "_" + String.valueOf(j));
}
return n;
}
}
Atiend