圖像處理之積分圖應用三(基于NCC快速相似度匹配算法)

from:https://blog.csdn.net/jia20003/article/details/53021614

圖像處理之積分圖應用三(基于NCC快速相似度匹配算法)

基于Normalized cross correlation(NCC)用來比較兩幅圖像的相似程度已經是一個常見的圖像處理手段。在工業生產環節檢測、監控領域對對象檢測與識別均有應用。NCC算法可以有效降低光照對圖像比較結果的影響。而且NCC最終結果在0到1之間,所以特別容易量化比較結果,只要給出一個閾值就可以判斷結果的好與壞。傳統的NCC比較方法比較耗時,雖然可以通過調整窗口大小和每次檢測的步長矩形部分優化,但是對工業生產檢測然后不能達到實時需求,通過積分圖像實現預計算,比較模板圖像與生產出電子版之間的細微差異,可以幫助企業提高產品質量,減少次品出廠率,把控質量。

一:NCC相關的數學知識

什么是NCC - (normalized cross correlation)歸一化的交叉相關性,是數學上統計兩組數據之間是否有關系的判斷方法,貌似搞大數據分析比較流行相關性分析和計算。正常的計算公式如下:

mxn表示窗口大小,這樣的計算復雜度就為O(m x n x M x N)。從上面公式就可以看出其中均值和平方和可以通過積分圖預計算得到,對于模板和目標圖像大小一致的應用場景來說

NCC的計算公式可以表示為如下:

其中根據積分圖像可以提前計算出任意窗口大小和與平方和,這樣就對

上述兩個計算實現了窗口半徑無關的常量時間計算,唯一缺少的是下面計算公式

通過積分圖像建立起來窗口下面的待檢測圖像與模板圖像的和與平方和以及他們的交叉乘積五個積分圖索引之后,這樣就完成了整個預計算生成。依靠索引表查找計算結果,NCC就可以實現線性時間的復雜度計算,而且時間消耗近似常量跟窗口半徑大小無關,完全可以滿足實時對象檢測工業環境工作條件。

?

二:算法步驟

1. 預計算模板圖像和目標圖像的積分圖

2. 根據輸入的窗口半徑大小使用積分圖完成NCC計算

3. 根據閾值得到匹配或者不匹配區域。

4. 輸出結果

為了減小計算量,我們可以要把輸入的圖像轉換為灰度圖像,在灰度圖像的基礎上完成整個NCC計算檢測。我們這個給出的基于RGB圖像的NCC計算完整代碼,讀者可以在此基礎上修改實現單通道圖像檢測。

三: 運行結果:

輸入的模板圖像與待檢測圖像,左邊是模板圖像,右邊是待檢測圖像,左上角有明顯污點。圖像顯示如下:

??

輸入待檢測圖像與模板比較以及檢測計算出NCC的圖像顯示如下:

其中左側是待檢測圖像,上面有黑色污點,右側輸出的非黑色區域表明,程序已經發現此區域與標準模板不同,越白的區域表示周圍跟模板相同位置反差越大,越是可疑的污染點,這樣就可以得到準確定位,最終帶檢測圖像繪制最可疑紅色矩形窗口區域

四:相關代碼實現

