基于easyx的简单图像处理 二(C语言)

 这篇主要写图像的二值化处理,图像二值化是指将图像的像素点只有两种情况,0和255,基本思路是先将图像灰度化,这里就不详细讲解了,在我的上一篇里有详细代码,接下来就是对灰度图像的处理。现在从最简单的情况开始,二值化就是要选取一个阈值,这里打个比方阈值是200,灰度值大于200的灰度值令为255,灰度值小于200的令其灰度值为0。

这里我先给出最简单的代码,这里的阈值是凭自己的感觉设置的:

#include <graphics.h>
#include <conio.h>
#include <stdio.h>
#include <math.h>
int image[1500][1000];
IMAGE img1;
int imagHight,imagWidth;
int threshold = 0;//阈值
int main()
{
	int i,j,k;
	// 读取图片至绘图窗口
	loadimage(&img1, _T("D:\\testh.bmp"));
	imagHight = img1.getheight();
	imagWidth = img1.getwidth();
	total = imagHight*imagWidth;
	initgraph(imagWidth,imagHight, SHOWCONSOLE|NOCLOSE|NOMINIMIZE);
    putimage(0, 0, &img1);
	DWORD* pMem = GetImageBuffer();

	//图像灰度化
	for(i = 0; i <imagHight; i++)
	{
		for(j=0;j<imagWidth;j++)
	  {
	   *pMem = BGR(*pMem);
	   image[i][j]  = (GetRValue(*pMem)*299+GetGValue(*pMem)*587+GetBValue(*pMem)*114+500)/1000;  
	   *pMem = RGB(image[i][j],image[i][j],image[i][j]);
	   pMem++;
		}
	}
	 pMem -= imagHight*imagWidth; //将指针重新指向第一个像素点
	
    //二值化
	for(i = 0; i <imagHight; i++)
	{
		for(j=0;j<imagWidth;j++)
	  {
	     if(image[i][j]>200)image[i][j] = 255;
		 else image[i][j] = 0;
		 *pMem = RGB(image[i][j],image[i][j],image[i][j]);
	      pMem++;
	  }
	}
	FlushBatchDraw();
    _getch();
	closegraph();
}

效果图如下:

原图

阈值为200

 if(image[i][j]>200)image[i][j] = 255;

这里把上面的200阈值改为50,可以看到,大部分的灰度都大于50,所以图像大部分是白色的(灰度值为255)。

 这里也看出阈值选取的重要性,不同的阈值,前景与背景的分离程度是不同的,如何选取最合适的阈值是二值化的关键。

 于是我研究了一下otsu二值算法,也叫大津算法,这里我参考了这篇文章,大家可以看一下,里面还是比较容易看懂的。             https://blog.csdn.net/qingzhuyuxian/article/details/88819810#commentBox

这里是我自己写的程序:

#include <graphics.h>
#include <conio.h>
#include <stdio.h>
#include <math.h>
int image[1500][1000];
int Histogram[256]={0};
IMAGE img1;
int imagHight,imagWidth;
double total;//像素点的总数
double variances[256];//每个阈值对应的组内方差
double bvariances;//背景的方差
double fvariances;//前景的方差
double bproportion;//背景的像素点占的比例
double fproportion;//前景的像素点占的比例
double count;//用来记录像素点的个数
double bmean;//背景的平均值
double fmean;//前景的平均值
double min_value;//最小的方差
int threshold = 0;//阈值
int main()
{
	int i,j,k;
	// 读取图片至绘图窗口
	loadimage(&img1, _T("D:\\testh.bmp"));
	imagHight = img1.getheight();
	imagWidth = img1.getwidth();
	total = imagHight*imagWidth;
	initgraph(imagWidth,imagHight, SHOWCONSOLE|NOCLOSE|NOMINIMIZE);
    putimage(0, 0, &img1);
	DWORD* pMem = GetImageBuffer();
	_getch();
	//图像灰度化
	for(i = 0; i <imagHight; i++)
	{
		for(j=0;j<imagWidth;j++)
	  {
	   *pMem = BGR(*pMem);
	   image[i][j]  = (GetRValue(*pMem)*299+GetGValue(*pMem)*587+GetBValue(*pMem)*114+500)/1000;  
	   *pMem = RGB(image[i][j],image[i][j],image[i][j]);
	   pMem++;
		}
	}
	 pMem -= imagHight*imagWidth; //将指针重新指向第一个像素点

	//获取直方图

	for(i = 0; i <imagHight; i++)
    {
	 for(j=0;j<imagWidth;j++)
	  {
	     Histogram[image[i][j]]++; 
	  }
	}

	//求组内方差最小的那个阈值
	for(i=0;i<256;i++) //从阈值为0到255 分别计算对应的组内方差
	{
		count = 0;
		bmean = 0;
		bproportion = 0;
		bvariances = 0;
		for(j=0;j<i;j++)
		{
			 count += Histogram[j]; 
			 bmean = Histogram[j]*j;
		}
		bproportion = count / total;
		bmean = (count==0)?0:(bmean/count);
		for(k=0;k<i;k++)
		{
			bvariances += pow(k-bmean,2)*Histogram[k]; 
		}

		bvariances = (count==0)?0:bvariances / count;

		count = 0;
		fmean = 0;
		fproportion = 0;
		fvariances = 0;

		for(j=i;j<256;j++)
		{
			 count += Histogram[j]; 
			 fmean = Histogram[j]*j;
		}
		fproportion = count / total;
		fmean = (count==0)?0:(fmean/count);
		for(k=i;k<256;k++)
		{
			fvariances += pow(k-fmean,2)*Histogram[k]; 
		}

		fvariances = (count==0)?0:fvariances / count;

		variances[i] = bproportion * bvariances + fproportion * fvariances;
	}

	//找到最小方差值对应的那个阈值
	min_value = variances[0];
	for(i=1;i<256;i++)
	{
		if(min_value>variances[i])
		{
			min_value = variances[i];
			threshold = i;
		}
	}
	
	printf("threshold:%d",threshold); //打印最佳阈值
    //二值化
	for(i = 0; i <imagHight; i++)
	{
		for(j=0;j<imagWidth;j++)
	  {
	     if(image[i][j]>threshold)image[i][j] = 255;
		 else image[i][j] = 0;
		 *pMem = RGB(image[i][j],image[i][j],image[i][j]);
	      pMem++;
	  }
	}
	FlushBatchDraw();
    _getch();
	closegraph();
}

效果图:

这里计算出的阈值是185

还有其他的求阈值的方法,这里就不列出来了,感兴趣的自己可以查一下。

发布了7 篇原创文章 · 获赞 13 · 访问量 2096

猜你喜欢

转载自blog.csdn.net/qq_39036834/article/details/97750403