Esempio n. 1
0
void DS3231::setDateTime(const char* date, const char* time)
{
    uint16_t year;
    uint8_t month;
    uint8_t day;
    uint8_t hour;
    uint8_t minute;
    uint8_t second;

    year = conv2d(date + 9);

    switch (date[0])
    {
        case 'J': month = date[1] == 'a' ? 1 : month = date[2] == 'n' ? 6 : 7; break;
        case 'F': month = 2; break;
        case 'A': month = date[2] == 'r' ? 4 : 8; break;
        case 'M': month = date[2] == 'r' ? 3 : 5; break;
        case 'S': month = 9; break;
        case 'O': month = 10; break;
        case 'N': month = 11; break;
        case 'D': month = 12; break;
    }

    day = conv2d(date + 4);
    hour = conv2d(time);
    minute = conv2d(time + 3);
    second = conv2d(time + 6);

    setDateTime(year+2000, month, day, hour, minute, second);
}
Esempio n. 2
0
// A convenient constructor for using "the compiler's time":
//   DateTime now (__DATE__, __TIME__);
// NOTE: using PSTR would further reduce the RAM footprint
DateTime::DateTime (const char* date, const char* time) {
    // sample input: date = "Dec 26 2009", time = "12:34:56"
    yOff = conv2d(date + 9);
    // Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
    switch (date[0]) {
    case 'J':
        m = date[1] == 'a' ? 1 : m = date[2] == 'n' ? 6 : 7;
        break;
    case 'F':
        m = 2;
        break;
    case 'A':
        m = date[2] == 'r' ? 4 : 8;
        break;
    case 'M':
        m = date[2] == 'r' ? 3 : 5;
        break;
    case 'S':
        m = 9;
        break;
    case 'O':
        m = 10;
        break;
    case 'N':
        m = 11;
        break;
    case 'D':
        m = 12;
        break;
    }
    d = conv2d(date + 4);
    hh = conv2d(time);
    mm = conv2d(time + 3);
    ss = conv2d(time + 6);
}
Esempio n. 3
0
void RTCDue::setTime (const char* time)
{
  _hour   = conv2d(time);
  _minute = conv2d(time + 3);
  _second = conv2d(time + 6);
  
  RTC_SetTime (RTC, _hour, _minute, _second);
}
// Marr-Hildreth edge detector with Gaussian and Laplacian kernels
// inputs:
//            float *input           -    pointer to input image
//            int w, int h           -    width and height of input image
//            float sigma            -    gaussian standard deviation
//            int n                  -    kernel size
//            float tzc              -    threshold in zero-crossing
//            int padding_method     -    padding method for convolution
// output:
//            float *                -    pointer to output image
float *edges_mh(float *im, int w, int h,
                float sigma, int n, float tzc, int padding_method) {

    // generate Gaussian kernel
    float *kernel = gaussian_kernel(n,sigma);

    // smooth input image with the Gaussian kernel
    float *im_smoothed = conv2d(im, w, h, kernel, n, padding_method);

    // compute Laplacian of the smoothed image using a 3x3 operator
    float operator[9] = {1, 1, 1, 1, -8, 1, 1, 1, 1};
    float *laplacian = conv2d(im_smoothed, w+n-1, h+n-1,
                               operator, 3, padding_method);

    // compute maximum of absolute Laplacian
    float max = 0.0;
    for(int i=0; i<w; i++) {
        for(int j=0; j<h; j++) {
            //laplacian is (w+n+1)x(h+n+1) with an offset of (n+1)/2 in x and y
            float v = abs( laplacian[(i+(n+1)/2) + (j+(n+1)/2)*(w+n+1)] );
            if( v > max ) max = v;
        }
    }

    // compute laplacian zero-crossings
    float *edges = xmalloc(w*h*sizeof(float));
    for(int i=0; i<w; i++) {
        for(int j=0; j<h; j++) {
            //laplacian is (w+n+1)x(h+n+1) with an offset of (n+1)/2 in x and y
            float UP_LE = laplacian[ (i-1+(n+1)/2) + (j+1+(n+1)/2)*(w+n+1) ];
            float UP    = laplacian[ (i  +(n+1)/2) + (j+1+(n+1)/2)*(w+n+1) ];
            float UP_RI = laplacian[ (i+1+(n+1)/2) + (j+1+(n+1)/2)*(w+n+1) ];
            float LE    = laplacian[ (i-1+(n+1)/2) + (j  +(n+1)/2)*(w+n+1) ];
            float RI    = laplacian[ (i+1+(n+1)/2) + (j  +(n+1)/2)*(w+n+1) ];
            float DO_LE = laplacian[ (i-1+(n+1)/2) + (j-1+(n+1)/2)*(w+n+1) ];
            float DO    = laplacian[ (i  +(n+1)/2) + (j-1+(n+1)/2)*(w+n+1) ];
            float DO_RI = laplacian[ (i+1+(n+1)/2) + (j-1+(n+1)/2)*(w+n+1) ];
            if( (LE*RI       < 0.0 && abs(LE-RI)       > tzc*max) ||
                (UP_LE*DO_RI < 0.0 && abs(UP_LE-DO_RI) > tzc*max) ||
                (DO_LE*UP_RI < 0.0 && abs(DO_LE-UP_RI) > tzc*max) ||
                (UP*DO       < 0.0 && abs(UP-DO)       > tzc*max) ) {
                edges[i+j*w] = 255.0;
            } else {
                edges[i+j*w] = 0.0;
            }
        }
    }

    // free memory
    free(kernel);
    free(im_smoothed);
    free(laplacian);

    return edges;
}
Esempio n. 5
0
DateTime::DateTime (const char* date, const char* time)
    : yOff(conv2d(date + 9)), m(0), d(conv2d(date + 4)), hh(conv2d(time)), mm(conv2d(time + 3)), ss(conv2d(time + 6))
{
    // Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
    switch (date[0]) {
        case 'J': m = (date[1] == 'a') ? 1 : (date[2] == 'n') ? 6 : 7; break;
        case 'F': m = 2; break;
        case 'A': m = date[2] == 'r' ? 4 : 8; break;
        case 'M': m = date[2] == 'r' ? 3 : 5; break;
        case 'S': m = 9; break;
        case 'O': m = 10; break;
        case 'N': m = 11; break;
        case 'D': m = 12; break;
    }
}
DateTime::DateTime (const char* date, const char* time) {
  yOff = conv2d(date + 9);
  switch(date[0]) {
    case 'J': m = date[1] == 'a' ? 1 : m = date[2] == 'n' ? 6 : 7; break;
    case 'F': m = 2; break;
    case 'A': m = date[2] == 'r' ? 4 : 8; break;
    case 'M': m = date[2] == 'r' ? 3 : 5; break;
    case 'S': m = 9; break;
    case 'O': m = 10; break;
    case 'N': m = 11; break;
    case 'D': m = 12; break;
  }
  d=conv2d(date+4);
  hh=conv2d(time);
  mm=conv2d(time+3);
  ss=conv2d(time+6);
}
// Roberts edge detector
// inputs:
//            float *input           -    pointer to input image
//            int w, int h           -    width and height of input image
//            float threshold        -    threshold of edge detection
//            int padding_method     -    padding method for convolution
// output:
//            float *                -    pointer to output image
float *edges_roberts(float *im, int w, int h,
                     float threshold, int padding_method) {

    // Define operators
    // 3x3 operators are used  (although it is unnecessary) in order to
    // simplify the convolution application, and also to unify the three
    // detectors of the first family.
    float roberts_1[9] = {-1, 0, 0, 0, 1, 0, 0, 0, 0};        // ROBERTS
    float roberts_2[9] = { 0,-1, 0, 1, 0, 0, 0, 0, 0};        // OPERATORS
    for(int z=0; z<9; z++) { // normalization
        roberts_1[z] /= 2.0;
        roberts_2[z] /= 2.0;
    }

    // Convolution with operators
    float *Gx = conv2d(im, w, h, roberts_1, 3, padding_method);
    float *Gy = conv2d(im, w, h, roberts_2, 3, padding_method);

    // Allocate memory for output image
    float *im_roberts = xmalloc(w*h*sizeof(float));

    // Two images are obtained (one for each operator). Then the gradient
    // magnitude image is constructed using sqrt(g_x^2+g_y^2). Also
    // the absolute maximum value of the constructed images is computed
    float max = 0.0;
    for(int i=0; i<w; i++) {
        for(int j=0; j<h; j++) {
            float gx = Gx[i+1 + (j+1)*(w+2)]; // Gx and Gy are (w+2) x (h+2)
            float gy = Gy[i+1 + (j+1)*(w+2)]; // there is an (+1,+1) offset
            im_roberts[i+j*w] = sqrt(gx*gx + gy*gy);
            max = MAX(max, im_roberts[i+j*w]);
        }
    }

    // Threshold
    for(int i=0; i<w*h; i++) {
        im_roberts[i] = THRESHOLD(im_roberts[i], threshold*max);
    }

    // Free memory
    free(Gx);
    free(Gy);

    return im_roberts;
}
// Sobel edge detector
// inputs:
//            float *input           -    pointer to input image
//            int w, int h           -    width and height of input image
//            float threshold        -    threshold of edge detection
//            int padding_method     -    padding method for convolution
// output:
//            float *                -    pointer to output image
float *edges_sobel(float *im, int w, int h,
                   float threshold, int padding_method) {

    // Define operators
    float sobel_1[9] = {-1,-2,-1, 0, 0, 0, 1, 2, 1};        // SOBEL
    float sobel_2[9] = {-1, 0, 1,-2, 0, 2,-1, 0, 1};        // OPERATORS
    for(int z=0; z<9; z++) { // normalization
        sobel_1[z] /= 8.0;
        sobel_2[z] /= 8.0;
    }

    // Convolution with operators
    float *Gx = conv2d(im, w, h, sobel_1, 3, padding_method);
    float *Gy = conv2d(im, w, h, sobel_2, 3, padding_method);

    // Allocate memory for output image
    float *im_sobel = xmalloc(w*h*sizeof(float));

    // Two images are obtained (one for each operator). Then the gradient
    // magnitude image is constructed using sqrt(g_x^2+g_y^2). Also
    // the absolute maximum value of the constructed images is computed
    float max = 0.0;
    for(int i=0; i<w; i++) {
        for(int j=0; j<h; j++) {
            float gx = Gx[i+1 + (j+1)*(w+2)]; // Gx and Gy are (w+2) x (h+2)
            float gy = Gy[i+1 + (j+1)*(w+2)]; // there is an (+1,+1) offset
            im_sobel[i+j*w] = sqrt(gx*gx + gy*gy);
            max = MAX(max, im_sobel[i+j*w]);
        }
    }

    // Threshold
    for(int i=0; i<w*h; i++) {
        im_sobel[i] = THRESHOLD(im_sobel[i], threshold*max);
    }

    // Free memory
    free(Gx);
    free(Gy);

    return im_sobel;
}
Esempio n. 9
0
/**
 * Geklaut von Jee-Labs.
 * A convenient constructor for using "the compiler's time":
 * DateTime now (__DATE__, __TIME__);
 * NOTE: using PSTR would further reduce the RAM footprint
 */
