AVX 指令集并行技术优化中值滤波

举报
ShaderJoy 发表于 2021/12/31 23:12:00 2021/12/31
【摘要】 利用 AVX 向量化技术优化的中值滤波 代码和注释如下: void medianFilterAVX(int height, int width, unsigned char *__restrict src, unsigned char *__restrict dst){ // 注意是从 1 开始 for(int i = 1;...

利用 AVX 向量化技术优化的中值滤波

代码和注释如下:


  
  1. void medianFilterAVX(int height, int width, unsigned char *__restrict src, unsigned char *__restrict dst)
  2. {
  3. // 注意是从 1 开始
  4. for(int i = 1; i < height - 1; i++)
  5. {
  6. int j;
  7. // 4字节*8 = 32
  8. for(j = 1; j < width - 1 - 32; j += 32)
  9. {
  10. __m256i a[9]; // 3*3 的领域
  11. a[0] = _mm256_loadu_si256((__m256i *)(src + i * width + j)); // 非对齐模式加载8 个 int 型
  12. a[1] = _mm256_loadu_si256((__m256i *)(src + i * width + j + 1));
  13. a[2] = _mm256_loadu_si256((__m256i *)(src + i * width + j - 1));
  14. a[3] = _mm256_loadu_si256((__m256i *)(src + (i + 1) * width + j));
  15. a[4] = _mm256_loadu_si256((__m256i *)(src + (i + 1) * width + j + 1));
  16. a[5] = _mm256_loadu_si256((__m256i *)(src + (i + 1) * width + j - 1));
  17. a[6] = _mm256_loadu_si256((__m256i *)(src + (i - 1) * width + j));
  18. a[7] = _mm256_loadu_si256((__m256i *)(src + (i - 1) * width + j + 1));
  19. a[8] = _mm256_loadu_si256((__m256i *)(src + (i - 1) * width + j - 1));
  20. // 因为只要知道中值就好(a[4])
  21. for( int ji = 0; ji < 5; ji++)
  22. {
  23. for( int k = ji + 1; k < 9; k++)
  24. {
  25. // 逐字节的比较(32个字节)
  26. __m256i large = _mm256_max_epu8(a[ji], a[k]);
  27. __m256i small = _mm256_min_epu8(a[ji], a[k]);
  28. a[ji] = small;
  29. a[k] = large;
  30. }
  31. }
  32. _mm256_storeu_si256((__m256i *)(dst + i * width + j), a[4]);// 非对齐模式存储8 个 int 型
  33. }
  34. // 不能被 32 整除的部分
  35. for(int je = j; je < width - 1; je++)
  36. {
  37. unsigned char a[9];
  38. a[0] = src[i * width + je];
  39. a[1] = src[i * width + je + 1];
  40. a[2] = src[i * width + je - 1];
  41. a[3] = src[(i + 1) * width + je];
  42. a[4] = src[(i + 1) * width + je + 1];
  43. a[5] = src[(i + 1) * width + je - 1];
  44. a[6] = src[(i - 1) * width + je];
  45. a[7] = src[(i - 1) * width + je + 1];
  46. a[8] = src[(i - 1) * width + je - 1];
  47. for( int ji = 0; ji < 5; ji++)
  48. {
  49. for( int jj = ji + 1; jj < 9; jj++)
  50. {
  51. unsigned char large = std::max<unsigned char>(a[ji], a[jj]);
  52. unsigned char small = std::min<unsigned char>(a[ji], a[jj]);
  53. a[ji] = small;
  54. a[jj] = large;
  55. }
  56. }
  57. dst[i * width + je] = a[4];
  58. }
  59. }
  60. // 边界处理:直接拷贝
  61. for( int i = 0; i < width; i++)
  62. {
  63. dst[i] = src[i];
  64. dst[(height - 1)*width + i] = src[(height - 1) * width + i];
  65. }
  66. for(int i = 0; i < height; i++)
  67. {
  68. dst[i * width] = src[i * width];
  69. dst[i * width + width - 1] = src[i * width + width - 1];
  70. }
  71. }

入口函数:


  
  1. cv::Mat input = imread("micky.png", cv::IMREAD_GRAYSCALE);
  2. cv::Mat scale;
  3. cv::resize(input, scale, cv::Size(3200, 3200));// 为了使得优化效果更明显
  4. int width = scale.cols;
  5. int height = scale.rows;
  6. cv::Mat output = cv::Mat(cv::Size(width, height), CV_8UC1, cv::Scalar(0));
  7. Timer timer;
  8. //meanFilter(scale.data, output.data, width, height);
  9. medianFilter(height, width, scale.data, output.data);
  10. timer.rlog("时间");
  11. timer.restart();
  12. medianFilterAVX(height, width, scale.data, output.data);
  13. timer.rlog("时间");

和串行版本的比较结果如下:提升了将近 19 倍

文章来源: panda1234lee.blog.csdn.net,作者:panda1234lee,版权归原作者所有,如需转载,请联系作者。

原文链接:panda1234lee.blog.csdn.net/article/details/85016941

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。