图像处理之基于NCC模板匹配识别

一:基本原理

NCC是一种基于统计学计算两组样本数据相关性的算法,其取值范围为[-1, 1]之间,而对图像来说,每个像素点都可以看出是RGB数值,这样整幅图像就可以看成是一个样本数据的集合,如果它有一个子集与另外一个样本数据相互匹配则它的ncc值为1,表示相关性很高,如果是-1则表示完全不相关,基于这个原理,实现图像基于模板匹配识别算法,其中第一步就是要归一化数据,数学公式如下:

二:实现步骤

(1)      获取模板像素并计算均值与标准方差、像素与均值diff数据样本

(2)      根据模板大小,在目标图像上从左到右,从上到下移动窗口,计

算每移动一个像素之后窗口内像素与模板像素的ncc值,与阈值比较,大于

阈值则记录位置

(3)      根据得到位置信息,使用红色矩形标记出模板匹配识别结果。

(4)      UI显示结果

三:编程实现

基于JAVA语言完成了整个算法编程实现与演示,其中第一步的代码如下:

		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;

第二步的实现代码如下:

		int[] windowPixels = new int[tw * th];
		Arrays.fill(windowPixels, 0);
		for (int row = 0; row < height; row++) {
			for (int col = 0; col < width; col++) {
				// calculate the means and dev for each window
				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++;
				}
				// calculate the ncc
				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);
				}
			}
		}

第三步的实现代码如下:

		// draw matched template on target image according position
		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);
		}

其中第二步用到的计算NCC的方法实现如下:

	private double calculateNcc(double[] tDiff, double[] diff, double dev1, double dev2) {
		// TODO Auto-generated method stub
		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部分完整源代码如下:

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("模板匹配与识别");
		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();
	}

}

四:程序运行效果如下


其中左边是目标图像、右边为模板图像

PS:博客从10月份开始每月都有多篇相关图像处理文章更新

欢迎大家继续关注

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-03 11:15:41

图像处理之基于NCC模板匹配识别的相关文章

字符识别OCR研究一(模板匹配&amp;amp;BP神经网络训练)

摘 要 在MATLAB环境下利用USB摄像头採集字符图像.读取一帧保存为图像.然后对读取保存的字符图像,灰度化.二值化,在此基础上做倾斜矫正.对矫正的图像进行滤波平滑处理,然后对字符区域进行提取切割出单个字符.识别方法一是採用模板匹配的方法逐个对字符与预先制作好的字符模板比較,假设结果小于某一阈值则结果就是模板上的字符:二是採用BP神经网络训练.通过训练好的net对待识别字符进行识别.最然后将识别结果通过MATLAB下的串口工具输出51单片机上用液晶显示出来. keyword: 倾斜矫正.字符切

基于HALCON的模板匹配方法总结 (转)

很早就想总结一下前段时间学习HALCON的心得,但由于其他的事情总是抽不出时间.去年有过一段时间的集中学习,做了许多的练习和实验,并对基于HDevelop的形状匹配算法的参数优化进行了研究,写了一篇<基于HDevelop的形状匹配算法参数的优化研究>文章,总结了在形状匹配过程中哪些参数影响到模板的搜索和匹配,又如何来协调这些参数来加快匹配过程,提高匹配的精度,这篇paper放到了中国论文在线了,需要可以去下载. 德国MVTec公司开发的HALCON机器视觉开发软件,提供了许多的功能,在这里我主

基于边界的模板匹配的原理及算法实现

最近被Halcon中的基于边缘的模板匹配算法吸引到了,故找到了一点点学习资料,供同行参阅,水平有限,大家多包含.本文算法很初级,做入门了解用.原文是英文,所以把原文copy 过来了,另加了一些中文.算法运行效果如下: [效果还行,只是原理性示意,不要要求太高了哦] Introduction Template matching is an image processing problem to find the location of an object using a template imag

基于opencv的视频流 模板匹配 (灰度化 二值化 )

#include <cv.h> #include <highgui.h> #include <windows.h> // 获取直方图 // 1. pImageData 图像数据 // 2. nWidth 图像宽度 // 3. nHeight 图像高度 // 4. nWidthStep 图像行大小 // 5. pHistogram 直方图 BOOL GetHistogram(unsigned char *pImageData, int nWidth, int nHeigh

图像处理 模板匹配

演示用局部图片匹配整张图片 VS2017 + OpenCV4.0.1编译 1 #include <iostream> 2 #include <opencv2/opencv.hpp> 3 #include <opencv2/core.hpp> 4 #include <opencv2/highgui.hpp> 5 #include <opencv2/imgproc.hpp> 6 using namespace std; 7 using namespa

Python+OpenCV图像处理之模板匹配

模板匹配就是在整个图像区域中发现与给定子图像匹配的小块区域 在OpenCV中,提供了相应的函数完成这个操作: matchTemplate 函数:在模板和输入图像之间寻找匹配,获得匹配结果图像 minMaxLoc 函数:在给定的矩阵中寻找最大和最小值,并给出它们的位置 几种常见的模板匹配算法: ①TM_SQDIFF是平方差匹配:TM_SQDIFF_NORMED是标准平方差匹配.利用平方差来进行匹配,最好匹配为0.匹配越差,匹配值越大. ②TM_CCORR是相关性匹配:TM_CCORR_NORMED

模式识别之ocr项目---(模板匹配&amp;BP神经网络训练)

摘 要 在MATLAB环境下利用USB摄像头采集字符图像,读取一帧保存为图像,然后对读取保存的字符图像,灰度化,二值化,在此基础上做倾斜矫正,对矫正的图像进行滤波平滑处理,然后对字符区域进行提取分割出单个字符,识别方法一是采用模板匹配的方法逐个对字符与预先制作好的字符模板比较,如果结果小于某一阈值则结果就是模板上的字符:二是采用BP神经网络训练,通过训练好的net对待识别字符进行识别.最然后将识别结果通过MATLAB下的串口工具输出51单片机上用液晶显示出来. 关键字: 倾斜矫正,字符分割,模板

基于ARM的指纹识别门禁系统设计方案

现代社会高速发展,很多场合需要身份确认,传统的身份识别技术已经不能满足社会要求.人的身体特征具有不可复制性,因此人们开始研究生物识别技术,而指纹具有唯一性.终生不变性.难于伪造等特点,安全性高,因而得到了广泛应用.在一些机要部门,如银行.宾馆.机房等一般都安装有门禁系统,门禁系统是为保障人们生活.工作及财产安全, 对重要通道的出入口进行管理与控制的系统,基于指纹识别技术的门禁系统是一项高科技安全设施,提高了系统的安全性.ARM作为一种嵌入式系统处理器,具有高性能.低功耗.低成本等特点,因而在工业

[模式识别].(希腊)西奥多里蒂斯&lt;第四版&gt;笔记8之__模板匹配

  对语音识别来讲,同一个单词被同一个人每次说的情况都不同,给识别带来困难.本章讨论的就是对不同的情形如何定义适应不同特性的度量. 1,基于最优路径搜索的度量:①贝尔曼最优性原则和动态编程②编辑距离(The Edit Distance)③在语音识别动态时间扭曲(DTW), speaker-dependentrecognition. speaker-independentrecognition. 2,基于相关性的度量:这一部分解决的问题是"给定一组记录数据,查找数据是否包含已知模式,并找出其具体位