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算法实现及其优化[基础实现篇]的更多相关文章

  1. 游戏中的自动寻路-A*算法(第一版优化——走斜线篇)

    一.简述以及地图 G 表示从起点移动到网格上指定方格的移动距离 (暂时不考虑沿斜向移动,只考虑上下左右移动). H 表示从指定的方格移动到终点的预计移动距离,只计算直线距离,走直角篇走的是直角路线. ...

  2. 转:机器学习中的算法(2)-支持向量机(SVM)基础

    机器学习中的算法(2)-支持向量机(SVM)基础 转:http://www.cnblogs.com/LeftNotEasy/archive/2011/05/02/basic-of-svm.html 版 ...

  3. 【算法】342- JavaScript常用基础算法

    一个算法只是一个把确定的数据结构的输入转化为一个确定的数据结构的输出的function.算法内在的逻辑决定了如何转换. 基础算法 一.排序 1.冒泡排序 //冒泡排序function bubbleSo ...

  4. Java 排序算法-冒泡排序及其优化

    Java 排序算法-冒泡排序及其优化 什么是冒泡排序 基本写法 优化后写法 终极版本 源码及测试 什么是冒泡排序 这里引用一下百度百科上的定义: 冒泡排序(Bubble Sort),是一种计算机科学领 ...

  5. SSE图像算法优化系列二:高斯模糊算法的全面优化过程分享(一)。

    这里的高斯模糊采用的是论文<Recursive implementation of the Gaussian filter>里描述的递归算法. 仔细观察和理解上述公式,在forward过程 ...

  6. 小波学习之二(单层一维离散小波变换DWT的Mallat算法C++实现优化)--转载

    小波学习之二(单层一维离散小波变换DWT的Mallat算法C++实现优化)   在上回<小波学习之一>中,已经详细介绍了Mallat算法C++实现,效果还可以,但也存在一些问题,比如,代码 ...

  7. PLSQL优化基础和性能优化 (学习总结)

    PLSQL优化基础和性能优化 (学习总结) 网上有一篇关于PLSQL优化的文章,不错,个人根据自己的经验再稍加整理和归纳,总结PLSQL优化和性能调优 适合有一定PLSQL基础,需要进一步提高的学友看 ...

  8. 数据结构和算法(Golang实现)(9)基础知识-算法复杂度及渐进符号

    算法复杂度及渐进符号 一.算法复杂度 首先每个程序运行过程中,都要占用一定的计算机资源,比如内存,磁盘等,这些是空间,计算过程中需要判断,循环执行某些逻辑,周而反复,这些是时间. 那么一个算法有多好, ...

  9. 数据结构和算法(Golang实现)(10)基础知识-算法复杂度主方法

    算法复杂度主方法 有时候,我们要评估一个算法的复杂度,但是算法被分散为几个递归的子问题,这样评估起来很难,有一个数学公式可以很快地评估出来. 一.复杂度主方法 主方法,也可以叫主定理.对于那些用分治法 ...

  10. 【Java虚拟机4】Java内存模型(硬件层面的并发优化基础知识--缓存一致性问题)

    前言 今天学习了Java内存模型第一课的视频,讲了硬件层面的知识,还是和大学时一样,醍醐灌顶.老师讲得太好了. Java内存模型,感觉以前学得比较抽象.很繁杂,抽象. 这次试着系统一点跟着2个老师学习 ...

随机推荐

  1. ubuntu18.04下安装MySQL5.7

    更新源 sudo apt update 安装mysql sudo apt install mysql-server 使用sudo mysql进入数据设置root账户的密码和权限 sudo mysql ...

  2. 【Azure Logic App】在Logic App中使用 Transfer XML组件遇见错误 undefined

    问题描述 在Azure Logic App中,使用Transform XML组件进行XML内容的转换,但是最近这个组件运行始终失败. 问题解答 点击Transform XML组件上的错误案例,并不能查 ...

  3. linux用户权限相关命令笔记

    1,用户 和 权限 的基本概念 1.1 ls 扩展 ls -l 1.2 chmod 简单使用(重要) + 是加权限, - 是减权限 chmod 修改文件权限 chmod 修改目录权限: 想要在目录下执 ...

  4. Volatile关键字原理

    转载请标明:https://www.cnblogs.com/tangZH/p/15113505.html 一.如果一个变量被volatile关键字修饰,那么所有线程都是可见的.所谓可见就是,当一条线程 ...

  5. SoftCnKiller 更新程序 bat 调用vbs 更新,下载gitee文件 更新自身数据

    bat @echo off title 更新流氓软件黑名单 cd /d "%~dp0" echo 请选择更新源,默认使用1.GitCode更新. echo.&choice ...

  6. 英语自定义标签 <i:juzi><i:zhuyu>John Smith</i:zhuyu></i:juzi> 主语谓语宾语

    效果 John Smith died in World War Two. John Smith killed three enemy soldiers. <style> i\:juzi { ...

  7. C++统计代码运行时间

    本来想自己写的,一看github上面都有就不再重复造轮子了.github上的项目如下: StopWatch 纯标准库实现:使用std::chrono::high_resolution_clock,其实 ...

  8. shell脚本中将 IFS (Internal Field Separator 内部字段分隔符)替换为换行符

    将 IFS 中的空白符(换行.制表符.空格)修改为仅包含换行 IFS 是shell中的内部变量,在使用 for var in var_list;do use $var do something don ...

  9. 基于DSP的光纤麦克风声音采集系统硬件设计方案总结

    前记  光纤声传感器是一种利用光纤作为传光介质或探测单元的一类声传感器,相比传统电声传感器其具有灵敏度高.频带响应宽.抗电磁干扰等优越特性,可广泛应用于国防安全.工业无损检测.医疗诊断及消费电子等领域 ...

  10. 【UE虚幻引擎】干货!UE修改分辨率的3种方法

    虚幻引擎作为一款实时3D创作工具,在游戏.建筑.影视动画.虚拟仿真等领域受到全球各行各业创作者广泛欢迎,在UE中获取和设置分辨率也是3D创作开发工作中的常用功能.本文介绍了在虚幻引擎中修改分辨率的3种 ...