你如何利用SIMD(如SSE/AVX)优化图像处理的性能?

embedded/2025/2/21 7:30:38/

SIMD优化问题

  • 1. SIMD 在图像处理中的优化方式
  • 2. 典型应用场景
  • 3. SIMD 的常见优化技巧
  • 4. 总结

利用 SIMD(Single Instruction, Multiple Data) 指令集(如 SSE/AVX/AVX2/AVX-512)优化图像处理的性能,可以极大地提升计算速度,减少 CPU 计算瓶颈。以下是具体的方法和示例:

1. SIMD 在图像处理中的优化方式

(1)SIMD 的原理
• 普通 CPU 处理方式:逐个像素计算(如 for 循环),每次只能处理一个数据。
• SIMD 处理方式:一次操作多个数据,例如 SSE 处理 4 个 32 位浮点数,AVX 处理 8 个 32 位浮点数,AVX-512 可处理 16 个 32 位浮点数。

2. 典型应用场景

1)灰度转换

RGB 图像转换为灰度图的公式:

Gray = 0.299 R + 0.587 G + 0.114 B

SIMD 优化代码(使用 AVX2):

#include <immintrin.h>  // 包含 AVX 指令集头文件
#include <opencv2/opencv.hpp>void rgb_to_gray_avx(const cv::Mat& src, cv::Mat& dst) {int width = src.cols;int height = src.rows;dst.create(height, width, CV_8UC1);__m256 r_weight = _mm256_set1_ps(0.299f);__m256 g_weight = _mm256_set1_ps(0.587f);__m256 b_weight = _mm256_set1_ps(0.114f);for (int y = 0; y < height; ++y) {const uchar* src_ptr = src.ptr<uchar>(y);uchar* dst_ptr = dst.ptr<uchar>(y);for (int x = 0; x < width; x += 8) {  // AVX 处理 8 个像素__m256 r = _mm256_cvtepi32_ps(_mm256_cvtepu8_epi32(_mm_loadl_epi64((__m128i*)(src_ptr + x * 3 + 0))));__m256 g = _mm256_cvtepi32_ps(_mm256_cvtepu8_epi32(_mm_loadl_epi64((__m128i*)(src_ptr + x * 3 + 1))));__m256 b = _mm256_cvtepi32_ps(_mm256_cvtepu8_epi32(_mm_loadl_epi64((__m128i*)(src_ptr + x * 3 + 2))));__m256 gray = _mm256_add_ps(_mm256_add_ps(_mm256_mul_ps(r, r_weight), _mm256_mul_ps(g, g_weight)), _mm256_mul_ps(b, b_weight));__m256i gray_int = _mm256_cvtps_epi32(gray);__m128i gray_8bit = _mm_packus_epi32(_mm256_castsi256_si128(gray_int), _mm256_extractf128_si256(gray_int, 1));_mm_storel_epi64((__m128i*)(dst_ptr + x), gray_8bit);}}
}

优化点:
• AVX2 一次处理 8 个像素,相比普通 for 循环,可以加速 8 倍。
• 使用 _mm256_mul_ps 进行浮点运算,提高吞吐量。

(2)高斯滤波

普通高斯滤波

G ( x , y ) = ∑ i = − 1 1 ∑ j = − 1 1 w ( i , j ) ⋅ I ( x + i , y + j ) G(x,y) = \sum\limits_{i=-1}^{1} \sum\limits_{j=-1}^{1} w(i,j) \cdot I(x+i, y+j) G(x,y)=i=11j=11w(i,j)I(x+i,y+j)

SIMD 优化思路
• 使用 SSE/AVX 加载多个像素点。
• 并行计算加权和,避免逐像素遍历。

SIMD 代码示例(AVX2 版本):

void gaussian_blur_avx(const cv::Mat& src, cv::Mat& dst) {int width = src.cols;int height = src.rows;dst.create(height, width, CV_8UC1);float kernel[3] = {0.25f, 0.5f, 0.25f}; // 高斯核__m256 k0 = _mm256_set1_ps(kernel[0]);__m256 k1 = _mm256_set1_ps(kernel[1]);__m256 k2 = _mm256_set1_ps(kernel[2]);for (int y = 1; y < height - 1; ++y) {for (int x = 1; x < width - 1; x += 8) {  // 8 个像素并行__m256 p0 = _mm256_cvtepi32_ps(_mm256_cvtepu8_epi32(_mm_loadl_epi64((__m128i*)&src.at<uchar>(y-1, x-1))));__m256 p1 = _mm256_cvtepi32_ps(_mm256_cvtepu8_epi32(_mm_loadl_epi64((__m128i*)&src.at<uchar>(y, x-1))));__m256 p2 = _mm256_cvtepi32_ps(_mm256_cvtepu8_epi32(_mm_loadl_epi64((__m128i*)&src.at<uchar>(y+1, x-1))));__m256 sum = _mm256_add_ps(_mm256_add_ps(_mm256_mul_ps(p0, k0), _mm256_mul_ps(p1, k1)), _mm256_mul_ps(p2, k2));__m256i result = _mm256_cvtps_epi32(sum);__m128i result_8bit = _mm_packus_epi32(_mm256_castsi256_si128(result), _mm256_extractf128_si256(result, 1));_mm_storel_epi64((__m128i*)&dst.at<uchar>(y, x), result_8bit);}}
}

