计算机视觉边缘检测实验报告,ARCore之路-计算机视觉之边缘检测

边缘检测是图像处理和计算机视觉中的基本问题,边缘检测的目的是标识数字图像中变化明显的点。图像属性中的显著变化通常反映了属性的重要事件和变化,这些包括深度上的不连续、表面方向不连续、物质属性变化和场景照明变化, 边缘检测大幅度地减少了数据量,并且剔除了可以认为不相关的信息,保留了图像重要的结构属性。常用的描边也是先进行边缘然后再进行边缘处理。

一、卷积

卷积(Convolution)本质上来讲就是一种数学运算,跟减加乘除没有区别。在图像处理中用一个模板(这个模板就是卷积核(kernel))和一幅图像进行卷积,对于图像上的一个点,让模板的原点和该点重合,然后模板上的点和图像上对应的点相乘,最后将各点的积相加,就得到该点的卷积值。然后移动模板对正下一个点,对图像上的每个点都这样处理。卷积是一种积分运算,可以看作加权求和,可以用来消除噪声、特征增强, 把一个点的像素值用它周围的点的像素值的加权平均代替。

卷积核通常是一个四方形风格结构(如2x2、3x3),该网格区域内的每一个方格都有一个权重值。当对图像中的某个像素进行卷积时,我们会把卷积核的中心放置于该像素上,如下图所示,翻转核之后再依次计算核中每个元素和其覆盖的图像像素值的乘积,最后将各乘积累加,得到的结果就是该像素的新像素值。然后移动卷积核到下一个像素,进行同样的处理,至到所有像素都处理完。  卷积听起来很难,在图形处理中其实就这么简单,但卷积可以实现很多常见的图像处理效果,例如图像模糊、边缘检测等等。

二、sobel算子

卷积的神奇之处在于选择的卷积核,用于边缘检测的卷积核也叫边缘检测算子,先后有好几种边缘检测算子被提出来。Roberts算子   Roberts算子采用对角线方向相邻两像素之差近似梯度幅值检测边缘。检测水平和垂直边缘的效果好于斜向边缘,定位精度高,但对噪声敏感。Prewitt算子

Prewitt算子利用像素点上下、左右邻点灰度差,在边缘处达到极值检测边缘。对噪声具有平滑作用,但是定位精度不够高。Sobel算子

Sobel 算子主要用作边缘检测,它是一个离散的一阶差分算子,用来计算图像亮度函数的一阶梯度之近似值。在图像的任何一点使用此算子,将会产生该点对应的梯度矢量或是其法矢量。与Prewitt算子相比,Sobel算子对于像素的位置的影响做了加权,可以降低边缘模糊程度,因此效果更好。

该算子包含两组3x3的矩阵,分别为横向及纵向,将之与图像作平面卷积,即可分别得出横向及纵向的亮度差分近似值。如果以A代表原始图像,Gx及Gy分别代表经横向及纵向边缘检测的图像灰度值,其公式如下:

具体计算如下:Gx = (-1)*f(x-1, y-1) + 0*f(x,y-1) + 1*f(x+1,y-1)

+(-2)*f(x-1,y) + 0*f(x,y)+2*f(x+1,y)

+(-1)*f(x-1,y+1) + 0*f(x,y+1) + 1*f(x+1,y+1)

= [f(x+1,y-1)+2*f(x+1,y)+f(x+1,y+1)]-[f(x-1,y-1)+2*f(x-1,y)+f(x-1,y+1)]

Gy =1* f(x-1, y-1) + 2*f(x,y-1)+ 1*f(x+1,y-1)

+0*f(x-1,y) 0*f(x,y) + 0*f(x+1,y)

+(-1)*f(x-1,y+1) + (-2)*f(x,y+1) + (-1)*f(x+1, y+1)

= [f(x-1,y-1) + 2f(x,y-1) + f(x+1,y-1)]-[f(x-1, y+1) + 2*f(x,y+1)+f(x+1,y+1)]

其中f(a,b), 表示图像(a,b)点的灰度值;

图像的每一个像素的横向及纵向灰度值通过以下公式结合,来计算该点灰度的大小:

G=Gx2+Gy2​

通常,为了提高效率 使用不开平方的近似值:

G=∣Gx∣+∣Gy∣

如果梯度G大于某一阀值则认为该点(x,y)为边缘点。Sobel算子根据像素点上下、左右邻点灰度加权差,在边缘处达到极值这一现象检测边缘。对噪声具有平滑作用,提供较为精确的边缘方向信息,边缘定位精度不够高。当对精度要求不是很高时,是一种较为常用的边缘检测方法。

Sobel算子的计算速度比Roberts算子慢,但其较大的卷积核在很大程度上平滑了输入图像,使算子对噪声的敏感性降低。与Roberts算子相比,通常也会为相似的边缘产生更高的输出值。与Roberts算子一样,操作时输出值很容易溢出仅支持小整数像素值(例如8位整数图像)的图像类型的最大允许像素值。当发生这种情况时,标准做法是简单地将溢出的输出像素设置为最大允许值。通过使用支持范围更大的像素值的图像类型,可以避免此问题。

三、ARCore计算机视觉示例

打开ARCore SDK自带的Computer vision示例。  在Hierarchy窗口中选中ComputerVisionController,在Inspector窗口中双击编辑ComputerVisionController.cs脚本。先不管其他辅助操作的功能如获取摄像头图像、显示信息等,我们直接查看EdgeDetector.Detect()方法,这里采用的边缘检测就是使用的Sobel算子卷积。private static void Sobel(byte[] outputImage, IntPtr inputImage, int width, int height, int rowStride)

{

// Adjust buffer size if necessary.

int bufferSize = rowStride * height;

if (bufferSize != s_ImageBufferSize || s_ImageBuffer.Length == 0)

{

s_ImageBufferSize = bufferSize;

s_ImageBuffer = new byte[bufferSize];

}

// Move raw data into managed buffer.

System.Runtime.InteropServices.Marshal.Copy(inputImage, s_ImageBuffer, 0, bufferSize);

// 边缘检测的阈值

int threshold = 128 * 128;

for (int j = 1; j < height - 1; j++)

{

for (int i = 1; i < width - 1; i++)

{

// Offset of the pixel at [i, j] of the input image.

int offset = (j * rowStride) + i;

// Neighbour pixels around the pixel at [i, j].

int a00 = s_ImageBuffer[offset - rowStride - 1];

int a01 = s_ImageBuffer[offset - rowStride];

int a02 = s_ImageBuffer[offset - rowStride + 1];

int a10 = s_ImageBuffer[offset - 1];

int a12 = s_ImageBuffer[offset + 1];

int a20 = s_ImageBuffer[offset + rowStride - 1];

int a21 = s_ImageBuffer[offset + rowStride];

int a22 = s_ImageBuffer[offset + rowStride + 1];

int xSum = -a00 - (2 * a10) - a20 + a02 + (2 * a12) + a22;

int ySum = a00 + (2 * a01) + a02 - a20 - (2 * a21) - a22;

if ((xSum * xSum) + (ySum * ySum) > threshold)

{

outputImage[(j * width) + i] = 0xFF; //是边缘则输出纯白

}

else

{

outputImage[(j * width) + i] = 0x1F; //不是边缘则输出黑色

}

}

}

}

通过之前的讲解,我们应该很容易理解这段代码,使用sobel算子做边缘检测的效果如下图所示:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值