void MyRTC::set(const char* date, const char* time) {
    // sample input: date = "Dec 26 2009", time = "12:34:56"
    _year = conv2d(date + 9);
    // Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
    switch (date[0]) {
        case 'J':
            if (date[1] == 'a') {
                _month = 1;
            } else if (date[2] == 'n') {
                _month = 6;
            } else {
                _month = 7;
            }
            break;
        case 'F':
            _month = 2;
            break;
        case 'A':
            _month = date[2] == 'r' ? 4 : 8;
            break;
        case 'M':
            _month = date[2] == 'r' ? 3 : 5;
            break;
        case 'S':
            _month = 9;
            break;
        case 'O':
            _month = 10;
            break;
        case 'N':
            _month = 11;
            break;
        case 'D':
            _month = 12;
            break;
    }
    _date = conv2d(date + 4);
    _hours = conv2d(time);
    _minutes = conv2d(time + 3);
    _seconds = conv2d(time + 6);
}
Esempio n. 10
0
// A convenient constructor for using "the compiler's time":
//   DateTime now (__DATE__, __TIME__);
// NOTE: using PSTR would further reduce the RAM footprint
DateTime::DateTime(
  const char *date,
  const char *time,
  uint32_t centisecond)
  : centisecond_(centisecond) {
  // sample input: date = "Dec 26 2009", time = "12:34:56"
  year_ = conv2d(date + 9);
  // Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
  switch (date[0]) {
    case 'J':
      month_ = date[1] == 'a' ? 1 : (month_ = date[2] == 'n' ? 6 : 7);
      break;
    case 'F':
      month_ = 2;
      break;
    case 'A':
      month_ = date[2] == 'r' ? 4 : 8;
      break;
    case 'M':
      month_ = date[2] == 'r' ? 3 : 5;
      break;
    case 'S':
      month_ = 9;
      break;
    case 'O':
      month_ = 10;
      break;
    case 'N':
      month_ = 11;
      break;
    case 'D':
      month_ = 12;
      break;
    default:
      break;
  }
  day_ = conv2d(date + 4);
  hour_ = conv2d(time);
  minute_ = conv2d(time + 3);
  second_ = conv2d(time + 6);
}
Esempio n. 11
0
// Based on https://github.com/adafruit/RTClib/blob/master/RTClib.cpp
void RTCDue::setDate (const char* date)
{
  _day = conv2d(date + 4);
  
  //Month
  switch (date[0]) {
    case 'J': _month = date[1] == 'a' ? 1 : _month = date[2] == 'n' ? 6 : 7; break;
    case 'F': _month =  2; break;
    case 'A': _month = date[2] == 'r' ? 4 : 8; break;
    case 'M': _month = date[2] == 'r' ? 3 : 5; break;
    case 'S': _month =  9; break;
    case 'O': _month = 10; break;
    case 'N': _month = 11; break;
    case 'D': _month = 12; break;
  }
  
  _year = conv2d(date + 7);
  _day_of_week = calculateDayofWeek(_year, _month, _day);
  
  RTC_SetDate (RTC, (uint16_t)_year, (uint8_t)_month, (uint8_t)_day, (uint8_t)_day_of_week);
}
// A convenient constructor for using "the compiler's time":
// This version will save RAM by using PROGMEM to store it by using the F macro.
//   DateTime now (F(__DATE__), F(__TIME__));
DateTime::DateTime (const __FlashStringHelper* date, const __FlashStringHelper* time) {
    // sample input: date = "Dec 26 2009", time = "12:34:56"
    char buff[11];
    memcpy_P(buff, date, 11);
    yOff = conv2d(buff + 9);
    // Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
    switch (buff[0]) {
        case 'J': m = buff[1] == 'a' ? 1 : m = buff[2] == 'n' ? 6 : 7; break;
        case 'F': m = 2; break;
        case 'A': m = buff[2] == 'r' ? 4 : 8; break;
        case 'M': m = buff[2] == 'r' ? 3 : 5; break;
        case 'S': m = 9; break;
        case 'O': m = 10; break;
        case 'N': m = 11; break;
        case 'D': m = 12; break;
    }
    d = conv2d(buff + 4);
    memcpy_P(buff, time, 8);
    hh = conv2d(buff);
    mm = conv2d(buff + 3);
    ss = conv2d(buff + 6);
}
Esempio n. 13
0
std::vector < Derived > lidarBoostEngine::lk_optical_flow( const MatrixBase<Derived>& I1, const MatrixBase<Derived> &I2, int win_sz)
{
    //Instantiate optical flow matrices
    std::vector < Derived > uv(2);

    //Create masks
    Matrix2d robX, robY, robT;
    robX << -1, 1,
            -1, 1;
    robY << -1, -1,
            1, 1;
    robT << -1, -1,
            -1, -1;

    Derived Ix, Iy, It, A, solutions, x_block, y_block, t_block;

    //Apply masks to images and average the result
    Ix = 0.5 * ( conv2d( I1, robX ) + conv2d( I2, robX ) );
    Iy = 0.5 * ( conv2d( I1, robY ) + conv2d( I2, robY ) );
    It = 0.5 * ( conv2d( I1, robT ) + conv2d( I2, robT ) );

    uv[0] = Derived::Zero( I1.rows(), I1.cols() );
    uv[1] = Derived::Zero( I1.rows(), I1.cols() );

    int hw = win_sz/2;

    for( int i = hw+1; i < I1.rows()-hw; i++ )
    {
        for ( int j = hw+1; j < I1.cols()-hw; j++ )
        {
            //Take a small block of window size in the filtered images
            x_block = Ix.block( i-hw, j-hw, win_sz, win_sz);
            y_block = Iy.block( i-hw, j-hw, win_sz, win_sz);
            t_block = It.block( i-hw, j-hw, win_sz, win_sz);

            //Convert these blocks in vectors
            Map<Derived> A1( x_block.data(), win_sz*win_sz, 1);
            Map<Derived> A2( y_block.data(), win_sz*win_sz, 1);
            Map<Derived> B( t_block.data(), win_sz*win_sz, 1);

            //Organize the vectors in a matrix
            A = Derived( win_sz*win_sz, 2 );
            A.block(0, 0, win_sz*win_sz, 1) = A1;
            A.block(0, 1, win_sz*win_sz, 1) = A2;

            //Solve the linear least square system
            solutions = (A.transpose() * A).ldlt().solve(A.transpose() * B);

            //Insert the solutions in the optical flow matrices
            uv[0](i, j) = solutions(0);
            uv[1](i, j) = solutions(1);

        }
    }

    return uv;

}
Esempio n. 14
0
/* 
 * ===  FUNCTION  ======================================================================
 *         Name: ConvPoolLayer::conv2d
 *  Description: This function is used for multiple input 2d-image-convolution with multiple kernels, in 'valid' mode
 *               i.e. to colvolve each input image with each kernel
 *    Arguments: maps_input: input images to be convolved
 *				    kernels: convolution kernels
 *				maps_conved: convolved maps
 * =====================================================================================
 */
