1. 程式人生 > >缺陷分析-基於NCC查詢兩幅影象中的不同點

缺陷分析-基於NCC查詢兩幅影象中的不同點

影象處理之積分圖應用三(基於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. 計算兩張影象每個畫素交叉乘積的積分圖程式碼如下:

  1. publicvoid caculateXYSum(byte[] x, byte[] y, int width, int height) {  
  2.     if(x.length != y.length)  
  3.         return;  
  4.     xysum = newfloat[width*height];  
  5.     this.width = width;  
  6.     this.height = height;  
  7.     // rows
  8.     int px = 0, py = 0;  
  9.     int offset = 0, uprow=0, leftcol=0;  
  10.     float sp2=0, sp3=0, sp4=0;  
  11.     for(int row=0; row<height; row++ ) {  
  12.         offset = row*width;  
  13.         uprow = row-1;  
  14.         for(int col=0; col<width; col++) {  
  15.             leftcol=col-1;  
  16.             px=x[offset]&0xff;  
  17.             py=y[offset]&0xff;  
  18.             int p1 = px*py;  
  19.             // 計算平方查詢表
  20.             sp2=(leftcol<0) ? 0:xysum[offset-1]; // p(x-1, y)
  21.             sp3=(uprow<0) ? 0:xysum[offset-width]; // p(x, y-1);
  22.             sp4=(uprow<0||leftcol<0) ? 0:xysum[offset-width-1]; // p(x-1, y-1);
  23.             xysum[offset]=p1+sp2+sp3-sp4;  
  24.             offset++;  
  25.         }  
  26.     }  
  27. }  
獲取任意視窗大小的交叉乘積的程式碼如下:
  1. publicfloat getXYBlockSum(int x, int y, int m, int n) {  
  2.     int swx = x + n/2;  
  3.     int swy = y + m/2;  
  4.     int nex = x-n/2-1;  
  5.     int ney = y-m/2-1;  
  6.     float sum1, sum2, sum3, sum4;  
  7.     if(swx >= width) {  
  8.         swx = width - 1;  
  9.     }  
  10.     if(swy >= height) {  
  11.         swy = height - 1;  
  12.     }  
  13.     if(nex < 0) {  
  14.         nex = 0;  
  15.     }  
  16.     if(ney < 0) {  
  17.         ney = 0;  
  18.     }  
  19.     sum1 = xysum[ney*width+nex];  
  20.     sum4 = xysum[swy*width+swx];  
  21.     sum2 = xysum[swy*width+nex];  
  22.     sum3 = xysum[ney*width+swx];  
  23.     return ((sum1 + sum4) - sum2 - sum3);  
  24. }  
其餘部分的積分圖計算,參見本人部落格《影象處理之積分圖演算法》
2. 預計算建立積分圖索引的程式碼如下:
  1. // per-calculate integral image for targetImage
  2. byte[] R = newbyte[width * height];  
  3. byte[] G = newbyte[width * height];  
  4. byte[] B = newbyte[width * height];  
  5. getRGB(width, height, pixels, R, G, B);  
  6. IntIntegralImage rii = new IntIntegralImage();  
  7. rii.setImage(R);  
  8. rii.process(width, height);  
  9. IntIntegralImage gii = new IntIntegralImage();  
  10. gii.setImage(G);  
  11. gii.process(width, height);  
  12. IntIntegralImage bii = new IntIntegralImage();  
  13. bii.setImage(B);  
  14. bii.process(width, height);  
  15. // setup the refer and target image index sum table
  16. rii.caculateXYSum(R, referRGB[0].getImage(), width, height);  
  17. gii.caculateXYSum(G, referRGB[1].getImage(), width, height);  
  18. bii.caculateXYSum(B, referRGB[2].getImage(), width, height);  
  19. int size = (xr * 2 + 1) * (yr * 2 + 1);  
3. 通過積分圖查詢實現快速NCC計算的程式碼如下:
  1. int r1=0, g1=0, b1=0;  
  2. int r2=0, g2=0, b2=0;  
  3. float sr1=0.0f, sg1=0.0f, sb1 = 0.0f;  
  4. float sr2=0.0f, sg2=0.0f, sb2 = 0.0f;  
  5. float xyr = 0.0f, xyg = 0.0f, xyb = 0.0f;  
  6. for (int row = yr; row < height - yr; row++) {  
  7.     for (int col = xr; col < width - xr; col++) {  
  8.         r1 = rii.getBlockSum(col, row, (yr * 2 + 1), (xr * 2 + 1));  
  9.         g1 = gii.getBlockSum(col, row, (yr * 2 + 1), (xr * 2 + 1));  
  10.         b1 = bii.getBlockSum(col, row, (yr * 2 + 1), (xr * 2 + 1));  
  11.         r2 = referRGB[0].getBlockSum(col, row, (yr * 2

    相關推薦

    缺陷分析-基於NCC查詢影象不同點

    影象處理之積分圖應用三(基於NCC快速相似度匹配演算法)基於Normalized cross correlation(NCC)用來比較兩幅影象的相似程度已經是一個常見的影象處理手段。在工業生產環節檢測、監控領域對物件檢測與識別均有應用。NCC演算法可以有效降低光照對影象比較結果的影響。而且NCC最終結果在0到

    opencv 影象直接相減

    關鍵函式cvAbsDiff() ,程式碼如下: #include "cv.h" #include "highgui.h" #include "cxcore.h" int main(int argc,char** argv) {cvNamedWindow("a",0);  

    [Tensorflow] 如何對影象做同樣的資料增廣操作

    在深度學習中,我們經常會對資料進行陣列增廣操作,比如說左右翻轉,增加noise等操作。 但是,現在我們的輸入是一組影象是一個sample,那我們需要對這一組影象進行同樣的資料增廣操作,也就是說同一個s

    用OpenCV疊加(融合)影象

    目標 在本例程中我們將要學習: l  什麼是線性融合並且為什麼它是有用的 l  用addWeighted函式疊加兩幅影象 理論依據 注:以下的解釋來自理查德﹒斯澤里斯基(Richard  Szeliski)Computer Vision:Algorithmand Appli

    matlab 影象配準

    兩幅影象配準。修改影象路徑之後,由於uiwait(msgbox('Click OK after closing the CPSELECT window.','Waiting...'));會有彈窗,先無視別關掉。接著再兩幅影象選定 成對對稱點,儲存工作空間再退出就可以了。

    latex並排插入影象

    下面是一些latex中並排兩圖的程式碼,以備今後使用 from:  http://blog.csdn.net/qq_22812319/article/details/51958958 \documentclass{article} \usepackage{graph

    【計算機視覺】opencv靶標相機姿態解算3 根據影象的位姿估計結果求某點的世界座標 (三維重建)

    關鍵詞:相機位姿估計,單目尺寸測量,環境探知 用途:基於相機的環境測量,SLAM,單目尺寸測量 文章型別:原理說明、Demo展示 @Author:VShawn @Date:2016-11-28 @Lab: [email protected] 前言 早就寫好了....不過doc放在膝

    使用SiftGPU對影象進行特徵點匹配

    前言 今天介紹繼續使用GLSL語言,在SiftGPU中對兩幅影象進行特徵點匹配方法,經本人驗證,在圖片解析度沒有那麼大的情況下,匹配速度會比Lowe演算法的快。 個人編譯環境:Windows 8.1,Visual Studio2010,OPENCV2.4.9 在你下載的S

    opencv學習(3)——addWeighted函式將影象疊加

    #include "opencv2/imgcodecs.hpp" #include "opencv2/highgui/highgui.hpp" #include <iostream> #include<stdlib.h> using na

    相機位姿估計3:根據影象的位姿估計結果求某點的世界座標_0

    關鍵詞:相機位姿估計,單目尺寸測量,環境探知 用途:基於相機的環境測量,SLAM,單目尺寸測量 文章型別:原理說明、Demo展示 @Author:VShawn @Date:2016-11-28 @Lab: [email protected] 目錄 《相機位姿估計

    OpenCV自帶例子(三)影象相加

    #include <cv.h> #include <highgui.h> #include <iostream> using namespace cv; int main( int argc, char** argv ) { doubl

    學習OpenCV範例(四)——使用OpenCV對影象求和(求混合(blending))

    這個範例相對來說比較簡單,簡單到在OpenCV的sample裡面都沒有提供原始碼,只能自己複製黏貼tutorial中的程式碼了,範例中介紹了線性混合操作的原理,和OpenCV提供的addWeighted()函式的用法,雖然簡單,但實現的功能還是挺有趣的,看看吧。 1、原理

    查詢張表關聯到的資料的和

    需要查詢出A和B表有 id 關聯欄位, 是一對多關係,需要在查詢中增加一列,查詢到A中的資料各關聯了B的多少份資料. 思路,使用group by 和 count 查詢出這些關聯資料的份數. 然後作為一箇中間表,再與A表進行 left join. select a.*, v.sealSum f

    setdiff:查詢個向量不同的元素 + 外則 去掉矩陣相同的東西

    轉自:http://blog.csdn.net/tina_lulu_21/article/details/6273646設有向量A和B,要求出A和B中的不同元素,可使用matlab自帶的setdiff函式。語法為:    c = setdiff(A, B)  其計算公式為c

    Sql使用SUM和UNION ALL 查詢張表指定欄位的和

    1、t_test1表           t_test2表       2、查詢需求:求t_test1.num與t_test2.amount之和   方法一: SELECT

    c語言查詢個字串的公共子串

    程式碼如下:#include <stdio.h> #include <string.h> #include <stdlib.h> void getCommon(ch

    Java學習 查詢個字串的最大子串

    public static String getMaxSubString(String str1,String str2) { String max = null,min = null; if(str1.length()>str2.length())     

    查詢個字串的相同的字元位置

    class Solution { public:     vector<int> findAnagrams(string s, string p) {      vector<int>ve1(256,0);            vector<int>ve2(256,0);

    基於svg.js可編輯影象的文字換行

        svg中的文字與一般頁面中的文字並不一樣,svg中的文字使用<text></text>標籤來包住文字,所以頁面中文字換行功能無法使用,這時候就要我們自己設定部分屬性來使其

    查詢張表某一對應欄位不相同的…

    功能:查詢A表中欄位v與B表中欄位m不重複的記錄並去除重複 sql語句: select distinct v from  A where not exists(select DISTINCT m from B where A.v=B.m) 表A: 表B: