// 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 ); } }
// 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)); }