MASH logo
Login | Register

cdubout/hough/3

User avatar

Core team

Author:
cdubout
Upload date:
April 20, 2010, 12:35 p.m.
Status:
Enabled
Summary:
Computes the linear Hough transform of the region of interest to detect lines.
Description:

Weighted Hough transform using the magnitude of the gradient (as given by a Sobel filter). Discretizes the theta parameter in 36 bins (from -90 to +85 degrees) and rho (the distance to the center, in the range +- sqrt(2) * roi_extent) in roi_size bins.

Evaluation:
Configuration Training error ( sd ) Test error ( sd )
adaboost-caltech 69.22% (1.4471) 73.97% (1.3349)
perceptron-mnist 4.09% (0.0534) 8.61% (0.325)
/** Author: Charles Dubout (charles.dubout@idiap.ch)
 *
 *  Hough transform heuristic (weighted). Compute the linear hough transform of
 *  the region of interest to detect lines. Discretize the theta parameter in 36
 *  bins (from -90 to +85 degrees) and rho (the distance to the center, in the
 *  range +- sqrt(2) * roi_extent) in roi_size bins.
 */

#include <mash/heuristic.h>

#include <algorithm>
#include <cmath>
#include <numeric>
#include <vector>

using namespace Mash;

//------------------------------------------------------------------------------
/// The 'Hough' heuristic class
//------------------------------------------------------------------------------
class HoughHeuristic : public Heuristic {
    //_____ Implementation of Heuristic __________
public:
    HoughHeuristic();
    virtual unsigned int dim();
    virtual void prepareForCoordinates();
    virtual scalar_t computeFeature(unsigned int feature_index);

private:
    // The hough matrix of features
    std::vector<scalar_t> features_;

    // Lookup tables of sines and cosines
    scalar_t sines_[36];
    scalar_t cosines_[36];
};

//------------------------------------------------------------------------------
/// Creation function of the heuristic
//------------------------------------------------------------------------------
extern "C" Heuristic* new_heuristic() {
    return new HoughHeuristic();
}

/************************* IMPLEMENTATION OF Heuristic ************************/

HoughHeuristic::HoughHeuristic() {
    for(int t = 0; t < 36; ++t) {
        // Convert to radian (from -90 to +85 degrees)
        scalar_t theta = (t - 18) * scalar_t(3.141592653589793) / 36;

        // Predivide by sqrt(2) so that we won't have to divide later
        sines_[t]   = std::sin(theta) / scalar_t(1.414213562);
        cosines_[t] = std::cos(theta) / scalar_t(1.414213562);
    }
}

unsigned int HoughHeuristic::dim() {
    // We have 36 * roi_size features
    int roi_size = roi_extent * 2 + 1;
    return 36 * roi_size;
}

void HoughHeuristic::prepareForCoordinates() {
    // Compute the coordinates of the top-left pixel of the region of interest
    int x0 = coordinates.x - roi_extent;
    int y0 = coordinates.y - roi_extent;

    // Compute the size of the region of interest
    int roi_size = roi_extent * 2 + 1;

    // Get the pixels values of the region of interest
    byte_t** pLines = image->grayLines();

    // Resize the features to the correct dimension
    features_.clear();
    features_.resize(dim());

    for(int y = 1; y < roi_size - 1; ++y) {
        for(int x = 1; x < roi_size - 1; ++x) {
            // Sobel filter
            int dx = -     (int)pLines[y0 + y - 1][x0 + x - 1]
                     - 2 * (int)pLines[y0 + y    ][x0 + x - 1]
                     -     (int)pLines[y0 + y + 1][x0 + x - 1]
                     +     (int)pLines[y0 + y - 1][x0 + x + 1]
                     + 2 * (int)pLines[y0 + y    ][x0 + x + 1]
                     +     (int)pLines[y0 + y + 1][x0 + x + 1];
            int dy = -     (int)pLines[y0 + y - 1][x0 + x - 1]
                     - 2 * (int)pLines[y0 + y - 1][x0 + x    ]
                     -     (int)pLines[y0 + y - 1][x0 + x + 1]
                     +     (int)pLines[y0 + y + 1][x0 + x - 1]
                     + 2 * (int)pLines[y0 + y + 1][x0 + x    ]
                     +     (int)pLines[y0 + y + 1][x0 + x + 1];

            // Compute the magnitude
            scalar_t magnitude = std::sqrt(scalar_t(dx * dx + dy * dy));

            if(magnitude > 0) {
                // For every possible theta
                for(int t = 0; t < 36; ++t) {
                    // Calculate rho (rho is in the range [0, 2 * roi_extent])
                    scalar_t rho = (x - (int)roi_extent) * cosines_[t] +
                                   (y - (int)roi_extent) * sines_[t] +
                                   roi_extent;

                    // Increment the rho/theta pair in the feature matrix by the
                    // magnitude of the edge

                    // Bilinear interpolation
                    int before = (int)rho;
                    int after = before + 1;
                    scalar_t alpha = rho - before;

                    features_[before * 36 + t] += (1 - alpha) * magnitude;
                    features_[after  * 36 + t] +=      alpha  * magnitude;
                }
            }
        }
    }
}

scalar_t HoughHeuristic::computeFeature(unsigned int feature_index) {
    return features_[feature_index];
}