图像处理-Sobel边缘检测(C++实现,不依赖opencv)

边缘检测一直是图像处理中比较热门的一块,今天简单实现了下sobel算法。先上图:

原图:

Sobel处理---彩图:
图像处理-Sobel边缘检测(C++实现,不依赖opencv)_第1张图片

Sobel处理--灰度图:

可以看到在不复杂的情况下,Sobel能很好的检测到边缘。

 

Sobel算法的原理简单理解下:根据像素点上下、左右邻点灰度加权差,在边缘处达到极值这一现象检测边缘。可以理解为在原图像的基础上只保留像素变化比较大的地方,也就形成了边缘。因为Sobel算子结合了高斯平滑和微分求导(分化),因此结果会具有更多的抗噪性,当对精度要求不是很高时,Sobel算子是一种较为常用的边缘检测方法。

一般使用的模板为下(借用一下别人的图): 

 实现方式为分别对图像的x方向和y方向进行平面卷积,最后通过以下公式来确定该点的灰度值:
图像处理-Sobel边缘检测(C++实现,不依赖opencv)_第2张图片

代码:

#include 

#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

 

你可能感兴趣的:(图像处理)