边缘检测一直是图像处理中比较热门的一块,今天简单实现了下sobel算法。先上图:
原图:
Sobel处理---彩图:
Sobel处理--灰度图:
可以看到在不复杂的情况下,Sobel能很好的检测到边缘。
Sobel算法的原理简单理解下:根据像素点上下、左右邻点灰度加权差,在边缘处达到极值这一现象检测边缘。可以理解为在原图像的基础上只保留像素变化比较大的地方,也就形成了边缘。因为Sobel算子结合了高斯平滑和微分求导(分化),因此结果会具有更多的抗噪性,当对精度要求不是很高时,Sobel算子是一种较为常用的边缘检测方法。
一般使用的模板为下(借用一下别人的图):
实现方式为分别对图像的x方向和y方向进行平面卷积,最后通过以下公式来确定该点的灰度值:
代码:
#include <iostream>
#define IMAGE_WIDTH 1920
#define IMAGE_HEIGHT 1080
int LimitValue(int val)
{
if (val < 0)
val = 0;
else if (val > 255)
val = 255;
return val;
}
int main()
{
FILE* fp = fopen("D:/test/4.yuv", "rb");
if (NULL == fp)
{
printf("Can not open image file!\n");
return -1;
}
fseek(fp, 0, SEEK_END);
int len = ftell(fp);
fseek(fp, 0, SEEK_SET);
unsigned char* inputImage = new unsigned char[len]();
unsigned char* outputImage = new unsigned char[len]();
fread(inputImage, 1, len, fp);
fclose(fp);
memcpy(outputImage, inputImage, len);
for (int i = 1; i < IMAGE_HEIGHT - 1; i++)
{
for (int j = 1; j < IMAGE_WIDTH - 1; j++)
{
unsigned char imageKernel[9] = { 0 };
imageKernel[0] = inputImage[(i - 1)*IMAGE_WIDTH + j - 1];
imageKernel[1] = inputImage[(i - 1)*IMAGE_WIDTH + j];
imageKernel[2] = inputImage[(i - 1)*IMAGE_WIDTH + j + 1];
imageKernel[3] = inputImage[(i)*IMAGE_WIDTH + j - 1];
imageKernel[4] = inputImage[(i)*IMAGE_WIDTH + j];
imageKernel[5] = inputImage[(i)*IMAGE_WIDTH + j + 1];
imageKernel[6] = inputImage[(i + 1)*IMAGE_WIDTH + j - 1];
imageKernel[7] = inputImage[(i + 1)*IMAGE_WIDTH + j];
imageKernel[8] = inputImage[(i + 1)*IMAGE_WIDTH + j + 1];
//化简后结果 这里使用了 1,1.414,1 的模板(各向同性Sobel算子),与 1,2,1的模板区别不是很大
float GX = imageKernel[2] - imageKernel[0] + (imageKernel[5] - imageKernel[3]) * 1.414 + imageKernel[8] - imageKernel[6];
float GY = imageKernel[0] + imageKernel[2] + (imageKernel[1] - imageKernel[7]) * 1.414 - imageKernel[6] - imageKernel[8];
int val = LimitValue(sqrt(GX*GX + GY*GY) + 0.5);
outputImage[i*IMAGE_WIDTH + j] = val;
}
}
fp = fopen("D:/test/out.yuv", "wb+");
fwrite(outputImage, 1, len, fp);
fclose(fp);
delete[] inputImage;
delete[] outputImage;
return 0;
}
图片链接: 百度网盘链接 提取码: w3af