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. 【Azure APIM】验证APIM删除后的恢复步骤

    问题描述 在Azure门户中,误删除API Management资源后,怎么办? 问题解答 遇见误删除的第一反应就是: 想恢复删除的内容,但是从门户上查看没有发现有可以操作的方面. (错误,Azure ...

  2. 浅析图数据库 Nebula Graph 数据导入工具——Spark Writer

    从 Hadoop 说起 近年来随着大数据的兴起,分布式计算引擎层出不穷.Hadoop 是 Apache 开源组织的一个分布式计算开源框架,在很多大型网站上都已经得到了应用.Hadoop 的设计核心思想 ...

  3. 为SQL Server配置连接加密

    前言 很多客户在对数据库做安全审计时要求配置连接加密,本文就如何配置加密以及使用证书做一个系统的整理. 连接加密 首先,连接加密不是透明数据加密,很多人经常把两个概念混淆.连接加密是指客户端程序和SQ ...

  4. Java 小练习(3) 方法的修改+ 调用

    1 package com.bytezero.exer; 2 3 public class ExerTest 4 { 5 public static void main(String[] args) ...

  5. C语言之牛必克拉斯 main() 函数

    C语言之main()函数 C程序最大的特点就是所有的程序都是用函数来装配的.main()称之为主函数,是所有程序运行的入口.其余函数分为有参或无参两种,均由main()函数或其它一般函数调用,若调用的 ...

  6. beanstalkd轻量级消息队列的安装

    1.版本介绍 CentOS:CentOS Linux release 7.9.2009 (Core) beanstalkd:beanstalkd 1.10 2.安装 (1)先安装epel-releas ...

  7. org.jetbrains.idea.maven - com.google.inject.CreationException: Unable to create injector, see the following errors-导入maven项目报错

    一.问题由来 最近准备更换Java开发工具,以前是使用Eclipse,现在准备换成号称Java开发神器的IntelliJ IDEA .在同事那里找到安装包后, 安装,导入需要的文件等等,一切都进行得很 ...

  8. 网关接口映射项目 前端 nestjs 项目名称 tf-gateway-http-proxy 改Nginx了

    需求 前端 需要连接后台地址,每次换别人联调都要修改,好几个项目的时候,就要改好几个 关键每次git提交 还会显示文件修改了 强迫症患者 表示 忍不了 群里有人给了个脚本 有时间可以替换nginx h ...

  9. idea branch 分支比较 | git 查看分支命令 `git branch -vv`

    git 查看分支命令 git branch -vv

  10. Android 语音播放(文字TTS)

    原文地址:Android 语音播放(文字TTS) | Stars-One的杂货小窝 基于Google内置的TTS引擎,封装了个语音播放的工具类 使用 //初始化 SpeechService.init( ...