// Identify the peaks of votes (most significant straight lines) in the accmulator.
void
peak_detection(lines_list_t &lines, const accumulator_t &accumulator)
{
	/* Leandro A. F. Fernandes, Manuel M. Oliveira
	 * Real-time line detection through an improved Hough transform voting scheme
	 * Pattern Recognition (PR), Elsevier, 41:1, 2008, 299-314.
	 *
	 * Section 3.4
	 */

	const int **bins = accumulator.bins();
	const double *rho = accumulator.rho();
	const double *theta = accumulator.theta();

	// Create a list with all cells that receive at least one vote.
	static bins_list_t used_bins;
	
	size_t used_bins_count = 0;
	for (size_t theta_index=1, theta_end=accumulator.height()+1; theta_index!=theta_end; ++theta_index)
	{
		for (size_t rho_index=1, rho_end=accumulator.width()+1; rho_index!=rho_end; ++rho_index)
		{
			if (bins[theta_index][rho_index])
			{
				used_bins_count++;
			}
		}
	}
	used_bins.resize( used_bins_count );
		
	for (size_t theta_index=1, i=0, theta_end=accumulator.height()+1; theta_index!=theta_end; ++theta_index)
	{
		for (size_t rho_index=1, rho_end=accumulator.width()+1; rho_index!=rho_end; ++rho_index)
		{
			if (bins[theta_index][rho_index])
			{
				bin_t &bin = used_bins[i];

				bin.rho_index = rho_index;
				bin.theta_index = theta_index;
				bin.votes = convolution( bins, rho_index, theta_index ); // Convolution of the cells with a 3x3 Gaussian kernel

				i++;
			}
		}
	}
	
	// Sort the list in descending order according to the result of the convolution.
	std::qsort( used_bins.items(), used_bins_count, sizeof( bin_t ), (int(*)(const void*, const void*))compare_bins );
	
	// Use a sweep plane that visits each cell of the list.
	static visited_map_t visited;
	visited.init( accumulator.width(), accumulator.height() );

	lines.clear();
	lines.reserve( used_bins_count );

	for (size_t i=0; i!=used_bins_count; ++i)
	{
		bin_t &bin = used_bins[i];

		if (!visited.visited_neighbour( bin.rho_index, bin.theta_index ))
		{
			line_t &line = lines.push_back();
			
			line.rho = rho[bin.rho_index];
			line.theta = theta[bin.theta_index];
		}
		visited.set_visited( bin.rho_index, bin.theta_index );
	}
}
Esempio n. 2
0
// This function complements the proposed voting process.
inline
void
vote(accumulator_t &accumulator, size_t rho_start_index, const size_t theta_start_index, const double rho_start, const double theta_start, int inc_rho_index, const int inc_theta_index, const double sigma2_rho, const double sigma2_theta, const double sigma_rho_theta, const double scale)
{
	/* Leandro A. F. Fernandes, Manuel M. Oliveira
	 * Real-time line detection through an improved Hough transform voting scheme
	 * Pattern Recognition (PR), Elsevier, 41:1, 2008, 299-314.
	 *
	 * Algorithm 4
	 */

	int **bins = accumulator.bins();
	
	const size_t rho_size = accumulator.width(), theta_size = accumulator.height();
	const double delta = accumulator.delta();
	const double inc_rho = delta * inc_rho_index, inc_theta = delta * inc_theta_index;
		
	const double sigma_rho_sigma_theta = sqrt( sigma2_rho ) * sqrt( sigma2_theta );
	const double r = (sigma_rho_theta / sigma_rho_sigma_theta), two_r = 2.0 * r;
	const double a = 1.0 / (2.0 * pi * sigma_rho_sigma_theta * sqrt( 1.0 - (r * r) ));
	const double b = 1.0 / (2.0 * (1.0 - (r * r)));

	bool theta_voted;
	double rho, theta;
	int votes, theta_not_voted = 0;
	size_t rho_index, theta_index, theta_count = 0;
	
	// Loop for the theta coordinates of the parameter space.
	theta_index = theta_start_index;
	theta = theta_start;
	do
	{
		// Test if the kernel exceeds the parameter space limits.
		if ((theta_index == 0) || (theta_index == (theta_size + 1)))
		{
			rho_start_index = rho_size - rho_start_index + 1;
			theta_index = (theta_index == 0) ? theta_size : 1;
			inc_rho_index = -inc_rho_index;
		}

		// Loop for the rho coordinates of the parameter space.
		theta_voted = false;

		rho_index = rho_start_index;
		rho = rho_start;
		while (((votes = static_cast<int>( (gauss( rho, theta, sigma2_rho, sigma2_theta, sigma_rho_sigma_theta, two_r, a, b ) * scale) + 0.5 )) > 0) && (rho_index >= 1) && (rho_index <= rho_size))
		{
			bins[theta_index][rho_index] += votes;
			theta_voted = true;

			rho_index += inc_rho_index;
			rho += inc_rho;
		}

		if (!theta_voted)
		{
			theta_not_voted++;
		}

		theta_index += inc_theta_index;
		theta += inc_theta;
		theta_count++;
	}
	while ((theta_not_voted != 2) && (theta_count < theta_size));
}