First: Fundamentals
NCC is an algorithm based on statistics to calculate the correlation of two sets of sample data, the value range is between [-1, 1], and for the image, each pixel can be seen as an RGB value, so that the whole image can be regarded as a collection of sample data, If it has a subset with another sample data matching its NCC value is 1, indicating that the correlation is very high, if 1 is completely irrelevant, based on this principle, the realization of image based on template matching recognition algorithm, the first step is to normalized the data, the mathematical formula is as follows:
Two: implementation steps
(1) Get the template pixel and calculate the mean and standard variance, pixel and mean diff data sample
(2) According to the template size, on the target image from left to right, from top to bottom to move the window, Count
The NCC value of the pixel in the window and the template pixel after each pixel move, compared to the threshold value, greater than
The threshold value is the record position
(3) According to the obtained position information, the template matching recognition result is marked with a red rectangle.
(4) UI display results
Three: Programming implementation
The implementation and demonstration of the whole algorithm programming is done based on the Java language, in which the code of the first step is as follows:
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] >>) & 0xFF;} double[] Meansdev = Getpixelsmeansanddev (tpixels);d ouble[] Tdiff = Calculatediff (Tpixels, meansdev[0]); int Raidus_ width = Tw/2;int Raidus_height = TH/2;
The implementation code for the second step is as follows:
int[] Windowpixels = new INT[TW * th]; Arrays.fill (windowpixels, 0); for (int row = 0; row < height; row++) {for (int col = 0; col < width; col++) {//CALCU Late the means and dev for each windowif (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++;} Calculate the nccdouble[] _meansdev = Getpixelsmeansanddev (windowpixels);d ouble[] diff = Calculatediff (windowpixels, _meansdev[0]);d ouble NCC = CALCULATENCC (Tdiff, diff, _meansdev[1], meansdev[1]); if (NCC > Threhold) {point mpoint = new Point (); mpoint.x = Col;mpoint.y = Row;points.add (Mpoint);}}
The implementation code for the third step is as follows:
Draw matched template on target image according Positionsetrgb (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);}
The second step used to calculate the NCC method is implemented as follows:
Private double CALCULATENCC (double[] Tdiff, double[] diff, double dev1, double dev2) {//TODO auto-generated method Stubdo uble 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);}
The complete source code for the UI section is as follows:
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;privat E 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;} @Overrideprotected void Paintcomponent (Graphics g) {Graphics2d g2 = (graphics2d) g;if (targetimage! = null) {G2.drawimage (Targetimage, Ten, Targetimage.getwidth (), Targetimage. GetHeight (), null);} if (template! = null) {g2.drawimage (template, 20+targetimage.getwidth (), ten, Template.getwidth (), Template.getheight () , null);}} public static void Main (string[] args) {JFrame f = new JFrame ("template matching and recognition"); JButton okbtn = new JButton ("Match"), final Demoui UI = new Demoui (); Okbtn.addactionlistener (new ActionListener () {@Overridep ublic 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 ( F.setdefaultcloseoperation (Jframe.exit_on_close); f.setvisible (true);} protected void process () {Ncctemplatematchalg algo = new Ncctemplatematchalg (template); targetimage = Algo.filter ( Targetimage, NULL); This.repaint ();}}
Four: The program works as follows
Where the left side is the target image, the right is the template image
PS: Blog from October onwards every month has a number of related image processing articles updated
We welcome your continued attention
Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.
Recognition of image processing based on NCC template matching