/*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
今日推荐
周排行