SSE 标准化向量

           mov    esi,   this            ; vector u
            movups xmm0,  [esi]           ; first vector in xmm0
            movaps xmm2,  xmm0            ; copy original vector
            mulps  xmm0,  xmm0            ; mul with 2nd vector
            movaps xmm1,  xmm0            ; copy result
            shufps xmm1,  xmm1, 4Eh       ; shuffle: f1,f0,f3,f2
            addps  xmm0,  xmm1            ; add: f3+f1,f2+f0,f1+f3,f0+f2 
            movaps xmm1,  xmm0            ; copy results
            shufps xmm1,  xmm1, 11h       ; shuffle: f0+f2,f1+f3,f0+f2,f1+f3 
            addps  xmm0,  xmm1            ; add: x,x,f0+f1+f2+f3,f0+f1+f2+f3

            rsqrtps xmm0,  xmm0           ; recip. sqrt (faster than ss + shufps)
            mulps   xmm2,  xmm0           ; mul by reciprocal
            movups  [esi], xmm2           ; bring back result

核心思想 xmm寄存器 4分量 全部赋值为x*x +y*y + z*z, rsqrtps 求向量长度的倒数,最终乘以xmm2存的原向量,完成标准化。

rsqrtps用的查表方式,近似求的开方倒数,提高执行速度。精确求利用rsqrtss指令。

转载于:https://www.cnblogs.com/seebro/p/3774802.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
归一化互相关(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个像素的结果,从而提高了计算效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值