void ConvPoolLayer::conv2d(const vector<MatrixXd>& maps_input, const vector<MatrixXd> kernels, vector<MatrixXd>& maps_conved)
{
	maps_conved.clear();
	maps_conved.reserve(kernels.size() * maps_input.size());  // number of output maps is equal to the number of input maps times the number of kernels
	MatrixXd map_conved_temp;                               // map_conved_temp is a temporary convolved map to store one single convolution operation

	for(int i = 0; i < kernels.size(); i++)
	{
		for(int j = 0; j < maps_input.size(); j++)
		{
			conv2d(maps_input[i], kernels[j], map_conved_temp);
			maps_conved.push_back(map_conved_temp);			
		}	
	}
}		/* -----  end of function ConvPoolLayer::conv2d  ----- */
// Marr-Hildreth edge detector with Laplacian of Gaussian kernel
// inputs:
//            float *input           -    pointer to input image
//            int w, int h           -    width and height of input image
//            float sigma            -    gaussian standard deviation
//            int n                  -    kernel size
//            float tzc              -    threshold in zero-crossing
//            int padding_method     -    padding method for convolution
// output:
//            float *                -    pointer to output image
float *edges_mh_log(float *im, int w, int h,
                    float sigma, int n, float tzc, int padding_method) {

    // compute Laplacian using a LoG (Laplacian of Gaussian) kernel
    float *kernel = LoG_kernel(n,sigma);
    float *laplacian = conv2d(im, w, h, kernel, n, padding_method);

    // compute maximum of absolute Laplacian
    float max = 0.0;
    for(int i=0; i<w; i++) {
        for(int j=0; j<h; j++) {
            // laplacian is (w+n-1)x(h+n-1) with an offset of (n-1)/2 in x and y
            float v = abs( laplacian[(i+(n-1)/2) + (j+(n-1)/2)*(w+n-1)] );
            if( v > max ) max = v;
        }
    }

    // compute laplacian zero-crossings
    float *edges = xmalloc(w*h*sizeof(float));
    for(int i=0; i<w; i++) {
        for(int j=0; j<h; j++) {
            // laplacian is (w+n-1)x(h+n-1) with an offset of (n-1)/2 in x and y
            float UP_LE = laplacian[ (i-1+(n-1)/2) + (j+1+(n-1)/2)*(w+n-1) ];
            float UP    = laplacian[ (i  +(n-1)/2) + (j+1+(n-1)/2)*(w+n-1) ];
            float UP_RI = laplacian[ (i+1+(n-1)/2) + (j+1+(n-1)/2)*(w+n-1) ];
            float LE    = laplacian[ (i-1+(n-1)/2) + (j  +(n-1)/2)*(w+n-1) ];
            float RI    = laplacian[ (i+1+(n-1)/2) + (j  +(n-1)/2)*(w+n-1) ];
            float DO_LE = laplacian[ (i-1+(n-1)/2) + (j-1+(n-1)/2)*(w+n-1) ];
            float DO    = laplacian[ (i  +(n-1)/2) + (j-1+(n-1)/2)*(w+n-1) ];
            float DO_RI = laplacian[ (i+1+(n-1)/2) + (j-1+(n-1)/2)*(w+n-1) ];
            if( (LE*RI       < 0.0 && abs(LE-RI)       > tzc*max) ||
                (UP_LE*DO_RI < 0.0 && abs(UP_LE-DO_RI) > tzc*max) ||
                (DO_LE*UP_RI < 0.0 && abs(DO_LE-UP_RI) > tzc*max) ||
                (UP*DO       < 0.0 && abs(UP-DO)       > tzc*max) ) {
                edges[i+j*w] = 255.0;
            } else {
                edges[i+j*w] = 0.0;
            }
        }
    }

    // free memory
    free(kernel);
    free(laplacian);

    return edges;
}
Esempio n. 16
0
void ConvPoolLayer::bp_weight(const vector<MatrixXd>& grad_conved, const vector<MatrixXd>& maps_input, const int& weight_size, vector<MatrixXd>& grad_weight_single)
{
	grad_weight_single.clear();
	MatrixXd grad_weight_temp(weight_size, weight_size);
	MatrixXd grad_weight_partial;

	int num_input = maps_input.size();
	int num_kernel = grad_conved.size() / num_input;

	grad_weight_single.reserve(num_kernel);

	for(int i = 0; i < num_kernel; i++)
	{
		grad_weight_partial.setZero(weight_size, weight_size);
		for(int j = 0; j < num_input; j++)
		{
			int index = i * num_input + j;
			conv2d(maps_input[j], grad_conved[index], grad_weight_temp);
			grad_weight_partial += grad_weight_temp;					
		}
		grad_weight_single.push_back(grad_weight_partial);
	}
}
Esempio n. 17
0
void RTC_set_default_time_to_compiled(void) {
	uint8_t month_as_number;
	switch (__DATE__[0]) {
	    case 'J': month_as_number = __DATE__[1] == 'a' ? 1 : __DATE__[2] == 'n' ? 6 : 7; break;
	    case 'F': month_as_number = 2; break;
	    case 'A': month_as_number = __DATE__[2] == 'r' ? 4 : 8; break;
	    case 'M': month_as_number = __DATE__[2] == 'r' ? 3 : 5; break;
	    case 'S': month_as_number = 9; break;
	    case 'O': month_as_number = 10; break;
	    case 'N': month_as_number = 11; break;
	    case 'D': month_as_number = 12; break;
	}
	RTC_time_SetTime(
			conv2d(__DATE__ + 7)*100 + conv2d(__DATE__ + 9),
			month_as_number,
			conv2d(__DATE__ + 4),
			conv2d(__TIME__),
			conv2d(__TIME__ + 3),
			conv2d(__TIME__ + 6),
			0);
}
Esempio n. 18
0
int main (int argc, char * argv[])
{
  APPROX int * frame;
  APPROX int * output;
  int i;

  int nFilterRowsFD = 9; 
  int nFilterColsFD = 9;
	  
  APPROX fltPixel_t FD[] =  {
			 1,   3,   4,   5,   6,   5,  4,    3,  1,
			 3,   9,  12,  15,  18,  15,  12,   9,  3,
			 4,  12,  16,  20,  24,  20,  16,  12,  4,
			 5,  15,  20,  25,  30,  25,  20,  15,  5,
			 6,  18,  24,  30,  36,  30,  24,  18,  6,
			 5,  15,  20,  25,  30,  25,  20,  15,  5,
			 4,  12,  16,  20,  24,  20,  16,  12,  4,
			 3,   9,  12,  15,  18,  15,  12,   9,  3,
			 1,   3,   4,   5,   6,   5,   4,   3,  1
  };

  for (i = 0; i < nFilterRowsFD * nFilterColsFD; i++) // ACCEPT_FORBID
  {
    FD[i] /= (1024.0);
  }

  srand (time (NULL));

  STATS_INIT ();
  PRINT_STAT_STRING ("kernel", "2d_convolution");
  PRINT_STAT_INT ("rows", N);
  PRINT_STAT_INT ("columns", M);
  PRINT_STAT_INT ("num_frames", BATCH_SIZE);

  frame = calloc (M * N * BATCH_SIZE, sizeof(algPixel_t));
  output = calloc (M * N * BATCH_SIZE, sizeof(algPixel_t));

  if (!frame || !output) {
    fprintf(stderr, "ERROR: Allocation failed.\n");
    exit(-1);
  }

  /* load image */
  tic ();
  read_array_from_octave (ENDORSE(frame), N, M, FILENAME);
  PRINT_STAT_DOUBLE ("time_load_image", toc ());

  /* Make BATCH_SIZE-1 copies */
  tic ();
  for (i = 1; i < BATCH_SIZE; i++) // ACCEPT_FORBID
  {
    memcpy (&frame[i * M * N], frame, M * N * sizeof(algPixel_t));
  }
  PRINT_STAT_DOUBLE ("time_copy", toc ());

  /* Perform the 2D convolution */
  tic ();
  accept_roi_begin();
  for (i = 0; i < BATCH_SIZE; i++) // ACCEPT_FORBID
  {
    conv2d (&frame[i * M * N], &output[i * M * N], N, M, FD, 1.0, nFilterRowsFD, nFilterColsFD);
  }
  accept_roi_end();
  PRINT_STAT_DOUBLE ("time_2d_convolution", toc ());

  /* Write the results out to disk */
  for (i = 0; i < BATCH_SIZE; i++) // ACCEPT_FORBID
  {
    char buffer [30];
    sprintf (buffer, "2dconv_output.%d.mat", i);
    write_array_to_octave (ENDORSE(&output[i * M * N]), N, M, buffer, "output_" SIZE);
  }
  PRINT_STAT_STRING ("output_file", "2dconv_output." SIZE ".#.mat");

  STATS_END ();

  free (output);
  free (frame);
  return 0;
}
Esempio n. 19
0
static uint8_t conv2d(const char* p) {
  uint8_t v = 0;
  if ('0' <= *p && *p <= '9')
    v = *p - '0';
  return 10 * v + *++p - '0';
}


