void distanceTransform::iteration8(channel& chnl) const {
    int x,y,z;

    const int rowm1 = chnl.rows()-1;
    const int colm1 = chnl.columns()-1;

    static const int deltax[12] = {1,1,0,-1,-1,-1, 0, 1,1,1,0,-1};
    static const int deltay[12] = {0,1,1, 1, 0,-1,-1,-1,0,1,1, 1};

    float minimum;

    // upper-left
    if (chnl.at(0,0) > 0) {
      chnl.at(0,0) = 1.0f+min(chnl.at(0,1),chnl.at(1,1),chnl.at(1,0));
    }

    // top
    y = 0;
    for (x=1;x<colm1;++x) {
      if (chnl.at(y,x) > 0) {
        // valid pixel, let's check for the distance value
        minimum = chnl.at(y+deltay[0],x+deltax[0]);

        for (z=1;z<5;++z) {
          minimum = min(minimum,chnl.at(y+deltay[z],x+deltax[z]));
        }

        chnl.at(y,x) = minimum+1.0f;
      }
    }

    // upper-right
    if (chnl.at(0,colm1) > 0) {
      chnl.at(0,colm1) = 1.0f+min(chnl.at(0,colm1-1),chnl.at(1,colm1-1),
                                  chnl.at(1,colm1));
    }

    // inner of the image only...
    for (y=1;y<rowm1;++y) {
      // left border
      x = 0;
      if (chnl.at(y,x) > 0) {
        minimum = chnl.at(y+deltay[6],x+deltax[6]);

        for (z=7;z<11;++z) {
          minimum = min(minimum,chnl.at(y+deltay[z],x+deltax[z]));
        }

        chnl.at(y,x) = minimum+1.0f;
      }

      // inner of the line
      for (x=1;x<colm1;++x) {
        if (chnl.at(y,x) > 0) {
          // valid pixel, let's check for the distance value
          minimum = chnl.at(y+deltay[0],x+deltax[0]);

          for (z=1;z<8;++z) {
            minimum = min(minimum,chnl.at(y+deltay[z],x+deltax[z]));
          }

          chnl.at(y,x) = minimum+1.0f;
        }
      }

      // right border
      if (chnl.at(y,x) > 0) {
        minimum = chnl.at(y+deltay[2],x+deltax[2]);

        for (z=3;z<7;++z) {
          minimum = min(minimum,chnl.at(y+deltay[z],x+deltax[z]));
        }

        chnl.at(y,x) = minimum+1.0f;
      }
    }

    // bottom-left
    if (chnl.at(rowm1,0) > 0) {
      chnl.at(rowm1,0) = 1.0f+min(chnl.at(rowm1,1),chnl.at(rowm1-1,1),
                                  chnl.at(rowm1-1,0));
    }

    // bottom
    for (x=1;x<colm1;++x) {
      if (chnl.at(y,x) > 0) {
        // valid pixel, let's check for the distance value
        minimum = chnl.at(y+deltay[4],x+deltax[4]);

        for (z=5;z<9;++z) {
          minimum = min(minimum,chnl.at(y+deltay[z],x+deltax[z]));
        }

        chnl.at(y,x) = minimum+1.0f;
      }
    }

    // bottom-right
    if (chnl.at(rowm1,colm1) > 0) {
      chnl.at(rowm1,colm1) = 1.0f+min(chnl.at(rowm1,colm1-1),
                                      chnl.at(rowm1-1,colm1-1),
                                      chnl.at(rowm1-1,colm1));
    }

  }
  void distanceTransform::iteration4back(channel& chnl) const {
    int x,y,z;

    const int rowm1 = chnl.lastRow();
    const int colm1 = chnl.lastColumn();

    static const int deltax[6] = {1,0,-1, 0, 1,0};
    static const int deltay[6] = {0,1, 0,-1, 0,1};

    float minimum;

    // bottom-right
    if (chnl.at(rowm1,colm1) > 0) {
      chnl.at(rowm1,colm1) = 1.0f+min(chnl.at(rowm1,colm1-1),
                                      chnl.at(rowm1-1,colm1));
    }

    // bottom
    y = rowm1;
    for (x=colm1-1;x>0;--x) {
      if (chnl.at(y,x) > 0) {
        // valid pixel, let's check for the distance value
        minimum = chnl.at(y+deltay[2],x+deltax[2]);

        for (z=3;z<5;++z) {
          minimum = min(minimum,chnl.at(y+deltay[z],x+deltax[z]));
        }

        chnl.at(y,x) = minimum+1.0f;
      }
    }

    // bottom-left
    if (chnl.at(rowm1,0) > 0) {
      chnl.at(rowm1,0) = 1.0f+min(chnl.at(rowm1,1),
                                  chnl.at(rowm1-1,0));
    }

    // inner of the image only...
    for (y=rowm1-1;y>0;--y) {
      x = colm1;
      // right border
      if (chnl.at(y,x) > 0) {
        minimum = chnl.at(y+deltay[1],x+deltax[1]);

        for (z=2;z<4;++z) {
          minimum = min(minimum,chnl.at(y+deltay[z],x+deltax[z]));
        }

        chnl.at(y,x) = minimum+1.0f;
      }

      // inner of the line
      for (x=colm1-1;x>0;--x) {
        if (chnl.at(y,x) > 0) {
          // valid pixel, let's check for the distance value
          minimum = chnl.at(y+deltay[0],x+deltax[0]);

          for (z=1;z<4;++z) {
            minimum = min(minimum,chnl.at(y+deltay[z],x+deltax[z]));
          }

          chnl.at(y,x) = minimum+1.0f;
        }
      }

      // left border
      if (chnl.at(y,x) > 0) {
        minimum = chnl.at(y+deltay[3],x+deltax[3]);

        for (z=0;z<2;++z) {
          minimum = min(minimum,chnl.at(y+deltay[z],x+deltax[z]));
        }

        chnl.at(y,x) = minimum+1.0f;
      }
    }

    // upper-right
    if (chnl.at(0,colm1) > 0) {
      chnl.at(0,colm1) = 1.0f+min(chnl.at(0,colm1-1),
                                  chnl.at(1,colm1));
    }

    // top
    for (x=colm1-1;x>0;--x) {
      if (chnl.at(y,x) > 0) {
        // valid pixel, let's check for the distance value
        minimum = chnl.at(y+deltay[0],x+deltax[0]);

        for (z=1;z<3;++z) {
          minimum = min(minimum,chnl.at(y+deltay[z],x+deltax[z]));
        }

        chnl.at(y,x) = minimum+1.0f;
      }
    }

    // upper-left
    if (chnl.at(0,0) > 0) {
      chnl.at(0,0) = 1.0f+min(chnl.at(0,1),chnl.at(1,0));
    }

  }
