Hough变换求圆心位置

/*HoughTransform参数说明:
HoughTransform(
Uchar* input,    输入边缘图像
IO_INFO* ioInfo, 输出:ioInfo->cirX 、ioInfo->cirY 、ioInfo->cladRadius
int halfWidth,   圆心可能区域半宽(10像素)
int rowSize,     行数
int colSize      列数
)
return -1检测圆失败,return 0检测圆成功
*/
static int HoughTransform(Uchar* input, IO_INFO* ioInfo, int halfWidth, int rowSize, int colSize)
{
	int* circleCenterDistribute = (int*)malloc(NUMBER_OF_RADIUS * rowSize * colSize * sizeof(int));
	memset(circleCenterDistribute, 0, NUMBER_OF_RADIUS * rowSize * colSize * sizeof(int));
    //int circleCenterDistribute[NUMBER_OF_RADIUS][NUMBER_OF_ROWS][NUMBER_OF_COLUMNS] = {};
	int rMin = int(estimatedRadius - NUMBER_OF_RADIUS * 0.5);                      //查找最小半径
	//int rMax = estimatedRadius + NUMBER_OF_RADIUS*0.5 - 1;                  //查找最大半径 
	int xCoordinate = 0;                //圆心X坐标
	int yCoordinate = 0;                //圆心Y坐标
	float angleStep = 0.2f * PI;        //角度步长
	//圆心可能区域的半宽,限制圆心范围进行搜索
	int xMin = preCenterX - halfWidth;
	int xMax = preCenterX + halfWidth;
	int yMin = preCenterY - halfWidth;
	int yMax = preCenterY + halfWidth;
	//霍夫变换的坐标范围
	int Xmin = xMin - estimatedRadius;
	int Xmax = xMax + estimatedRadius;
	int Ymin = yMin - estimatedRadius;
	int Ymax = yMax + estimatedRadius;
	if (Xmin<0)
	{
		Xmin = 0;
	}
	if (Xmax > colSize - 1)
	{
		Xmax = colSize - 1;
	}
	if (Ymin < 0)
	{
		Ymin = 0;
	}
	if (Ymax > rowSize - 1)
	{
		Ymax = rowSize - 1;
	}
	// 霍夫变换
	for (int k = 0; k < NUMBER_OF_RADIUS; k++)
	{
		for (int i = Ymin; i <= Ymax; i++)
		{
			for (int j = Xmin; j <= Xmax; j++)
			{
				for (float angle = 0; angle < 2 * PI; angle += angleStep)
				{
					if (input[i * colSize + j] > 0)//边缘
					{
						xCoordinate = (int)roundf(j - (k + rMin)*cosf(angle));
						yCoordinate = (int)roundf(i - (k + rMin)*sinf(angle));
						//根据开始粗略估计圆心位置(preCenterY,preCenterX),限制圆心范围						
						if ((xCoordinate >= 0) && (xCoordinate >= xMin) && (xCoordinate < colSize) && (xCoordinate < xMax)
							&& (yCoordinate >= 0) && (yCoordinate >= yMin) && (yCoordinate < rowSize) && (yCoordinate < yMax))
						{
							//circleCenterDistribute[k][yCoordinate][xCoordinate] += 1;
							circleCenterDistribute[k * rowSize * colSize + yCoordinate* colSize + xCoordinate] += 1;
						}
					}
				}
			}
		}
	}
	//寻找圆心
	int MaxValue = 0;
	for (int k = 0; k < NUMBER_OF_RADIUS; k++)
	{
		for (int i = yMin; i < yMax; i++)
		{
			for (int j = xMin; j < xMax; j++)
			{
				if (circleCenterDistribute[k * rowSize * colSize + i * colSize + j] > MaxValue)
				{
					//MaxValue = circleCenterDistribute[k][i][j];
					MaxValue = circleCenterDistribute[k * rowSize * colSize + i * colSize + j];
					ioInfo->cirY = i;
					ioInfo->cirX = j;
					ioInfo->cladRadius = rMin + k;
				}
			}
		}
	}
	//通过计算边缘在霍夫圆上的点数,判断是否正确检测到圆
	int wide = OFF_BORDER_WIDTH;
	float halfWidth = 1;//圆的半宽(0.5(400+)or 1(580+))
	int numberOfCirpoints = 0;
	for (int i = wide; i < rowSize - wide; i++)
	{
		for (int j = wide; j < colSize - wide; j++)
		{
			if (input[i * colSize + j]>0)
			{
				int d = (i - ioInfo->cirY) * (i - ioInfo->cirY) + (j - ioInfo->cirX) * (j - ioInfo->cirX);//点到圆心距离的平方
				if (((ioInfo->cladRadius - halfWidth) * (ioInfo->cladRadius - halfWidth) <= d ) & (d <= (ioInfo->cladRadius + halfWidth) * (ioInfo->cladRadius + halfWidth)))
				{
					numberOfCirpoints = numberOfCirpoints + 1;
				}
			}
		}
	}
	if (numberOfCirpoints<NUMBER_OF_CIRPOINT)//判断检测圆是否成功
	{
		printf("HoughTransform: Detection circle failed");
		free(circleCenterDistribute);
		circleCenterDistribute = NULL;
		return -1;
	}
	free(circleCenterDistribute);
	circleCenterDistribute = NULL;
	return 0;
}

猜你喜欢

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