Adafruit_ILI9341_AS tft = Adafruit_ILI9341_AS(__cs, __dc, __rst);       // Invoke custom library

float sx = 0, sy = 1, mx = 1, my = 0, hx = -1, hy = 0;    // Saved H, M, S x & y multipliers
float sdeg=0, mdeg=0, hdeg=0;
uint16_t osx=120, osy=120, omx=120, omy=120, ohx=120, ohy=120;  // Saved H, M, S x & y coords
uint16_t x0=0, x1=0, y0=0, y1=0;
uint32_t targetTime = 0;                    // for next 1 second timeout
uint8_t hh=conv2d(__TIME__), mm=conv2d(__TIME__+3), ss=conv2d(__TIME__+6);  // Get H, M, S from compile time
boolean initial = 1;

void loop() {
//  if (targetTime < millis()) {
//    targetTime = millis()+1000;
		_delay_ms(1000);
    ss++;              // Advance second
    if (ss==60) {
      ss=0;
      mm++;            // Advance minute
      if(mm>59) {
        mm=0;
        hh++;          // Advance hour
        if (hh>23) {
          hh=0;
Esempio n. 20
0
int main(int argc, char *argv[]) {
	if (argc != 6) {
		printf("Usage: %s input_image_1 sigma n tzc output\n", argv[0]);
	} else {

		// Execution time:
		double start = (double)clock();
	
		// Parameters
		float sigma = atof(argv[2]);
			// <sigma> is the standard deviation of the gaussian function used to
			// create the kernel.
		int n = atoi(argv[3]);
			// <n> is the size of the kernel (n*n).
		float tzc = atof(argv[4]);
			// <tzc> is the threshold of the zero-crossing method.
	
		// Load input image (using iio)
		int w, h, pixeldim;
		float *im_orig = iio_read_image_float_vec(argv[1], &w, &h, &pixeldim);
		fprintf(stderr, "Input image loaded:\t %dx%d image with %d channel(s).\n", w, h, pixeldim);

		// Grayscale conversion (if necessary)
		double *im = malloc(w*h*sizeof(double));
		if (im == NULL){
			fprintf(stderr, "Out of memory...\n");
			exit(EXIT_FAILURE);
		}
			// allocate memory for the grayscale image <im>, output of the grayscale conversion
			// and correct allocation check.
		int z;
			// <z> is just an integer used as array index.
		int zmax = w*h;		// number of elements of <im>
		if (pixeldim==3){	// if the image is color (RGB, three channels)...
			for(z=0;z<zmax;z++){		// for each pixel in the image <im>, calculate the gray 
										// value according to the expression: 
										// I = ( 6968*R + 23434*G + 2366*B ) / 32768.
				im[z] =  (double)(6968*im_orig[3*z] + 23434*im_orig[3*z + 1] + 2366*im_orig[3*z + 2])/32768;
			}
			fprintf(stderr, "images converted to grayscale\n");
		} else {		// the image was originally grayscale...
			for(z=0;z<zmax;z++){
				im[z] = (double)im_orig[z];		// only assign the value of im_orig to im, casting to double.
			}
			fprintf(stderr, "images are already in grayscale\n");
		}

		// Generate gaussian kernel
		// see gaussian_kernel.c
		double *kernel = gaussian_kernel(n,sigma);

		// Debug: save kernel to image (this is not part of the algorithm itself)
		if (SAVE_KERNEL){
			float *kernel_float = malloc(n*n*sizeof(float));
			if (kernel_float == NULL){
				fprintf(stderr, "Out of memory...\n");
				exit(EXIT_FAILURE);
			}			
			int i;
			int imax = n*n;
			for (i=0;i<imax;i++){
				kernel_float[i] = 5000*(float)kernel[i];
			}
			iio_save_image_float_vec("kernel.png", kernel_float, n, n, 1);
			free(kernel_float);
			fprintf(stderr, "kernel saved to kernel.png\n");
		}
		// end of save kernel image
		
		// Smooth input image with gaussian kernel
		// see 2dconvolution.c
		// <im_smoothed> is calculated convolving the grayscale image <im> with
		// the gaussian kernel previously generated.
		double *im_smoothed = conv2d(im, w, h, kernel, n);

		// Debug: save smoothed image (this is not part of the algorithm itself)
		if (SAVE_SMOOTHED_IMAGE){
			float *smoothed = malloc((w+n-1)*(h+n-1)*sizeof(float));
			if (smoothed == NULL){
				fprintf(stderr, "Out of memory...\n");
				exit(EXIT_FAILURE);
			}
			int i,j, fila, col;
			int imax = w*h;
			int dif_fila_col = (n-1)/2;
			for (i=0;i<imax;i++){
				fila = (int)(i/w);
				col = i - w*fila + dif_fila_col;
				fila += dif_fila_col;
				j = col + (w+n-1)*fila;
				smoothed[i] = (float)im_smoothed[j];
			}
			iio_save_image_float_vec("smoothed.png", smoothed, w, h, 1);
			free(smoothed);
			fprintf(stderr, "smoothed image saved to smoothed.png\n");
		}
		// end of save smoothed image

		// Laplacian of the smoothed image
		double operator[9] = {1, 1, 1, 1, -8, 1, 1, 1, 1};
			// an approximation of the laplacian operator:
			//		/ 1  1  1 \
			//	   |  1 -8  1  |
			//		\ 1  1  1 /
			// now we convolve the smoothed image with this operator,
			// generating the <laplacian> image.
		double *laplacian = conv2d(im_smoothed, w+n-1, h+n-1, operator, 3);
		
		// calculate max absolute value of laplacian:
		// required for thresholding in zero-crossing (next)
		double max_l = 0;
		int p;
		int pmax = (w+n+1)*(h+n+1);
		for (p=0;p<pmax;p++){
			if (abs(laplacian[p])>max_l){
				max_l = abs(laplacian[p]);
			}
		}

		// Debug: save laplacian image (this is not part of the algorithm itself)
		if (SAVE_LAPLACIAN_IMAGE){
			float *lapl = malloc((w+n+1)*(h+n+1)*sizeof(float));
			if (lapl == NULL){
				fprintf(stderr, "Out of memory...\n");
				exit(EXIT_FAILURE);
			}
			int i,j, fila, col;
			int imax = w*h;
			int dif_fila_col = (n+1)/2;
			for (i=0;i<imax;i++){
				fila = (int)(i/w);
				col = i - w*fila + dif_fila_col;
				fila += dif_fila_col;
				j = col + (w+n+1)*fila;
				lapl[i] = (float)laplacian[j];
			}
			iio_save_image_float_vec("laplacian.png", lapl, w, h, 1);
			free(lapl);
			fprintf(stderr, "laplacian image saved to laplacian.png\n");
		}
		// end of save laplacian image

		// Zero-crossing
		float *zero_cross = calloc(w*h,sizeof(float));		// this image will only content values 0 and 255
															// but we use float for saving with iio.
		if (zero_cross == NULL){
			fprintf(stderr, "Out of memory...\n");
			exit(EXIT_FAILURE);
		}
		int ind_en_lapl, fila, col;
		int *offsets = get_neighbors_offset(w+n+1, 3);
		pmax = w*h;
		int dif_fila_col = (n+1)/2;
		for (p=0;p<pmax;p++){
			fila = ((int)(p/w));
			col = p-(w*fila) + dif_fila_col;
			fila += dif_fila_col;
			ind_en_lapl = col + (w+n+1)*fila;
			double *n3 = get_neighborhood(laplacian, ind_en_lapl, 3, offsets);
			if ((n3[3]*n3[5]<0)&&(abs(n3[3]-n3[5])>(tzc*max_l))) {
				// horizontal sign change
				zero_cross[p] = 255;
			} else if ((n3[1]*n3[7]<0)&&(abs(n3[1]-n3[7])>(tzc*max_l))) {
					// vertical sign change
					zero_cross[p] = 255;
				} else if ((n3[2]*n3[6]<0)&&(abs(n3[2]-n3[6])>(tzc*max_l))) {
						// +45deg sign change
						zero_cross[p] = 255;
					} else if ((n3[0]*n3[8]<0)&&(abs(n3[0]-n3[8])>(tzc*max_l))) {
							// -45deg sign change
							zero_cross[p] = 255;
						}
			free_neighborhood(n3);
		}
		free_neighbors_offsets(offsets);

		// Save output image
		iio_save_image_float_vec(argv[5], zero_cross, w, h, 1);
		fprintf(stderr, "Output Image saved in %s:\t %dx%d image with %d channel(s).\n", argv[5], w, h, pixeldim);
	
		// Free memory
		free(zero_cross);
		free(im_orig);
		free(im);
		free(im_smoothed);
		free(laplacian);
		free_gaussian_kernel(kernel);

		fprintf(stderr, "marr-hildreth edge detector computation done.\n");

		// Execution time:
		double finish = (double)clock();
		double exectime = (finish - start)/CLOCKS_PER_SEC;
		fprintf(stderr, "execution time: %1.3f s.\n", exectime);		

		return 0;
	
	} // else (argc)
}
Esempio n. 21
0
bool SerialLineIn::dispatch(void) 
{
  bool handled = false;
  DateTime now = RTC.nowDateTime();
  switch (toupper(*buf))
  {
    case 'D':
      // Dyymmdd: Set date
      handled = true;
      if ( strlen(buf) == 1 )
      {
	print_time();
	break;
      }
      if ( strlen(buf) != 7 )
      {
	printf_P(PSTR("SERL Format: Dyymmdd\n\r"));
	break;
      }
      now = DateTime(2000+conv2d(buf+1),conv2d(buf+3),conv2d(buf+5),now.hour(),now.minute(),now.second());
      RTC.adjust(now);
      print_time();
      break;
    case 'T':
      // Thhmmss: Set time
      handled = true;
      if ( strlen(buf) != 7 )
      {
	printf_P(PSTR("SERL Format: Dyymmdd\n\r"));
	break;
      }
      now = DateTime(now.year(),now.month(),now.day(),conv2d(buf+1),conv2d(buf+3),conv2d(buf+5));
      RTC.adjust(now);
      print_time();
      break;
    case '@':
      handled = true;
      // Special time values

      if ( !strcmp(buf+1,"N") )
      {
	uint32_t when = events.whenNext();
#ifdef HAVE_FIRE_CAMERA
	if ( fire_camera.is_valid() )
	  when = fire_camera.whenNext();
#endif
	RTC.adjust(when);
	print_time();
      }
      else if ( !strcmp(buf+1,"1") )
      {
	events.reset();
#ifdef HAVE_FIRE_CAMERA
	fire_camera.invalidate();
#endif
	RTC.adjust(events.whenNext());
	print_time();
      }
      else if ( !strcmp(buf+1,"0") )
      {
	RTC.adjust(DateTime(2011,1,1,0,0,0).unixtime());
	print_time();
      }
      else
	printf_P(PSTR("SERL Error: Unknown @ value: %s"),buf+1);
      break;
    case 'E':
      // E: Print EEPROM
      handled = true;
      logger.play();

      break;
    case 'F':
      // F: Free memory 
      handled = true;
      printf_P(PSTR("FREE %u\n\r"),freeMemory());

      break;
  }
  return handled;
}
Esempio n. 22
0
/* 
 * ===  FUNCTION  ======================================================================
 *         Name: ConvPoolLayer::flip_conv2d
 *  Description: This function is used for single input 2d-image-convolution with a single kernels, in 'valid' mode. Strictly this is convolution
 *    Arguments: map_input: input image to be convolved
 *				    kernel: convolution kernel
 *				map_conved: convolved map
 * =====================================================================================
 */
void ConvPoolLayer::flip_conv2d(const MatrixXd& map_input, const MatrixXd& kernel, MatrixXd& map_conved)
{
	map_conved.resize(map_input.rows() + 1 - kernel.rows(), map_input.cols() + 1 - kernel.cols());
	conv2d(map_input, kernel.reverse(), map_conved);
}		/* -----  end of function ConvPoolLayer::flip_conv2d  ----- */
//  Software Guide : BeginLatex
//	\vspace{0.5cm}
//	\Large{Main function} \\
//  Software Guide : EndLatex
// Software Guide : BeginCodeSnippet
int main(int argc, char *argv[]) {
// Software Guide : EndCodeSnippet

	if (argc != 4) {
		printf("Usage: %s input_image threshold padding_method\n", argv[0]);
	} else {

		// Execution time:
		double start = (double)clock();

		// Load input image (using iio)
//  Software Guide : BeginLatex
//	Load input image (using \textit{iio}): \\
//  Software Guide : EndLatex
// Software Guide : BeginCodeSnippet
		int w, h, pixeldim;
		float *im_orig = iio_read_image_float_vec(argv[1], &w, &h, &pixeldim);
// Software Guide : EndCodeSnippet
		fprintf(stderr, "Input image loaded:\t %dx%d image with %d channel(s).\n", w, h, pixeldim);

		// Grayscale conversion (if necessary)
//  Software Guide : BeginLatex
//	Grayscale conversion (if necessary): explained in \ref{sec:grayscale}. \\ \\
//  Software Guide : EndLatex
		double *im = malloc(w*h*sizeof(double));
		if (im == NULL){
			fprintf(stderr, "Out of memory...\n");
			exit(EXIT_FAILURE);
		}
			// allocate memory for the grayscale image <im>, output of the grayscale conversion
			// and correct allocation check.
		int z;
			// <z> is just an integer used as array index.
		int zmax = w*h;		// number of elements of <im>
		if (pixeldim==3){	// if the image is color (RGB, three channels)...
			for(z=0;z<zmax;z++){		// for each pixel in the image <im>, calculate the gray 
										// value according to the expression: 
										// I = ( 6968*R + 23434*G + 2366*B ) / 32768.
				im[z] =  (double)(6968*im_orig[3*z] + 23434*im_orig[3*z + 1] + 2366*im_orig[3*z + 2])/32768;
			}
			fprintf(stderr, "images converted to grayscale\n");
		} else {		// the image was originally grayscale...
			for(z=0;z<zmax;z++){
				im[z] = (double)im_orig[z];		// only assign the value of im_orig to im, casting to double.
			}
			fprintf(stderr, "images are already in grayscale\n");
		}

		// Define operators:
//  Software Guide : BeginLatex
//	Define the normalized Roberts, Prewitt and Sobel operators: \\
//	(We use $3\times 3$ operators)
//	\begin{itemize}
//		\item	Roberts:
//				$$
//				R_1 = \begin{bmatrix} -1 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 0 & 0 \end{bmatrix}
//				$$
//				$$
//				R_2 = \begin{bmatrix} 0 & -1 & 0 \\ 1 & 0 & 0 \\ 0 & 0 & 0 \end{bmatrix}
//				$$
//		\item	Prewitt:
//				$$
//				P_1 = \begin{bmatrix} \frac{-1}{6} & \frac{-1}{6} & \frac{-1}{6} \\ 0 & 0 & 0 \\ \frac{1}{6} & \frac{1}{6} & \frac{1}{6} \end{bmatrix}
//				$$
//				$$
//				P_2 = \begin{bmatrix} \frac{-1}{6} & 0 & \frac{1}{6} \\ \frac{-1}{6} & 0 & \frac{1}{6} \\ \frac{-1}{6} & 0 & \frac{1}{6} \end{bmatrix}
//				$$
//		\item	Sobel:
//				$$
//				S_1 = \begin{bmatrix} \frac{-1}{8} & \frac{-1}{4} & \frac{-1}{8} \\ 0 & 0 & 0 \\ \frac{1}{8} & \frac{1}{4} & \frac{1}{8} \end{bmatrix}
//				$$
//				$$
//				S_2 = \begin{bmatrix} \frac{-1}{8} & 0 & \frac{1}{8} \\ \frac{-1}{4} & 0 & \frac{1}{4} \\ \frac{-1}{8} & 0 & \frac{1}{8} \end{bmatrix}
//				$$
//	\end{itemize}
//  Software Guide : EndLatex
// Software Guide : BeginCodeSnippet
		double roberts_1[9] = {-1, 0, 0, 0, 1, 0, 0, 0, 0};		// ROBERTS
		double roberts_2[9] = { 0,-1, 0, 1, 0, 0, 0, 0, 0};		// OPERATORS
		//---------------------------------------------------------------------------------
		double prewitt_1[9] = {-1,-1,-1, 0, 0, 0, 1, 1, 1};		// PREWITT
		double prewitt_2[9] = {-1, 0, 1,-1, 0, 1,-1, 0, 1};		// OPERATORS
		//---------------------------------------------------------------------------------
		double sobel_1[9] = {-1,-2,-1, 0, 0, 0, 1, 2, 1};		// SOBEL
		double sobel_2[9] = {-1, 0, 1,-2, 0, 2,-1, 0, 1};		// OPERATORS
		//---------------------------------------------------------------------------------
		for (z=0;z<9;z++) {										// NORMALIZATION
			//roberts_1[z] /= 1;
			//roberts_2[z] /= 1;
			prewitt_1[z] /= 6;
			prewitt_2[z] /= 6;
			sobel_1[z] /= 8;
			sobel_2[z] /= 8;
		}
// Software Guide : EndCodeSnippet

		// Convolve images:
//  Software Guide : BeginLatex
//	The input image is convolved with the defined operatos, using the \texttt{conv2d} function in \texttt{2dconvolution.c}:
//  Software Guide : EndLatex
// Software Guide : BeginCodeSnippet
		int padding_method = atoi(argv[3]);
		double *im_r1 = conv2d(im, w, h, roberts_1, 3, padding_method);
		double *im_r2 = conv2d(im, w, h, roberts_2, 3, padding_method);
		double *im_p1 = conv2d(im, w, h, prewitt_1, 3, padding_method);
		double *im_p2 = conv2d(im, w, h, prewitt_2, 3, padding_method);
		double *im_s1 = conv2d(im, w, h, sobel_1, 3, padding_method);
		double *im_s2 = conv2d(im, w, h, sobel_2, 3, padding_method);
// Software Guide : EndCodeSnippet

		// Allocate memory for final images:
//	Software Guide : BeginLatex
//	Allocate memory for final images:
//  Software Guide : EndLatex
// Software Guide : BeginCodeSnippet
		float *im_roberts = malloc(w*h*sizeof(float));
		float *im_prewitt = malloc(w*h*sizeof(float));
		float *im_sobel = malloc(w*h*sizeof(float));
// Software Guide : EndCodeSnippet

//	Software Guide : BeginLatex
//	For each method, two images are obtained (one for each operator). Then the gradient magnitude image is constructed using $M=\sqrt{g_x^2+g_y^2}$. \\
//	Also the absolute maximum value of the constructed images is computed, for each method. \\
//	Software Guide : EndLatex
// Software Guide : BeginCodeSnippet
		int i,j, fila, col;
		double max_r = 0;
		double max_p = 0;
		double max_s = 0;
		int imax = w*h;
		for (i=0;i<imax;i++){
			fila = (int)(i/w);
			col = i - w*fila + 1;
			fila += 1;
			j = col + (w+2)*fila;
			// Max in each case
			im_roberts[i] = sqrt(im_r1[j]*im_r1[j] + im_r2[j]*im_r2[j]);
			im_prewitt[i] = sqrt(im_p1[j]*im_p1[j] + im_p2[j]*im_p2[j]);
			im_sobel[i] = sqrt(im_s1[j]*im_s1[j] + im_s2[j]*im_s2[j]);
			// Absolute max
			max_r = MAX(max_r,im_roberts[i]);
			max_p = MAX(max_p,im_prewitt[i]);
			max_s = MAX(max_s,im_sobel[i]);
		}
// Software Guide : EndCodeSnippet

		// Thresholding
//	Software Guide : BeginLatex
//	Thresholded images of each method are created, using the THRESHOLD macro: \\
//	Software Guide : EndLatex
// Software Guide : BeginCodeSnippet
		float th = atof(argv[2]);
		for (i=0;i<imax;i++){
			im_roberts[i] = THRESHOLD(im_roberts[i],th*max_r);
			im_prewitt[i] = THRESHOLD(im_prewitt[i],th*max_p);
			im_sobel[i] = THRESHOLD(im_sobel[i],th*max_s);
		}
// Software Guide : EndCodeSnippet

		// Save outout images
//  Software Guide : BeginLatex
//	Save output image (using \textit{iio}): \\
//  Software Guide : EndLatex
// Software Guide : BeginCodeSnippet
		iio_save_image_float_vec("roberts.png", im_roberts, w, h, 1);
		iio_save_image_float_vec("prewitt.png", im_prewitt, w, h, 1);
		iio_save_image_float_vec("sobel.png", im_sobel, w, h, 1);
// Software Guide : EndCodeSnippet
			fprintf(stderr, "Roberts image saved to roberts.png.\n");
			fprintf(stderr, "Prewitt image saved to prewitt.png.\n");
			fprintf(stderr, "Sobel image saved to sobel.png.\n");

		// Free memory:
		free(im_orig);
		free(im);
		free(im_r1);
		free(im_r2);
		free(im_p1);
		free(im_p2);
		free(im_s1);
		free(im_s2);
		free(im_roberts);
		free(im_prewitt);
		free(im_sobel);

		fprintf(stderr, "Edge detection algorithms based on first derivative computation done.\n");

		// Execution time:
		double finish = (double)clock();
		double exectime = (finish - start)/CLOCKS_PER_SEC;
		fprintf(stderr, "execution time: %1.3f s.\n", exectime);

		return 0;

	} // else (argc)

} // end of the program
// Haralick edge detector
// inputs:
//            float *input           -    pointer to input image
//            int w, int h           -    width and height of input image
//            float rhozero          -    threshold
//            int padding_method     -    padding method for convolution
// output:
//            float *                -    pointer to output image
float *edges_haralick(float *im, int w, int h,
                      float rhozero, int padding_method) {

    // Haralick's masks for computing k1 to k10
    // New masks calculated by 2-d fitting using LS, with the function
    //   f(x,y) = k1 + k2*x + k3*y + k4*x^2 + k5*xy
    //            + k6*y^2 + k7*x^3 + k8*x^2y + k9*xy^2 + k10*y^3
    float mask[10][25] = { {       425,   275,  225,  275,  425,
                                   275,   125,   75,  125,  275,
                                   225,    75,   25,   75,  225,
                                   275,   125,   75,  125,  275,
                                   425,   275,  225,  275,  425},
                               { -2260,  -620,    0,  620, 2260,
                                 -1660,  -320,    0,  320, 1660,
                                 -1460,  -220,    0,  220, 1460,
                                 -1660,  -320,    0,  320, 1660,
                                 -2260,  -620,    0,  620, 2260},
                               {  2260,  1660, 1460, 1660, 2260,
                                   620,   320,  220,  320,  620,
                                     0,     0,    0,    0,    0,
                                  -620,  -320, -220, -320, -620,
                                 -2260, -1660,-1460,-1660,-2260},
                               {  1130,   620,  450,  620, 1130,
                                   830,   320,  150,  320,  830,
                                   730,   220,   50,  220,  730,
                                   830,   320,  150,  320,  830,
                                  1130,   620,  450,  620, 1130},
                               {  -400,  -200,    0,  200,  400,
                                  -200,  -100,    0,  100,  200,
                                     0,     0,    0,    0,    0,
                                   200,   100,    0, -100, -200,
                                   400,   200,    0, -200, -400},
                               {  1130,   830,  730,  830, 1130,
                                   620,   320,  220,  320,  620,
                                   450,   150,   50,  150,  450,
                                   620,   320,  220,  320,  620,
                                  1130,   830,  730,  830, 1130},
                               { -8260, -2180,    0, 2180, 8260,
                                 -6220, -1160,    0, 1160, 6220,
                                 -5540,  -820,    0,  820, 5540,
                                 -6220, -1160,    0, 1160, 6220,
                                 -8260, -2180,    0, 2180, 8260},
                               {  5640,  3600, 2920, 3600, 5640,
                                  1800,   780,  440,  780, 1800,
                                     0,     0,    0,    0,    0,
                                 -1800,  -780, -440, -780,-1800,
                                 -5640, -3600,-2920,-3600,-5640},
                               { -5640, -1800,    0, 1800, 5640,
                                 -3600,  -780,    0,  780, 3600,
                                 -2920,  -440,    0,  440, 2920,
                                 -3600,  -780,    0,  780, 3600,
                                 -5640, -1800,    0, 1800, 5640},
                               {  8260,  6220, 5540, 6220, 8260,
                                  2180,  1160,  820, 1160, 2180,
                                     0,     0,    0,    0,    0,
                                 -2180, -1160, -820,-1160,-2180,
                                 -8260, -6220, -5540,-6220,-8260   } };

    // apply the masks operators, this will lead to coefficients k1 to k10
    float *aux[10];
    for(int i=0; i<10; i++) {
        aux[i] = conv2d(im, w, h, mask[i], 5, padding_method);
    }

	 float eps=1e-16;
    // compute Haralick edges
    float *edges = xmalloc(w*h*sizeof(float)); // get memory for output
    for(int i=0; i<w; i++) {
        for(int j=0; j<h; j++) {
            // aux is (w+4)x(h+4) and there is an offset of (2,2)
            // k1 is not used
            float k2  = aux[1][i+2 + (j+2)*(w+4)];
            float k3  = aux[2][i+2 + (j+2)*(w+4)];
            float k4  = aux[3][i+2 + (j+2)*(w+4)];
            float k5  = aux[4][i+2 + (j+2)*(w+4)];
            float k6  = aux[5][i+2 + (j+2)*(w+4)];
            float k7  = aux[6][i+2 + (j+2)*(w+4)];
            float k8  = aux[7][i+2 + (j+2)*(w+4)];
            float k9  = aux[8][i+2 + (j+2)*(w+4)];
            float k10 = aux[9][i+2 + (j+2)*(w+4)];
            float sintheta =  -k2 / sqrt(k2*k2 + k3*k3+eps);
            float costheta =  -k3 / sqrt(k2*k2 + k3*k3+eps);
            float C1 = k2  * sintheta + k3 * costheta;
            float C2 = k4  * sintheta * sintheta
                     + k5  * sintheta * costheta
                     + k6  * costheta * costheta;
            float C3 = k7  * sintheta * sintheta * sintheta
                     + k8  * sintheta * sintheta * costheta
                     + k9  * sintheta * costheta * costheta
                     + k10 * costheta * costheta * costheta;
			int cond1=fabs( C2 / (3.0 * C3+eps)) < rhozero;
			int cond2=C3 < 0.0;
			/* this condition is implicit, does not need to be checked, but we 
			do to provide extra safety.
			*/
			int cond3=C2 > 0.0;	
			//this one does not need to be imposed by construction, see paper.
			//int cond4=fabs(C1-C2*C2/C3/3) > 0.0;
			
				
            if( cond1  && cond2 && cond3) {
                edges[i+j*w] = 255.0;
            } else {
                edges[i+j*w] = 0.0;
            }
        }
    }

    // free memory
    for(int i=0; i<10; i++) {
        free(aux[i]);
    }

    return edges;
}