Simple image processing based on easyx 2 (C language)

 This article mainly writes the image binarization processing. Image binarization refers to only two cases of image pixels, 0 and 255. The basic idea is to grayscale the image first. In the previous article, there are detailed codes, and the next step is to process grayscale images. Now from the simplest case, binarization is to choose a threshold. Here, for example, the threshold is 200. The gray value greater than 200 is set to 255, and the gray value less than 200 is set to gray 0.

Here I give the simplest code first, the threshold here is set according to my own feeling:

#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();
}

The effect chart is as follows:

Original image

Threshold is 200

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

Here, the 200 threshold above is changed to 50. It can be seen that most of the grayscales are greater than 50, so most of the images are white (grayscale value is 255).

 Here we also see the importance of threshold selection, different thresholds, the degree of separation of foreground and background are different, how to choose the most appropriate threshold is the key to binarization.

 So I researched the otsu binary algorithm, also known as the Otsu algorithm. Here I refer to this article, you can take a look, it is still relatively easy to understand.             https://blog.csdn.net/qingzhuyuxian/article/details/88819810#commentBox

 

Here is the program I wrote myself:

#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();
}

Effect picture:

The threshold calculated here is 185

 

There are other ways to find the threshold, which are not listed here, you can check it if you are interested.

Published 7 original articles · won 13 · views 2096

Guess you like

Origin blog.csdn.net/qq_39036834/article/details/97750403