opencv455通过getRotationMatrix2D创建变换矩阵使用SSE2加速warpAffine并带参数WARP_INVERSE_MAP
时间: 2024-01-11 19:02:44 浏览: 82
在OpenCV 4.4.5中,使用SSE2加速warpAffine并带参数WARP_INVERSE_MAP可以通过以下步骤实现:
1. 在编译OpenCV时启用SSE2加速,可以在CMake中设置WITH_SSE2选项为ON。
2. 使用cv::getRotationMatrix2D函数创建变换矩阵,例如:
```
cv::Mat rot_mat = cv::getRotationMatrix2D(center, angle, scale);
```
其中,center表示旋转中心,angle表示旋转角度,scale表示缩放比例。
3. 将变换矩阵转换为__m128类型,并进行数据对齐,例如:
```
__m128 rot_mat_aligned[2];
rot_mat_aligned[0] = _mm_load_ps(rot_mat.ptr<float>(0));
rot_mat_aligned[1] = _mm_load_ps(rot_mat.ptr<float>(1));
```
其中,_mm_load_ps函数可以将4个单精度浮点数加载到__m128类型中。
4. 使用SSE2指令集进行仿射变换,例如:
```
for (int y = 0; y < dst.rows; y++) {
float* dst_row = dst.ptr<float>(y);
float x = center.x - dst.cols / 2.0f;
float yf = center.y - y - dst.rows / 2.0f;
__m128 xf = _mm_set1_ps(x);
__m128 yf_aligned = _mm_set1_ps(yf);
for (int x = 0; x < dst.cols; x += 4) {
__m128 x0f = _mm_setr_ps(x + 0.0f, x + 1.0f, x + 2.0f, x + 3.0f);
__m128 xf_aligned = _mm_add_ps(xf, x0f);
__m128 x_src_f = _mm_add_ps(_mm_mul_ps(rot_mat_aligned[0], xf_aligned),
_mm_mul_ps(rot_mat_aligned[1], yf_aligned));
__m128 y_src_f = _mm_add_ps(_mm_mul_ps(rot_mat_aligned[2], xf_aligned),
_mm_mul_ps(rot_mat_aligned[3], yf_aligned));
__m128i x_src_i = _mm_cvtps_epi32(x_src_f);
__m128i y_src_i = _mm_cvtps_epi32(y_src_f);
__m128i src_idx = _mm_add_epi32(_mm_mullo_epi32(y_src_i, src_step), x_src_i);
__m128 src_val0 = _mm_loadu_ps(src_ptr + _mm_extract_epi16(src_idx, 0) * src_channels);
__m128 src_val1 = _mm_loadu_ps(src_ptr + _mm_extract_epi16(src_idx, 1) * src_channels);
__m128 src_val2 = _mm_loadu_ps(src_ptr + _mm_extract_epi16(src_idx, 2) * src_channels);
__m128 src_val3 = _mm_loadu_ps(src_ptr + _mm_extract_epi16(src_idx, 3) * src_channels);
__m128 src_val01 = _mm_shuffle_ps(src_val0, src_val1, _MM_SHUFFLE(1, 0, 1, 0));
__m128 src_val23 = _mm_shuffle_ps(src_val2, src_val3, _MM_SHUFFLE(1, 0, 1, 0));
__m128 src_val = _mm_shuffle_ps(src_val01, src_val23, _MM_SHUFFLE(2, 0, 2, 0));
_mm_storeu_ps(dst_row + x, src_val);
}
}
```
其中,_mm_add_ps、_mm_mul_ps、_mm_set1_ps、_mm_setr_ps、_mm_shuffle_ps、_mm_cvtps_epi32、_mm_extract_epi16、_mm_add_epi32、_mm_mullo_epi32、_mm_loadu_ps和_mm_storeu_ps等函数都是SSE2指令集中的函数,可以参考Intel的SSE2指令集文档进行学习。
5. 如果需要进一步优化,可以使用OpenCV的parallel_for_函数和多线程技术,以便利用多核CPU进行加速。具体实现方法可以参考OpenCV的官方文档和代码示例。
需要注意的是,使用SSE2加速需要满足一些条件,例如数据需要对齐,否则可能会出现未定义的行为。此外,SSE2指令集并不是适用于所有情况,需要根据具体的应用场景进行选择。
阅读全文