1.NCC算法实现及其优化[基础实现篇]
NCC算法实现及其优化
本文将集中探讨一种实现相对简单,效果较好的模板匹配算法(NCC)
\[R(x,y)= \frac{ \sum_{x',y'} (T'(x',y') \cdot I'(x+x',y+y')) }{ \sqrt{\sum_{x',y'}T'(x',y')^2 \cdot \sum_{x',y'} I'(x+x',y+y')^2} }
\\
\\
\begin{array}{l} T'(x',y')=T(x',y') - 1/(w \cdot h) \cdot \sum _{ x'',y''} T(x'',y'') \\ I'(x+x',y+y')=I(x+x',y+y') - 1/(w \cdot h) \cdot \sum _{x'',y''} I(x+x'',y+y'') \end{array}
\]具体原理是高中知识,也就是Spearma相关系数,这里就不赘述了。
基本实现代码
float MatchTemplateCPU(int8_t* pSearchImage,
    int8_t* pTemplate,
    int nSearchImageWidth,
    int nSearchImageHeight,
    int nTemplateWidth,
    int nTemplateHeight,
    int& nMatchPointX,
    int& nMatchPointY
)
{
    //R(x,y)= \frac{ \sum_{x',y'} (T'(x',y') \cdot I'(x+x',y+y')) }{ \sqrt{\sum_{x',y'}T'(x',y')^2 \cdot \sum_{x',y'} I'(x+x',y+y')^2} }
    //T'(x', y')=T(x', y') - 1/(w \cdot h) \cdot \sum _{ x'',y''} T(x'',y'')
    //I'(x + x',y+y') = I(x + x',y+y') - 1 / (w \cdot h) \cdot \sum _{ x'',y'' } I(x + x'', y + y'')
//预处理T和S
    float fAvgT = 0;
    for (int i = 0; i < nTemplateHeight; i++)
    {
        for (int j = 0; j < nTemplateWidth; j++)
		{
            fAvgT += pTemplate[i * nTemplateWidth + j];
		}
    }
    fAvgT = fAvgT / (nTemplateHeight * nTemplateWidth);
    float fSigmaT = 0;
    float *fT=new float[nTemplateHeight*nTemplateWidth];
    for (int i = 0; i < nTemplateHeight; i++)
	{
		for (int j = 0; j < nTemplateWidth; j++)
		{
            fT[i * nTemplateWidth + j] = pTemplate[i * nTemplateWidth + j] - fAvgT;
			fSigmaT += fT[i * nTemplateWidth + j] * fT[i * nTemplateWidth + j];
		}
	}
//结束预处理
    int nRetHeight=nSearchImageHeight-nTemplateHeight;
    int nRetWidth=nSearchImageWidth-nTemplateWidth;
    float* m_pRet=new float[nRetHeight*nRetWidth];
    float fMaxScore = -1;
    int sze_Template = nTemplateHeight * nTemplateWidth;
    for (int i = 0; i < nRetHeight; i++)
    {
        for (int j = 0; j < nRetWidth; j++)
        {
            float fSigmaS=0;
            for (int m = 0; m < nTemplateHeight; m++)
            {
                for (int n = 0; n < nTemplateWidth; n++)
                {
                    fSigmaS += pSearchImage[(i + m) * nSearchImageWidth + j + n];
                }
            }
            float fSigmaST = 0;
            for (int m = 0; m < nTemplateHeight; m++)
            {
                for (int n = 0; n < nTemplateWidth; n++)
                {
					fSigmaST += fT[m * nTemplateWidth + n] * (pSearchImage[(i + m) * nSearchImageWidth + j + n] - fSigmaS/ sze_Template);
                }
            }
            m_pRet[i * nRetWidth + j] = fSigmaST / sqrt(fSigmaS * fSigmaT);
            if (m_pRet[i * nRetWidth + j] > fMaxScore)
			{
				fMaxScore = m_pRet[i * nRetWidth + j];
				nMatchPointX = j;
				nMatchPointY = i;
			}
        }
    }
    return fMaxScore;
}
这里的这段代码实际运行速度非常慢。下一章我将讲解如何使用FFT算法加速计算。
优化思路
根据公式不难得出NCC算法的复杂度为$$\O(n^4)$$,是一种计算复杂度很大的算法。在笔者 i9-13900HX 处理器单线程上仍需要将近12s才能完成(1000 * 1000上匹配100 * 100)。
因此需要先把复杂度降低再考虑其他方向的优化。
1.NCC算法实现及其优化[基础实现篇]的更多相关文章
- 游戏中的自动寻路-A*算法(第一版优化——走斜线篇)
		一.简述以及地图 G 表示从起点移动到网格上指定方格的移动距离 (暂时不考虑沿斜向移动,只考虑上下左右移动). H 表示从指定的方格移动到终点的预计移动距离,只计算直线距离,走直角篇走的是直角路线. ... 
- 转:机器学习中的算法(2)-支持向量机(SVM)基础
		机器学习中的算法(2)-支持向量机(SVM)基础 转:http://www.cnblogs.com/LeftNotEasy/archive/2011/05/02/basic-of-svm.html 版 ... 
- 【算法】342- JavaScript常用基础算法
		一个算法只是一个把确定的数据结构的输入转化为一个确定的数据结构的输出的function.算法内在的逻辑决定了如何转换. 基础算法 一.排序 1.冒泡排序 //冒泡排序function bubbleSo ... 