优化点:
• 通过 _mm256_mul_ps 进行 SIMD 并行加权计算。
• 适用于 高斯模糊、均值滤波等卷积操作。

3. SIMD 的常见优化技巧

1.	使用对齐内存(如 _mm_malloc 或 alignas(32)),避免 内存访问未对齐 导致的性能下降。
2.	数据预取(Prefetching),减少 Cache Miss。
3.	循环展开(Loop Unrolling),减少 分支预测失败。
4.	减少分支(Branchless Programming),例如使用 _mm256_blendv_ps() 进行 条件运算。

4. 总结

在这里插入图片描述

使用 SIMD(SSE/AVX) 优化图像处理,不仅能显著提升性能,还能降低 CPU 负载,尤其适用于 工业检测、实时图像处理、深度学习预处理 等领域。


http://www.ppmy.cn/embedded/162438.html

相关文章

芯麦GC6208:革新摄像机与医疗设备的智能音频解决方案

引言 在现代科技的推动下&#xff0c;音频设备和图像处理在各个领域的应用日益广泛。芯麦科技的GC6208是一款创新的音频处理芯片&#xff0c;具有高性能和多功能性&#xff0c;适用于摄像机、医疗设备等多种产品。本文将探讨GC6208在这些领域中的应用及其带来的优势。 1. 在摄…

MySQL创建存储过程和存储函数

【图书推荐】《MySQL 9从入门到性能优化&#xff08;视频教学版&#xff09;》-CSDN博客 《MySQL 9从入门到性能优化&#xff08;视频教学版&#xff09;&#xff08;数据库技术丛书&#xff09;》(王英英)【摘要 书评 试读】- 京东图书 (jd.com) MySQL9数据库技术_夏天又到了…

单片机上SPI和IIC的区别

SPI&#xff08;Serial Peripheral Interface&#xff09;和IC&#xff08;Inter-Integrated Circuit&#xff09;是两种常用的嵌入式外设通信协议&#xff0c;它们各有优缺点&#xff0c;适用于不同的场景。以下是它们的详细对比&#xff1a; — 1. 基本概念 SPI&#xff0…

关于FSGithubPNG生成外链时描述出现路径问题

​ 之前在FSGithubPNG上添加一个新的功能&#xff0c;就是上传图片后生成的外链可以是Markdown格式的图片链接&#xff0c; 如下&#xff1a; ![美丽的风景](https://example.com/path/to/your/image.jpg)图片描述在不同系统下的差异 在 macOS 系统中&#xff0c;图片外链的…

关于post和get的请求参数问题

今天在和泓宇交流的时候&#xff0c;谈到了关于postman测试接口的问题。我昨天在postman测试的时候&#xff0c;对于条件查询不知道怎么测试&#xff0c;脑子里很混乱。今天&#xff0c;泓宇借着条件查询这个机会给我讲了讲get和post的请求参数的知识&#xff0c;趁着现在有记忆…

动态建表并插入数据

Service层根据解析到的数据在Mysql数据库中动态建表并插入数据 以Easy Excel解析得到的文件为例 Slf4j Service public class ExcelImportServiceImpl implements ExcelImportService {Autowired private ExcelImportDao dao; Value("${source.url}") private Stri…

vue中使用lodash的debounce(防抖函数)

1、安装 npm i --save lodash.debounce2、引入 import debounce from lodash.debounce3、使用 <van-search v-model"searchValue" placeholder"输入姓名或工号" inputhandleInput />第一种&#xff1a; handleInput: debounce(function (val) {c…

京东获得JD商品详情 API 返回值说明||京东API接口

item_get-获得JD商品详情 .jd.item_get 公共参数 名称类型必须描述keyString是调用key&#xff08;必须以GET方式拼接在URL中&#xff09;secretString是调用密钥api_nameString是API接口名称&#xff08;包括在请求地址中&#xff09;[item_search,item_get,item_search_sh…