孔洞填充

/*HoleFill参数说明:
HoleFill(
Uchar* input,    输入闭运算后的边缘图像
Uchar* output,   输出空洞填充后的图像
int rowSize,     行数
int colSize      列数
)
*/
static int HoleFill(Uchar* input, Uchar* output, int rowSize, int colSize)
{
	int i = 0;//背景点坐标,需保证与整个背景连通(图像边界的边缘检测值置零可保证(0,0)为背景)
	int j = 0;
	Uchar backFlag = 0;
	Uchar targetFlag = MAXIMUM_PIXEL_VALUE;
	Uchar* closeImage = (Uchar*)malloc(rowSize * colSize  * sizeof(Uchar));
	memcpy(closeImage, input, rowSize * colSize  * sizeof(Uchar));//保留边缘图像,后续使用
	//背景填充
	BackgroundFill(input, rowSize, colSize, i, j, backFlag, targetFlag);
	//背景取反
	Uchar* antiBackground = (Uchar*)malloc(rowSize * colSize * sizeof(Uchar));
	int wide = OFF_BORDER_WIDTH;
	for (int i = wide; i < rowSize - wide; i++)
	{
		for (int j = wide; j < colSize - wide; j++)
		{	
			antiBackground[i * colSize + j] = MAXIMUM_PIXEL_VALUE - input[i * colSize + j];//和为MAXIMUM_PIXEL_VALUE
		}
	}
	//区域标记
	int* connectArea = (int*)malloc(rowSize * colSize  * sizeof(int)); //记录各区域面积
	memset(connectArea, 0, rowSize * colSize  * sizeof(int));
	//int connectArea[NUMBER_OF_PIXELS] ={};
	int areaNumber = 0;
	//对antiBackground连通区标记,1、2、3...(用四连通标记)
	ConnectivityMark(antiBackground, 4 ,connectArea, &areaNumber, rowSize, colSize, backFlag, targetFlag);
	//将大的连通区置为背景(面积大于该值区域置为背景值),以排除包层圆内部。
	//不排除包层圆未闭合(即bigAreaNum=0),此时已与大背景连通,大于该阈值的面积数为0(目前未发现此种可能)
    int areaThr =(int)( PI*estimatedRadius*estimatedRadius*0.6 ); //连通区大小阈值设置(包层圆面积为pi*estimatedRadius*estimatedRadius,AreaThr为该值一半以上即可)
	int bigAreaNum = 0;//该值正常不会超过1
	int areaValue = 0;//标记值为该值的区域面积大于areaThr 
	//areaFlag从1开始
	for (int areaFlag = 1; areaFlag <= areaNumber; areaFlag++)
	{
		if (connectArea[areaFlag]>areaThr)
		 {
			 areaValue = areaFlag;//标记为该值的区域面积太大,认为是包层圆
			 bigAreaNum = bigAreaNum + 1;
		 }
	}
	
	if (bigAreaNum>1)
	{
		printf(" Error in HoleFill :HoleFill fail \n");
		free(closeImage);
		closeImage = NULL;
		free(antiBackground);
		antiBackground = NULL;
		free(connectArea);
		connectArea = NULL;
		return -1;
	}
	for (int i = wide; i < rowSize - wide; i++)
	{
		for (int j = wide; j < colSize - wide; j++)
		{
			if (antiBackground[i * colSize + j] == areaValue)
			{
				input[i * colSize + j] = targetFlag;
			}
		}
	}
	//小孔洞填充部分
	Uchar* smallHole = (Uchar*)malloc(rowSize * colSize  * sizeof(Uchar)); 
	for (int i = wide; i < rowSize - wide; i++)
	{
		for (int j = wide; j < colSize - wide; j++)
		{
			smallHole[i * colSize + j] = MAXIMUM_PIXEL_VALUE - input[i * colSize + j];//和为MAXIMUM_PIXEL_VALUE
		}
	}
	//小孔洞填充部分与原图取或
	for (int i = wide; i < rowSize - wide; i++)
	{
		for (int j = wide; j < colSize - wide; j++)
		{
			output[i * colSize + j] = (closeImage[i * colSize + j] || smallHole[i * colSize + j])*targetFlag;
		}
	}
	free(closeImage);
	closeImage = NULL;
	free(antiBackground);
	antiBackground = NULL;
	free(connectArea);
	connectArea = NULL;
	free(smallHole);
	smallHole = NULL;
	return 0;

}

猜你喜欢

转载自blog.csdn.net/u013297911/article/details/88058019