Exemplo n.º 3
0
  // On copy apply for type channel!
  bool huMoments::apply(const channel& src,dvector& dest, dvector& more) const {
    channel::value_type val;

    dest.resize(NUM_FEAT,0,false,true);
    more.resize(MORE_FEAT,0,false,true);

    double m00=0.0;
    double cm11,cm20,cm02,cm30,cm03,cm12,cm21;
    cm11=cm20=cm02=cm30=cm03=cm12=cm21=0.0;
    double xcog, ycog;
    xcog=ycog=0.0;

    int r, rows=src.rows();
    int c, cols=src.columns();

    // compute simple moments and cog
    for (r=0; r<rows; r++) {
      for (c=0; c<cols; c++) {
        val = src.at(r,c);
        m00+=val;
        xcog+=c*val;
        ycog+=r*val;
      }
    }

    // end here, if no content
    if (m00==0) {
      return false;
    }

    // compute cog's
    more[huMoments::xcog]=xcog=xcog/m00;  //xcog
    more[huMoments::ycog]=ycog=ycog/m00;  //ycog

    // compute central moments
    for (r=0; r<rows; r++) {
      for (c=0; c<cols; c++) {
        val = src.at(r,c);
        double x_xcog = c-xcog;
        double y_ycog = r-ycog;
        cm11+=(x_xcog)*(y_ycog)*val;
        cm20+=(x_xcog)*(x_xcog)*val;
        cm02+=(y_ycog)*(y_ycog)*val;
        cm30+=(x_xcog)*(x_xcog)*(x_xcog)*val;
        cm03+=(y_ycog)*(y_ycog)*(y_ycog)*val;
        cm12+=(x_xcog)*(y_ycog)*(y_ycog)*val;
        cm21+=(x_xcog)*(x_xcog)*(y_ycog)*val;
      }
    }

    double m00pow2,m00pow2_5;
    m00pow2 = m00*m00;
    m00pow2_5 = pow(m00,2.5);
    // normalized central moments
    cm02 = cm02/m00pow2;
    cm03 = cm03/m00pow2_5;
    cm11 = cm11/m00pow2;
    cm12 = cm12/m00pow2_5;
    cm20 = cm20/m00pow2;
    cm21 = cm21/m00pow2_5;
    cm30 = cm30/m00pow2_5;

    // calculate moment invariants
    dest[huMoments::hu1] = cm20 + cm02;
    dest[huMoments::hu2] = pow((cm20 - cm02),2) + 4*pow(cm11,2);
    dest[huMoments::hu3] = pow((cm30 - 3*cm12),2) + pow((3*cm21 - cm03),2);
    dest[huMoments::hu4] = pow((cm30 + cm12),2) + pow((cm21 + cm03),2);
    dest[huMoments::hu5] = (cm30-3*cm12)*(cm30+cm12)*(   pow((cm30+cm12),2) - 3*pow((cm21+cm03),2) )
                         + (3*cm21-cm03)*(cm21+cm03)*( 3*pow((cm30+cm12),2) -   pow((cm21+cm03),2) );
    dest[huMoments::hu6] = (cm20-cm02)*( pow((cm30+cm12),2) - pow((cm21+cm03),2) )
                         + 4*cm11*(cm30+cm12)*(cm21+cm03);
    dest[huMoments::hu7] = (3*cm21-cm03)*(cm30+cm12)*(   pow((cm30+cm12),2) - 3*pow((cm21+cm03),2) )
                         - (cm30-3*cm12)*(cm21+cm03)*( 3*pow((cm30+cm12),2) -   pow((cm21+cm03),2) );


    double temp = sqrt( (cm20 - cm02)*(cm20 - cm02) + 4*cm11*cm11 );
    more[huMoments::eigen1]=m00*0.5*((cm20+cm02) + temp); //eigen 1
    more[huMoments::eigen2]=m00*0.5*((cm20+cm02) - temp); //eigen 2
    more[huMoments::orientation]=0.5*atan2(2*cm11, cm20 - cm02); //orientation
    more[huMoments::m00]=m00; //m00

    const parameters& param = getParameters();

    if (param.scaling) {
      int i;
      for (i=0; i<dest.size();i++){
        dest[i]=-logn(dest[i]);
      }
    }

    return true;
  }