Sobel算子,也叫Sobel-Feldman算子或Sobel滤波,常用于图像处理领域中的边缘检测。用学术的语言来说,它是一种离散的微分算子,用于计算图像亮度的梯度近似值。简单来说,Sobel算子可看作为一种固定的滤波核,对整幅图进行滤波操作。
Sobel算子分为水平方向和垂直方向,两者不一样,分别记为Gx和Gy,则Gx和Gy的值如下所示:
假设输入图像A,A图像如下所示:
以图像A中的像素值为12的点为例,则该点水平方向和垂直方向的Sobel运算结果分别记为Px和Py,则运算过程如下所示:
OpenCV中代码实现及其调用格式如下:
Mat src = imread("../ORB_DBoW2/lenna.jpg", 0);
imshow("src", src);
cvWaitKey(0);
Mat gx, gy;
Sobel(src, gx, CV_16S, 1, 0);
Sobel(src, gy, CV_16S, 0, 1);
convertScaleAbs(gx, gx);
imshow("gx", gx);
cvWaitKey(0);
convertScaleAbs(gy, gy);
imshow("gy", gy);
cvWaitKey(0);
OpenCV的效果如下图所示:
C语言实现的代码如下:
int ComputerSobel(unsigned char *pSrc, int nWidth, int nHeight, int nChannel, short *pSobelX, short *pSobelY)
{
int nRow, nCol, nVer, nHor, nSumX, nSumY, nIndex;
const int nKernelSize = 3;
int nHalfKernel = nKernelSize / 2;
int nCentKernel = nKernelSize * nKernelSize / 2;
/*水平方向和垂直方向的核*/
int pKernelX[nKernelSize * nKernelSize] = { -1, 0, 1, -2, 0, 2, -1, 0, 1};
int pKernelY[nKernelSize * nKernelSize] = { -1, -2, -1, 0, 0, 0, 1, 2, 1};
if (NULL == pSrc || 1 != nChannel)
{
return -1;
}
if (NULL != pSobelX)
{
memset(pSobelX, 0, sizeof(short) * nHeight * nWidth);
}
if (NULL != pSobelY)
{
memset(pSobelY, 0, sizeof(short) * nHeight * nWidth);
}
/*计算sobel算子结果*/
for (nRow = 1; nRow < nHeight - 1; nRow++)
{
for (nCol = 1; nCol < nWidth - 1; nCol++)
{
nSumX = 0;
nSumY = 0;
for (nVer = -nHalfKernel; nVer < nHalfKernel + 1; nVer++)
{
for (nHor = -nHalfKernel; nHor < nHalfKernel + 1; nHor++)
{
nIndex = (nRow + nVer) * nWidth + nCol + nHor;
nSumX += pSrc[nIndex] * pKernelX[nVer * nKernelSize + nCentKernel + nHor];
nSumY += pSrc[nIndex] * pKernelY[nVer * nKernelSize + nCentKernel + nHor];
}
}
nIndex = nRow * nWidth + nCol;
if (NULL != pSobelX)
{
pSobelX[nIndex] = nSumX;
}
if (NULL != pSobelY)
{
pSobelY[nIndex] = nSumY;
}
}
}
return 0;
}