1. 計算兩張圖像每個像素交叉乘積的積分圖代碼如下:

	public void caculateXYSum(byte[] x, byte[] y, int width, int height) {if(x.length != y.length)return;xysum = new float[width*height];this.width = width;this.height = height;// rowsint px = 0, py = 0;int offset = 0, uprow=0, leftcol=0;float sp2=0, sp3=0, sp4=0;for(int row=0; row<height; row++ ) {offset = row*width;uprow = row-1;for(int col=0; col<width; col++) {leftcol=col-1;px=x[offset]&0xff;py=y[offset]&0xff;int p1 = px*py;// 計算平方查找表sp2=(leftcol<0) ? 0:xysum[offset-1]; // p(x-1, y)sp3=(uprow<0) ? 0:xysum[offset-width]; // p(x, y-1);sp4=(uprow<0||leftcol<0) ? 0:xysum[offset-width-1]; // p(x-1, y-1);xysum[offset]=p1+sp2+sp3-sp4;offset++;}}}
獲取任意窗口大小的交叉乘積的代碼如下:
	public float getXYBlockSum(int x, int y, int m, int n) {int swx = x + n/2;int swy = y + m/2;int nex = x-n/2-1;int ney = y-m/2-1;float sum1, sum2, sum3, sum4;if(swx >= width) {swx = width - 1;}if(swy >= height) {swy = height - 1;}if(nex < 0) {nex = 0;}if(ney < 0) {ney = 0;}sum1 = xysum[ney*width+nex];sum4 = xysum[swy*width+swx];sum2 = xysum[swy*width+nex];sum3 = xysum[ney*width+swx];return ((sum1 + sum4) - sum2 - sum3);}

?

其余部分的積分圖計算,參見本人博客《圖像處理之積分圖算法》
2. 預計算建立積分圖索引的代碼如下:

		// per-calculate integral image for targetImagebyte[] R = new byte[width * height];byte[] G = new byte[width * height];byte[] B = new byte[width * height];getRGB(width, height, pixels, R, G, B);IntIntegralImage rii = new IntIntegralImage();rii.setImage(R);rii.process(width, height);IntIntegralImage gii = new IntIntegralImage();gii.setImage(G);gii.process(width, height);IntIntegralImage bii = new IntIntegralImage();bii.setImage(B);bii.process(width, height);// setup the refer and target image index sum tablerii.caculateXYSum(R, referRGB[0].getImage(), width, height);gii.caculateXYSum(G, referRGB[1].getImage(), width, height);bii.caculateXYSum(B, referRGB[2].getImage(), width, height);int size = (xr * 2 + 1) * (yr * 2 + 1);

3. 通過積分圖查找實現快速NCC計算的代碼如下:

		int r1=0, g1=0, b1=0;int r2=0, g2=0, b2=0;float sr1=0.0f, sg1=0.0f, sb1 = 0.0f;float sr2=0.0f, sg2=0.0f, sb2 = 0.0f;float xyr = 0.0f, xyg = 0.0f, xyb = 0.0f;for (int row = yr; row < height - yr; row++) {for (int col = xr; col < width - xr; col++) {r1 = rii.getBlockSum(col, row, (yr * 2 + 1), (xr * 2 + 1));g1 = gii.getBlockSum(col, row, (yr * 2 + 1), (xr * 2 + 1));b1 = bii.getBlockSum(col, row, (yr * 2 + 1), (xr * 2 + 1));r2 = referRGB[0].getBlockSum(col, row, (yr * 2 + 1), (xr * 2 + 1));g2 = referRGB[1].getBlockSum(col, row, (yr * 2 + 1), (xr * 2 + 1));b2 = referRGB[2].getBlockSum(col, row, (yr * 2 + 1), (xr * 2 + 1));sr1 = rii.getBlockSquareSum(col, row, (yr * 2 + 1), (xr * 2 + 1));sg1 = gii.getBlockSquareSum(col, row, (yr * 2 + 1), (xr * 2 + 1));sb1 = bii.getBlockSquareSum(col, row, (yr * 2 + 1), (xr * 2 + 1));sr2 = referRGB[0].getBlockSquareSum(col, row, (yr * 2 + 1), (xr * 2 + 1));sg2 = referRGB[1].getBlockSquareSum(col, row, (yr * 2 + 1), (xr * 2 + 1));sb2 = referRGB[2].getBlockSquareSum(col, row, (yr * 2 + 1), (xr * 2 + 1));xyr = rii.getXYBlockSum(col, row, (yr * 2 + 1), (xr * 2 + 1));xyg = gii.getXYBlockSum(col, row, (yr * 2 + 1), (xr * 2 + 1));xyb = bii.getXYBlockSum(col, row, (yr * 2 + 1), (xr * 2 + 1));float nccr = calculateNCC(r1, r2, sr1, sr2, xyr, size);float nccg = calculateNCC(g1, g2, sg1, sg2, xyg, size);float nccb = calculateNCC(b1, b2, sb1, sb2, xyb, size);outPixels[row * width + col] = (nccr + nccg + nccb);}}System.out.println("time consum : " + (System.currentTimeMillis() - time));

4. 歸一化輸出NCC圖像與結果代碼如下:

		// normalization the datafloat max = 0.0f, min = 100.0f;for(int i=0; i<outPixels.length; i++) {max = Math.max(max, outPixels[i]);min = Math.min(min, outPixels[i]);}// create output image float delta = max - min;BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);int ry = -1;int rx = -1;for(int row = 0; row<height; row++) {for(int col=0; col<width; col++) {int gray = (int)(((outPixels[row*width+col]-min) / delta) *255);gray = 255 - gray;if(min == outPixels[row*width+col]) {bi.setRGB(col, row, Color.RED.getRGB());ry = row;rx = col;} else {int color = (0xff << 24) | (gray << 16) | (gray << 8) | gray;bi.setRGB(col, row, color);}}}if(rx > 0 && ry > 0) {Graphics2D g2d = image.createGraphics();g2d.setPaint(Color.RED);g2d.drawRect(rx-xr, ry-yr, xr*2, yr*2);}

相比傳統的NCC計算方法,此方法的計算效率是傳統方法幾百倍提升,而且窗口越大效率提升越明顯,有人對此作出的統計如下:

可見基于積分圖快速NCC可以極大提升執行效率減少計算時間,實現窗口半徑無關NCC比較。

最后

本文是關于積分圖使用的第三篇文章,可以說積分圖在實際圖像處理中應用十分廣泛,本人會繼續努力深挖與大家分享。希望各位頂下次文以表支持, 謝謝!本人堅持分享有用實用的圖像處理算法!需要大家多多支持。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/458148.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/458148.shtml
英文地址,請注明出處:http://en.pswp.cn/news/458148.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

深入淺出地理解機器人手眼標定

from&#xff1a;https://blog.csdn.net/qq_16481211/article/details/79764730 所謂手眼系統&#xff0c;就是人眼鏡看到一個東西的時候要讓手去抓取&#xff0c;就需要大腦知道眼鏡和手的坐標關系。如果把大腦比作B&#xff0c;把眼睛比作A&#xff0c;把手比作C,如果A和B的…

centos 6.5 安裝 mongodb

官方給出的鏈接地址&#xff1a;https://docs.mongodb.org/manual/tutorial/install-mongodb-on-red-hat/ 安裝后重要的日志 win10 上使用mongochef連接不上數據庫 解決方案&#xff1a; 修改 /etc/mongod.conf 將bindIP 改為0.0.0.0 監聽外網轉載于:https://www.cnblogs.com/l…

scala學習資料

1. scala-sbt 構建工具&#xff1a; http://www.scala-sbt.org/0.13/docs/zh-cn/Directories.html 2. 資料&#xff1a; http://www.ibm.com/developerworks/cn/java/j-lo-funinscala2/ https://www.zhihu.com/question/34548588?sortcreated http://nerd-is.in/2013-09/scala…

opencv3/C++ 機器學習-SVM應用實例:藥品(膠囊)識別與分類

from&#xff1a;https://blog.csdn.net/akadiao/article/details/79278072 版權聲明&#xff1a;本文為博主原創文章&#xff0c;未經博主允許不得轉載。 https://blog.csdn.net/akadiao/article/details/79278072 問題描述&#xff1a; 現對6種不同顏色藥品&#xff08;膠囊…

Elasticsearch 搜索不到數據問題(_mapping 設置)

需求 由于 kibana3 中&#xff0c;不支持直接在請求的 url 中設置搜索的 type &#xff08;是不是我不知道&#xff1f;&#xff1f;&#xff1f;&#xff09;。 為了支持特定 type 的搜索&#xff0c;所以我設置了個下每個 panel 的查詢語句&#xff0c;讓它增加一個&#xff…

SVM之交叉驗證【轉】

交叉驗證(CrossValidation)方法思想簡介 以下簡稱交叉驗證(Cross Validation)為CV.CV是用來驗證分類器的性能一種統計分析方法,基本思想是把在某種意義下將原始數據(dataset)進行分組,一部分做為訓練集(train set),另一部分做為驗證集(validation set),首先用訓練集對分類器進…

linux命令學習-1-less

less 工具也是對文件或其它輸出進行分頁顯示的工具&#xff0c;應該說是linux正統查看文件內容的工具&#xff0c;功能極其強大。less 的用法比起 more 更加的有彈性。在 more 的時候&#xff0c;我們并沒有辦法向前面翻&#xff0c; 只能往后面看&#xff0c;但若使用了 less …

python問題匯總

問題1&#xff1a;如何解決python3中numpy報錯No module named numpy 打開terminal pip3 install numpy 問題2&#xff1a;ModuleNotFoundError No module named matplotlib 打開terminal pip3 install matplotlib

jspspy database help

.轉載于:https://www.cnblogs.com/outline/p/5316051.html

SVM 調參策略

轉自&#xff1a;SVM 調參策略&#xff1a;https://blog.csdn.net/u014484783/article/details/78220646 SVM 怎樣能得到好的結果 1. 對數據做歸一化&#xff08;simple scaling&#xff09; 2. 應用 RBF kernel 3. 用cross-validation和grid-search 得到最優的c和g 4. 用…

美好的?天 從ActionTab開始 美觀、智能、?效的新標簽? iTab 新標簽頁iTab新標簽頁Atop100工具推薦

文章目錄 ActionTabiTab 新標簽頁iTab新標簽頁&#xff0c;小組件&#xff0c;起始頁&#xff0c;標簽頁&#xff0c;日歷&#xff0c;股票&#xff0c;瀏覽器擴展 https://www.actiontab.cn/ ActionTab 收費&#xff1f;&#xff1f;&#xff1f;&#xff1f; iTab 新標簽頁iT…

Oracle學習之merge

--使用merge語句 create table new as select * from emp where 10; insert into new (empno,ename) select empno,ename from emp where deptno10;merge into new n using emp e on (n.empnoe.empno) when matched then update set n.sale.salwhen not matched then insert (…

機器學習中的算法(2)-支持向量機(SVM)基礎

from:http://www.cnblogs.com/LeftNotEasy/archive/2011/05/18/2034566.html 版權聲明&#xff1a; 本文由LeftNotEasy發布于http://leftnoteasy.cnblogs.com, 本文可以被全部的轉載或者部分使用&#xff0c;但請注明出處&#xff0c;如果有問題&#xff0c;請聯系wheeleastgm…

HDU 2586 How far away ?【LCA】

題目鏈接&#xff1a; http://acm.hdu.edu.cn/showproblem.php?pid2586 題意&#xff1a; 無向圖&#xff0c;給定邊及邊權重&#xff0c;任意兩點之間都有一條唯一的道路&#xff0c;道路上每個點只能出現一次。給定詢問&#xff0c;求詢問的結點之間的距離。 分析&#xff1…

深入理解拉格朗日乘子法(Lagrange Multiplier) 和KKT條件

from:https://blog.csdn.net/xianlingmao/article/details/7919597 在求取有約束條件的優化問題時&#xff0c;拉格朗日乘子法&#xff08;Lagrange Multiplier) 和KKT條件是非常重要的兩個求取方法&#xff0c;對于等式約束的優化問題&#xff0c;可以應用拉格朗日乘子法去求…

android一些若干回調測試

1.activity&#xff1a;onAttachedToWindow在onResume后回調 2.onCreate和onResume調用間隔為29ms, onAttachedToWindow和OnResume相差11ms, viewTreeObserver:OnGloballayout和onAttachedtoWindow相差19ms 注:以上的測試時間間隔不能保證精確相同&#xff0c;但是可以從中看出…

Kinect深度圖與攝像頭RGB的標定與配準(轉載文章)

作者原文地址&#xff1a;http://blog.csdn.net/aichipmunk/article/details/9264703 自從有了Kinect&#xff0c;根據深度圖提取前景就非常方便了。因此出現了很多虛擬現實、視頻融合等應用。但是&#xff0c;Kinect自身的RGB攝像頭分辨率有限&#xff0c;清晰度也不及一些專業…

臺北到淡水版Firefox無法播放視頻

臺北到淡水版的Firefox所有的視頻都無法播放&#xff0c;禁用了各種插件也還是沒法播放&#xff0c;最后才確定是SWF的問題&#xff0c;大家有同樣問題的&#xff0c;可以下載我的放到SWF文件夾下&#xff0c;目錄結構如下圖&#xff1a; ?Firefox的SWF下載地址1 ?Firefox的S…

最詳細、最完整的相機標定講解

相機標定詳解 最近做項目要用到標定&#xff0c;因為是小白&#xff0c;很多東西都不懂&#xff0c;于是查了一堆的博客&#xff0c;但沒有一個博客能讓我完全能看明白整個過程&#xff0c;絕大多數都講的不全面&#xff0c;因此自己總結了一篇博客&#xff0c;給自己理一下思…

時間日志和缺陷日志

項目計劃總結&#xff1a; 日期&&任務 聽課 編寫程序 閱讀相關書籍 網上查找資料 日總計 周一 2 2 1 1 6 周二 2 1 3 周三 1 2 2 5 周四 2 2 1 5 周五 4 1 1 6 周六 3 1 1 4 周日 4 2 2 周總計 4 …