- Java 排序算法-冒泡排序及其优化
		Java 排序算法-冒泡排序及其优化 什么是冒泡排序 基本写法 优化后写法 终极版本 源码及测试 什么是冒泡排序 这里引用一下百度百科上的定义: 冒泡排序(Bubble Sort),是一种计算机科学领 ... 
- SSE图像算法优化系列二:高斯模糊算法的全面优化过程分享(一)。
		这里的高斯模糊采用的是论文<Recursive implementation of the Gaussian filter>里描述的递归算法. 仔细观察和理解上述公式,在forward过程 ... 
- 小波学习之二(单层一维离散小波变换DWT的Mallat算法C++实现优化)--转载
		小波学习之二(单层一维离散小波变换DWT的Mallat算法C++实现优化) 在上回<小波学习之一>中,已经详细介绍了Mallat算法C++实现,效果还可以,但也存在一些问题,比如,代码 ... 
- PLSQL优化基础和性能优化 (学习总结)
		PLSQL优化基础和性能优化 (学习总结) 网上有一篇关于PLSQL优化的文章,不错,个人根据自己的经验再稍加整理和归纳,总结PLSQL优化和性能调优 适合有一定PLSQL基础,需要进一步提高的学友看 ... 
- 数据结构和算法(Golang实现)(9)基础知识-算法复杂度及渐进符号
		算法复杂度及渐进符号 一.算法复杂度 首先每个程序运行过程中,都要占用一定的计算机资源,比如内存,磁盘等,这些是空间,计算过程中需要判断,循环执行某些逻辑,周而反复,这些是时间. 那么一个算法有多好, ... 
- 数据结构和算法(Golang实现)(10)基础知识-算法复杂度主方法
		算法复杂度主方法 有时候,我们要评估一个算法的复杂度,但是算法被分散为几个递归的子问题,这样评估起来很难,有一个数学公式可以很快地评估出来. 一.复杂度主方法 主方法,也可以叫主定理.对于那些用分治法 ... 
- 【Java虚拟机4】Java内存模型(硬件层面的并发优化基础知识--缓存一致性问题)
		前言 今天学习了Java内存模型第一课的视频,讲了硬件层面的知识,还是和大学时一样,醍醐灌顶.老师讲得太好了. Java内存模型,感觉以前学得比较抽象.很繁杂,抽象. 这次试着系统一点跟着2个老师学习 ... 
随机推荐
- 【LeetCode链表#12】链表相交
			链表相交 同:160.链表相交 力扣题目链接(opens new window) 给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点.如果两个链表没有交点,返 ... 
- 【Azure Redis 缓存 Azure Cache For Redis】Redis支持的版本及不同版本迁移风险
			问题描述 1. Azure Redis缓存支持的版本包括4.0以及6.0(预览) 这种情形下,可以使用PaaS服务提供的 Azure Redis 缓存(4.0版本).Azure Redis对6.0的支 ... 
- 【Azure Redis 缓存】Redis连接无法建立问题的排查(注:Azure Redis集成在VNET中)
			问题描述 在Azure App Service中部署的应用,需要连接到Redis中,目标Redis已经集成了虚拟网络(VNET)并且在Redis的网络防火墙中已经添加App Service的出站IP地 ... 
- 【Azure 环境】Azure门户中 Metrics 图表的聚合指标每项具体代表什么意思呢?
			问题描述 下图中,指标里的每项聚合指标具体代表什么呢? 问题解答 Azure Metrics 指标中提供了五种基本的聚合类型. Sum - 在聚合间隔内捕获的所有值的总和. 有时称为总聚合. Coun ... 
- UserWarning: To get the last learning rate computed by the scheduler, please use `get_last_lr()`
			将 lr = scheduler.get_lr() 改为 lr = scheduler.get_last_lr() 
- C#多线程(11):线程等待
			目录 前言 volatile 关键字 三种常用等待 再说自旋和阻塞 SpinWait 结构 属性和方法 自旋示例 新的实现 SpinLock 结构 属性和方法 示例 等待性能对比 前面我们学习了很多用 ... 
- Effective C++ 第一章:让自己习惯C++
			Effective C++ 第一章:让自己习惯C++ 引言 最近在阅读这本<effective C++ 改善程序与设计的55个具体做法>这本书,为了以后忘记的时候回顾,写一些笔记,每次笔记 ... 
- Redis集群Cluster
			Redis Cluster 是社区版推出的 Redis 分布式集群解决方案,主要解决 Redis 分布式方面的需求,比如,当遇到单机内存,并发和流量等瓶颈的时候,Redis Cluster 能起到很好 ... 
- 我见过最好的.NET/C#图片工具(裁剪、缩放、与加水印)
			付费才能得到的好资源,限今天"免费"领取,月薪超30k必备技能! 资源1:高薪热门[WPF上位机+工业互联网]从零手写实战回复wpf免费领取 资源2:C#+Halcon机器视觉零基 ... 
- 来自 AI Secure 实验室的 LLM 安全排行榜简介
			近来,LLM 已深入人心,大有燎原之势.但在我们将其应用于千行百业之前,理解其在不同场景下的安全性和潜在风险显得尤为重要.为此,美国白宫发布了关于安全.可靠.可信的人工智能的行政命令; 欧盟人工智能法 ... 
