C++ opencv ncc归一化互相关 使用SSE优化 具体实现代码
时间: 2024-05-04 21:21:16 浏览: 183
归一化互相关(Normalized Cross-Correlation,NCC)是一种常用的图像匹配方法,可以用于模板匹配、目标跟踪等领域。SSE(Streaming SIMD Extensions)是Intel公司开发的一种SIMD指令集,可以在处理器中同时处理多个数据。下面是使用SSE优化的归一化互相关的实现代码:
```c++
#include <emmintrin.h> // 包含SSE指令集头文件
#include <opencv2/opencv.hpp>
using namespace cv;
void NCC_SSE(const Mat& img, const Mat& templ, Mat& result)
{
int img_h = img.rows, img_w = img.cols;
int templ_h = templ.rows, templ_w = templ.cols;
int result_h = img_h - templ_h + 1, result_w = img_w - templ_w + 1;
result.create(result_h, result_w, CV_32FC1);
__m128i zero = _mm_setzero_si128(); // 初始化一个全0的向量
for (int i = 0; i < result_h; i++)
{
for (int j = 0; j < result_w; j += 4)
{
__m128 sum = _mm_setzero_ps(); // 初始化一个全0的向量
// 计算模板和图像的均值
float templ_mean = mean(templ)[0];
Mat img_roi(img, Rect(j, i, templ_w, templ_h));
float img_mean = mean(img_roi)[0];
// 计算模板和图像的标准差
Mat templ_square, img_square;
multiply(templ, templ, templ_square);
multiply(img_roi, img_roi, img_square);
float templ_stddev = sqrt(mean(templ_square)[0] - templ_mean * templ_mean);
float img_stddev = sqrt(mean(img_square)[0] - img_mean * img_mean);
// 计算NCC
for (int k = 0; k < templ_h; k++)
{
const float* img_ptr = img.ptr<float>(i + k) + j;
const float* templ_ptr = templ.ptr<float>(k);
for (int l = 0; l < templ_w; l += 4)
{
__m128 a = _mm_loadu_ps(img_ptr + l);
__m128 b = _mm_loadu_ps(templ_ptr + l);
__m128 c = _mm_sub_ps(a, _mm_set1_ps(img_mean));
__m128 d = _mm_sub_ps(b, _mm_set1_ps(templ_mean));
__m128 e = _mm_mul_ps(c, d);
sum = _mm_add_ps(sum, e);
}
}
// 归一化
float scale = img_stddev / templ_stddev;
__m128 s = _mm_set1_ps(scale);
__m128 r = _mm_div_ps(sum, _mm_mul_ps(_mm_set1_ps(templ_w * templ_h), _mm_mul_ps(_mm_set1_ps(img_stddev), s)));
r = _mm_max_ps(r, zero);
result.at<float>(i, j) = r[0];
result.at<float>(i, j + 1) = r[1];
result.at<float>(i, j + 2) = r[2];
result.at<float>(i, j + 3) = r[3];
}
}
}
```
其中,`__m128`是SSE指令集中的128位向量类型,可以同时存储4个float类型的数据,`_mm_loadu_ps`、`_mm_set1_ps`、`_mm_add_ps`、`_mm_sub_ps`、`_mm_mul_ps`、`_mm_div_ps`等函数是SSE指令集中的函数,用于对向量进行加载、赋值、加减乘除等操作。在计算NCC时,利用SSE指令集的优势,可以同时计算4个像素的结果,从而提高了计算效率。
阅读全文