sobel算子_【AI PC端算法优化】四,一步步将Sobel边缘检测加速22倍

本文详细介绍了Sobel边缘检测算法的优化过程,从原始实现到利用SSE、AVX指令集进行优化,最终速度提升了22倍。通过逐版优化代码,展示了如何减少浮点运算、利用SIMD指令和并行计算提高效率。
摘要由CSDN通过智能技术生成

1. 前言

继续优化技术的探索,今天以一个

的Sobel算子进行边缘检测的算法为例来看看如何使用SSE指令集对其进行优化。

2. 原理介绍

众所周知,在传统的图像边缘检测算法中,最常用的一种算法是利用Sobel算子完成的。Sobel算子一共有

个,一个是检测水平边缘的算子,另一个是检测垂直边缘的算子。

Sobel算子的优点是可以利用快速卷积函数,简单有效,且对领域像素位置的影响做了加权,可以降低边缘模糊程度,有较好效果。然而Sobel算子并没有基于图像的灰度信息进行处理,所以在提取图像边缘信息的时候可能不会让人视觉满意。

我们来看一下怎么构造Sobel算子?

Sobel算子是在一个坐标轴的方向进行非归一化的高斯平滑,在另外一个坐标轴方向做一个差分,

大小的Sobel算子是由
平滑算子差分算子全卷积得到,其中
代表Sobel算子的半径,必须为奇数。

对于窗口大小为

非归一化Sobel平滑算子等于
阶的二项式展开式的系数,而
Sobel平滑算子等于
阶的二项式展开式的系数两侧补
,然后向前差分。

在这个例子中:我们要构造一个

阶的Sobel非归一化的
Sobel平滑算子和Sobel差分算子

Sobel平滑算子: 取二项式的阶数为

,然后计算展开式系数为,
也即是
,这就是
阶的非归一化的Sobel平滑算子。

Sobel差分算子:取二项式的阶数为

,然后计算二项展开式的系数,即为:
,两侧补
并且前向差分得到
,第
项差分后可以直接删除。

Sobel算子

阶的Sobel平滑算子和Sobel差分算子进行全卷积
,即可得到
的Sobel算子。

其中

方向的Sobel算子为:

方向的Sobel算子为:

3. 原始实现

我们先放出针对

的Sobel算子的原始实现代码,如下所示:
inline unsigned char IM_ClampToByte(int Value)
{
 if (Value < 0)
  return 0;
 else if (Value > 255)
  return 255;
 else
  return (unsigned char)Value;
 //return ((Value | ((signed int)(255 - Value) >> 31)) & ~((signed int)Value >> 31));
}

void Sobel_FLOAT(unsigned char *Src, unsigned char *Dest, int Width, int Height, int Stride) {
 int Channel = Stride / Width;
 unsigned char *RowCopy = (unsigned char*)malloc((Width + 2) * 3 * Channel);
 unsigned char *First = RowCopy;
 unsigned char *Second = RowCopy + (Width + 2) * Channel;
 unsigned char *Third = RowCopy + (Width + 2) * 2 * Channel;
 //拷贝第二行数据,边界值填充
 memcpy(Second, Src, Channel);
 memcpy(Second + Channel, Src, Width*Channel);
 memcpy(Second + (Width + 1)*Channel, Src + (Width - 1)*Channel, Channel);
 //第一行和第二行一样
 memcpy(First, Second, (Width + 2) * Channel);
 //拷贝第三行数据,边界值填充
 memcpy(Third, Src + Stride, Channel);
 memcpy(Third + Channel, Src + Stride, Width * Channel);
 memcpy(Third + (Width + 1) * Channel, Src + Stride + (Width - 1) * Channel, Channel);

 for (int Y = 0; Y < Height; Y++) {
  unsigned char *LinePS = Src + Y * Stride;
  unsigned char *LinePD = Dest + Y * Stride;
  if (Y != 0) {
   unsigned char *Temp = First;
   First = Second;
   Second = Third;
   Third = Temp;
  }
  if (Y == Height - 1) {
   memcpy(Third, Second, (Width +
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值