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