生活随笔
收集整理的這篇文章主要介紹了
图像处理之基于NCC模板匹配识别
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
圖像處理之基于NCC模板匹配識(shí)別
一:基本原理
NCC是一種基于統(tǒng)計(jì)學(xué)計(jì)算兩組樣本數(shù)據(jù)相關(guān)性的算法,其取值范圍為[-1, 1]之間,而對(duì)圖像來說,每個(gè)像素點(diǎn)都可以看出是RGB數(shù)值,這樣整幅圖像就可以看成是一個(gè)樣本數(shù)據(jù)的集合,如果它有一個(gè)子集與另外一個(gè)樣本數(shù)據(jù)相互匹配則它的ncc值為1,表示相關(guān)性很高,如果是-1則表示完全不相關(guān),基于這個(gè)原理,實(shí)現(xiàn)圖像基于模板匹配識(shí)別算法,其中第一步就是要?dú)w一化數(shù)據(jù),數(shù)學(xué)公式如下:
二:實(shí)現(xiàn)步驟
(1)??????獲取模板像素并計(jì)算均值與標(biāo)準(zhǔn)方差、像素與均值diff數(shù)據(jù)樣本
(2)??????根據(jù)模板大小,在目標(biāo)圖像上從左到右,從上到下移動(dòng)窗口,計(jì)
算每移動(dòng)一個(gè)像素之后窗口內(nèi)像素與模板像素的ncc值,與閾值比較,大于
閾值則記錄位置
(3)??????根據(jù)得到位置信息,使用紅色矩形標(biāo)記出模板匹配識(shí)別結(jié)果。
(4)??????UI顯示結(jié)果
?
三:編程實(shí)現(xiàn)
基于JAVA語言完成了整個(gè)算法編程實(shí)現(xiàn)與演示,其中第一步的代碼如下:
[java] view plaincopy
int?tw?=?template.getWidth();??int?th?=?template.getHeight();??int[]?tpixels?=?new?int[tw?*?th];??getRGB(template,?0,?0,?tw,?th,?tpixels);??for(int?i=0;?i<tpixels.length;?i++)??{??????tpixels[i]?=?(tpixels[i]?>>?16)?&?0xff;??}??double[]?meansdev?=?getPixelsMeansAndDev(tpixels);??double[]?tDiff?=?calculateDiff(tpixels,?meansdev[0]);??int?raidus_width?=?tw?/?2;??int?raidus_height?=?th?/?2;??
第二步的實(shí)現(xiàn)代碼如下:
[java] view plaincopy
int[]?windowPixels?=?new?int[tw?*?th];??Arrays.fill(windowPixels,?0);??for?(int?row?=?0;?row?<?height;?row++)?{??????for?(int?col?=?0;?col?<?width;?col++)?{????????????????????if(row?<??raidus_height?||?(row?+?raidus_height)?>=?height)??????????????continue;??????????if(col?<?raidus_width?||?(col?+?raidus_width)?>=?width)???????????????continue;??????????int?wrow?=?0;??????????Arrays.fill(windowPixels,?0);??????????for(int?subrow?=?-raidus_height;?subrow?<=?raidus_height;?subrow++?)??????????{??????????????int?wcol?=?0;??????????????for(int?subcol?=?-raidus_width;?subcol?<=?raidus_width;?subcol++?)??????????????{??????????????????if(wrow?>=?th?||?wcol?>=?tw)??????????????????{??????????????????????continue;??????????????????}??????????????????windowPixels[wrow?*?tw?+?wcol]?=?getPixelValue(width,?col?+?subcol,?row?+?subrow,?inPixels);??????????????????wcol++;??????????????}??????????????wrow++;??????????}????????????????????double[]?_meansDev?=?getPixelsMeansAndDev(windowPixels);??????????double[]?diff?=?calculateDiff(windowPixels,?_meansDev[0]);??????????double?ncc?=?calculateNcc(tDiff,?diff,?_meansDev[1],?meansdev[1]);??????????if(ncc?>?threhold)?{??????????????Point?mpoint?=?new?Point();??????????????mpoint.x?=?col;??????????????mpoint.y??=?row;??????????????points.add(mpoint);??????????}??????}??}??
第三步的實(shí)現(xiàn)代碼如下:
[java] view plaincopy
??setRGB(?dest,?0,?0,?width,?height,?inPixels?);??Graphics2D?g2d?=?dest.createGraphics();??g2d.setPaint(Color.RED);??g2d.setStroke(new?BasicStroke(4));??for(Point?p?:?points)??{??????g2d.drawRect(p.x?-?raidus_width,?p.y?-?raidus_height,?tw,?th);??}??
其中第二步用到的計(jì)算NCC的方法實(shí)現(xiàn)如下:
[java] view plaincopy
private?double?calculateNcc(double[]?tDiff,?double[]?diff,?double?dev1,?double?dev2)?{????????????double?sum?=?0.0d;??????double?count?=?diff.length;??????for(int?i=0;?i<diff.length;?i++)??????{??????????sum?+=?((tDiff[i]?*?diff[i])/(dev1?*?dev2));??????}??????return?(sum?/?count);??}??
UI部分完整源代碼如下:
[java] view plaincopy
package?com.gloomyfish.image.templae.match;????import?java.awt.BorderLayout;??import?java.awt.FlowLayout;??import?java.awt.Graphics;??import?java.awt.Graphics2D;??import?java.awt.event.ActionEvent;??import?java.awt.event.ActionListener;??import?java.awt.image.BufferedImage;??import?java.io.IOException;????import?javax.imageio.ImageIO;??import?javax.swing.JButton;??import?javax.swing.JComponent;??import?javax.swing.JFrame;??import?javax.swing.JPanel;????public?class?DemoUI?extends?JComponent?{????????????????????private?static?final?long?serialVersionUID?=?1L;??????private?BufferedImage?targetImage;??????private?BufferedImage?template;????????????public?DemoUI()??????{??????????super();??????????java.net.URL?imageURL?=?this.getClass().getResource("words.png");??????????java.net.URL?templateURL?=?this.getClass().getResource("template.png");????????????????????try?{??????????????template?=?ImageIO.read(templateURL);??????????????targetImage?=?ImageIO.read(imageURL);??????????}?catch?(IOException?e)?{??????????????e.printStackTrace();??????????}??????}????????????public?void?setTarget(BufferedImage?target)?{??????????this.targetImage?=?target;??????}????????@Override??????protected?void?paintComponent(Graphics?g)?{??????????Graphics2D?g2?=?(Graphics2D)?g;??????????if(targetImage?!=?null)?{??????????????g2.drawImage(targetImage,?10,?10,?targetImage.getWidth(),?targetImage.getHeight(),?null);??????????}??????????if(template?!=?null)?{??????????????g2.drawImage(template,?20+targetImage.getWidth(),?10,?template.getWidth(),?template.getHeight(),?null);??????????}??????}????????????public?static?void?main(String[]?args)?{??????????JFrame?f?=?new?JFrame("模板匹配與識(shí)別");??????????JButton?okBtn?=?new?JButton("匹配");??????????final?DemoUI?ui?=?new?DemoUI();??????????okBtn.addActionListener(new?ActionListener()?{????????????????@Override??????????????public?void?actionPerformed(ActionEvent?e)?{????????????????????????????????????ui.process();??????????????}??????????});????????????????????JPanel?btnPanel?=?new?JPanel();??????????btnPanel.setLayout(new?FlowLayout(FlowLayout.RIGHT));??????????btnPanel.add(okBtn);????????????????????f.getContentPane().add(btnPanel,?BorderLayout.SOUTH);??????????f.getContentPane().add(ui,?BorderLayout.CENTER);??????????f.setSize(500,?500);??????????f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);??????????f.setVisible(true);??????}????????protected?void?process()?{??????????NccTemplateMatchAlg?algo?=?new?NccTemplateMatchAlg(template);??????????targetImage?=?algo.filter(targetImage,?null);??????????this.repaint();??????}????}??
四:程序運(yùn)行效果如下
其中左邊是目標(biāo)圖像、右邊為模板圖像
PS:博客從10月份開始每月都有多篇相關(guān)圖像處理文章更新
歡迎大家繼續(xù)關(guān)注
總結(jié)
以上是生活随笔為你收集整理的图像处理之基于NCC模板匹配识别的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。