@@ -275,24 +275,18 @@ void ERFilterNM::er_tree_extract( InputArray image )
275275 // the component stack
276276 vector<ERStat*> er_stack;
277277
278- // the quads for euler number calculation
279- unsigned char quads[3 ][4 ];
280- quads[0 ][0 ] = 1 << 3 ;
281- quads[0 ][1 ] = 1 << 2 ;
282- quads[0 ][2 ] = 1 << 1 ;
283- quads[0 ][3 ] = 1 ;
284- quads[1 ][0 ] = (1 <<2 )|(1 <<1 )|(1 );
285- quads[1 ][1 ] = (1 <<3 )|(1 <<1 )|(1 );
286- quads[1 ][2 ] = (1 <<3 )|(1 <<2 )|(1 );
287- quads[1 ][3 ] = (1 <<3 )|(1 <<2 )|(1 <<1 );
288- quads[2 ][0 ] = (1 <<2 )|(1 <<1 );
289- quads[2 ][1 ] = (1 <<3 )|(1 );
290- // quads[2][2] and quads[2][3] are never used so no need to initialize them.
278+ // the quads for euler number calculation
279+ // quads[2][2] and quads[2][3] are never used.
291280 // The four lowest bits in each quads[i][j] correspond to the 2x2 binary patterns
292281 // Q_1, Q_2, Q_3 in the Neumann and Matas CVPR 2012 paper
293282 // (see in page 4 at the end of first column).
294283 // Q_1 and Q_2 have four patterns, while Q_3 has only two.
295-
284+ const int quads[3 ][4 ] =
285+ {
286+ { 1 <<3 , 1 <<2 , 1 <<1 , 1 <<0 },
287+ { (1 <<2 )|(1 <<1 )|(1 ), (1 <<3 )| (1 <<1 )|(1 ), (1 <<3 )|(1 <<2 )| (1 ), (1 <<3 )|(1 <<2 )|(1 <<1 ) },
288+ { (1 <<2 )|(1 <<1 ) , (1 <<3 )| (1 ), /* unused*/ -1 , /* unused*/ -1 }
289+ };
296290
297291 // masks to know if a pixel is accessible and if it has been already added to some region
298292 vector<bool > accessible_pixel_mask (width * height);
@@ -392,8 +386,8 @@ void ERFilterNM::er_tree_extract( InputArray image )
392386 int non_boundary_neighbours = 0 ;
393387 int non_boundary_neighbours_horiz = 0 ;
394388
395- unsigned char quad_before[4 ] = {0 ,0 ,0 ,0 };
396- unsigned char quad_after[4 ] = {0 ,0 ,0 ,0 };
389+ int quad_before[4 ] = {0 ,0 ,0 ,0 };
390+ int quad_after[4 ] = {0 ,0 ,0 ,0 };
397391 quad_after[0 ] = 1 <<1 ;
398392 quad_after[1 ] = 1 <<3 ;
399393 quad_after[2 ] = 1 <<2 ;
@@ -542,9 +536,9 @@ void ERFilterNM::er_tree_extract( InputArray image )
542536 current_edge = boundary_edges[threshold_level].back ();
543537 boundary_edges[threshold_level].erase (boundary_edges[threshold_level].end ()-1 );
544538
545- while (boundary_pixes[threshold_level]. empty () && ( threshold_level < (255 /thresholdDelta)+1 ) )
546- threshold_level++;
547-
539+ for (; threshold_level < (255 /thresholdDelta)+1 ; threshold_level++ )
540+ if (!boundary_pixes[ threshold_level]. empty ())
541+ break ;
548542
549543 int new_level = image_data[current_pixel];
550544
@@ -784,28 +778,27 @@ ERStat* ERFilterNM::er_save( ERStat *er, ERStat *parent, ERStat *prev )
784778// recursively walk the tree and filter (remove) regions using the callback classifier
785779ERStat* ERFilterNM::er_tree_filter ( InputArray image, ERStat * stat, ERStat *parent, ERStat *prev )
786780{
787- Mat src = image.getMat ();
788781 // assert correct image type
789- CV_Assert ( src.type () == CV_8UC1 );
782+ CV_Assert ( image.type () == CV_8UC1 );
783+
784+ Mat src = image.getMat ();
790785
791786 // Fill the region and calculate 2nd stage features
792- Mat region = region_mask (Rect (Point ( stat->rect .x ,stat-> rect . y ), Point ( stat->rect .br (). x + 2 ,stat-> rect . br (). y + 2 )));
787+ Mat region = region_mask (Rect (stat->rect .tl (), stat->rect .br () + Point ( 2 , 2 )));
793788 region = Scalar (0 );
794789 int newMaskVal = 255 ;
795790 int flags = 4 + (newMaskVal << 8 ) + FLOODFILL_FIXED_RANGE + FLOODFILL_MASK_ONLY;
796791 Rect rect;
797792
798- floodFill ( src (Rect ( Point ( stat->rect . x ,stat-> rect . y ), Point (stat-> rect . br (). x ,stat-> rect . br (). y )) ),
799- region, Point (stat->pixel %src.cols - stat-> rect . x , stat->pixel /src.cols - stat->rect .y ),
793+ floodFill ( src (stat->rect ),
794+ region, Point (stat->pixel %src.cols , stat->pixel /src.cols ) - stat->rect .tl ( ),
800795 Scalar (255 ), &rect, Scalar (stat->level ), Scalar (0 ), flags );
801- rect.width += 2 ;
802- rect.height += 2 ;
803- region = region (rect);
796+ region = region (Rect (1 , 1 , rect.width , rect.height ));
804797
805798 vector<vector<Point> > contours;
806799 vector<Point> contour_poly;
807800 vector<Vec4i> hierarchy;
808- findContours ( region ( Rect ( 1 , 1 , region. cols - 2 , region. rows - 2 )), contours, hierarchy, RETR_TREE, CHAIN_APPROX_NONE, Point (1 , 1 ) );
801+ findContours ( region, contours, hierarchy, RETR_TREE, CHAIN_APPROX_NONE, Point (0 , 0 ) );
809802 // TODO check epsilon parameter of approxPolyDP (set empirically) : we want more precission
810803 // if the region is very small because otherwise we'll loose all the convexities
811804 approxPolyDP ( Mat (contours[0 ]), contour_poly, (float )min (rect.width ,rect.height )/17 , true );
@@ -2859,9 +2852,7 @@ bool guo_hall_thinning(const Mat1b & img, Mat& skeleton)
28592852}
28602853
28612854
2862- float extract_features (Mat &grey, Mat& channel, vector<ERStat> ®ions, vector<ERFeatures> &features);
2863-
2864- float extract_features (Mat &grey, Mat& channel, vector<ERStat> ®ions, vector<ERFeatures> &features)
2855+ static float extract_features (Mat &grey, Mat& channel, vector<ERStat> ®ions, vector<ERFeatures> &features)
28652856{
28662857 // assert correct image type
28672858 CV_Assert (( channel.type () == CV_8UC1 ) && ( grey.type () == CV_8UC1 ));
@@ -2890,18 +2881,15 @@ float extract_features(Mat &grey, Mat& channel, vector<ERStat> ®ions, vector<
28902881 {
28912882
28922883 // Fill the region and calculate features
2893- Mat region = region_mask (Rect (Point ( stat->rect .x ,stat-> rect . y ),
2894- Point ( stat->rect .br (). x + 2 ,stat-> rect . br (). y + 2 )));
2884+ Mat region = region_mask (Rect (stat->rect .tl ( ),
2885+ stat->rect .br () + Point ( 2 , 2 )));
28952886 region = Scalar (0 );
28962887 int newMaskVal = 255 ;
28972888 int flags = 4 + (newMaskVal << 8 ) + FLOODFILL_FIXED_RANGE + FLOODFILL_MASK_ONLY;
2898- Rect rect;
28992889
2900- floodFill ( channel (Rect ( Point ( stat->rect . x ,stat-> rect . y ), Point (stat-> rect . br (). x ,stat-> rect . br (). y )) ),
2890+ floodFill ( channel (stat->rect ),
29012891 region, Point (stat->pixel %channel.cols - stat->rect .x , stat->pixel /channel.cols - stat->rect .y ),
2902- Scalar (255 ), &rect, Scalar (stat->level ), Scalar (0 ), flags );
2903- rect.width += 2 ;
2904- rect.height += 2 ;
2892+ Scalar (255 ), NULL , Scalar (stat->level ), Scalar (0 ), flags );
29052893 Mat rect_mask = region_mask (Rect (stat->rect .x +1 ,stat->rect .y +1 ,stat->rect .width ,stat->rect .height ));
29062894
29072895
@@ -2911,7 +2899,7 @@ float extract_features(Mat &grey, Mat& channel, vector<ERStat> ®ions, vector<
29112899 f.intensity_std = (float )std[0 ];
29122900
29132901 Mat tmp,bw;
2914- region_mask ( Rect (stat-> rect . x + 1 ,stat-> rect . y + 1 ,stat-> rect . width ,stat-> rect . height )) .copyTo (bw);
2902+ rect_mask .copyTo (bw);
29152903 distanceTransform (bw, tmp, DIST_L1,3 ); // L1 gives distance in round integers while L2 floats
29162904
29172905 // Add border because if region span all the image size skeleton will crash
@@ -3513,19 +3501,16 @@ bool isValidPair(Mat &grey, Mat &lab, Mat &mask, vector<Mat> &channels, vector<
35133501 i = ®ions[idx1[0 ]][idx1[1 ]];
35143502 j = ®ions[idx2[0 ]][idx2[1 ]];
35153503
3516- Mat region = mask (Rect (Point ( i->rect .x ,i-> rect . y ),
3517- Point ( i->rect .br (). x + 2 ,i-> rect . br (). y + 2 )));
3504+ Mat region = mask (Rect (i->rect .tl ( ),
3505+ i->rect .br ()+ Point ( 2 , 2 )));
35183506 region = Scalar (0 );
35193507
35203508 int newMaskVal = 255 ;
35213509 int flags = 4 + (newMaskVal << 8 ) + FLOODFILL_FIXED_RANGE + FLOODFILL_MASK_ONLY;
3522- Rect rect;
35233510
3524- floodFill ( channels[idx1[0 ]](Rect (Point (i->rect .x ,i->rect .y ),Point (i->rect .br ().x ,i->rect .br ().y ))),
3525- region, Point (i->pixel %grey.cols - i->rect .x , i->pixel /grey.cols - i->rect .y ),
3526- Scalar (255 ), &rect, Scalar (i->level ), Scalar (0 ), flags);
3527- rect.width += 2 ;
3528- rect.height += 2 ;
3511+ floodFill ( channels[idx1[0 ]](i->rect ),
3512+ region, Point (i->pixel %grey.cols , i->pixel /grey.cols ) - i->rect .tl (),
3513+ Scalar (255 ), NULL , Scalar (i->level ), Scalar (0 ), flags);
35293514 Mat rect_mask = mask (Rect (i->rect .x +1 ,i->rect .y +1 ,i->rect .width ,i->rect .height ));
35303515
35313516 Scalar mean,std;
@@ -3535,15 +3520,12 @@ bool isValidPair(Mat &grey, Mat &lab, Mat &mask, vector<Mat> &channels, vector<
35353520 float a_mean1 = (float )mean[1 ];
35363521 float b_mean1 = (float )mean[2 ];
35373522
3538- region = mask (Rect (Point (j->rect .x ,j->rect .y ),
3539- Point (j->rect .br ().x +2 ,j->rect .br ().y +2 )));
3523+ region = mask (Rect (j->rect .tl (), j->rect .br ()+ Point (2 ,2 )));
35403524 region = Scalar (0 );
35413525
3542- floodFill ( channels[idx2[0 ]](Rect (Point (j->rect .x ,j->rect .y ),Point (j->rect .br ().x ,j->rect .br ().y ))),
3543- region, Point (j->pixel %grey.cols - j->rect .x , j->pixel /grey.cols - j->rect .y ),
3544- Scalar (255 ), &rect, Scalar (j->level ), Scalar (0 ), flags);
3545- rect.width += 2 ;
3546- rect.height += 2 ;
3526+ floodFill ( channels[idx2[0 ]](j->rect ),
3527+ region, Point (j->pixel %grey.cols , j->pixel /grey.cols ) - j->rect .tl (),
3528+ Scalar (255 ), NULL , Scalar (j->level ), Scalar (0 ), flags);
35473529 rect_mask = mask (Rect (j->rect .x +1 ,j->rect .y +1 ,j->rect .width ,j->rect .height ));
35483530
35493531 meanStdDev (grey (j->rect ),mean,std,rect_mask);
@@ -4181,7 +4163,7 @@ void MSERsToERStats(InputArray image, vector<vector<Point> > &contours, vector<v
41814163void detectRegions (InputArray image, const Ptr<ERFilter>& er_filter1, const Ptr<ERFilter>& er_filter2, CV_OUT vector< vector<Point> >& regions)
41824164{
41834165 // assert correct image type
4184- CV_Assert ( image.getMat (). type () == CV_8UC1 );
4166+ CV_Assert ( image.type () == CV_8UC1 );
41854167 // at least one ERFilter must be passed
41864168 CV_Assert ( !er_filter1.empty () );
41874169
@@ -4195,36 +4177,33 @@ void detectRegions(InputArray image, const Ptr<ERFilter>& er_filter1, const Ptr<
41954177 }
41964178
41974179 // Convert each ER to vector<Point> and push it to output regions
4198- Mat src = image.getMat ();
4199- Mat region_mask = Mat::zeros (src.rows +2 , src.cols +2 , CV_8UC1);
4180+ const Mat src = image.getMat ();
42004181 for (size_t i=1 ; i < ers.size (); i++) // start from 1 to deprecate root region
42014182 {
42024183 ERStat* stat = &ers[i];
42034184
42044185 // Fill the region and calculate 2nd stage features
4205- Mat region = region_mask (Rect (Point (stat->rect .x ,stat->rect .y ),Point (stat->rect .br ().x +2 ,stat->rect .br ().y +2 )));
4206- region = Scalar (0 );
4186+ Mat region_mask (Size (stat->rect .width + 2 , stat->rect .height + 2 ), CV_8UC1, Scalar (0 ));
4187+ Mat region = region_mask (Rect (1 , 1 , stat->rect .width , stat->rect .height ));
4188+
42074189 int newMaskVal = 255 ;
42084190 int flags = 4 + (newMaskVal << 8 ) + FLOODFILL_FIXED_RANGE + FLOODFILL_MASK_ONLY;
4209- Rect rect;
42104191
4211- floodFill ( src (Rect (Point (stat->rect .x ,stat->rect .y ),Point (stat->rect .br ().x ,stat->rect .br ().y ))),
4212- region, Point (stat->pixel %src.cols - stat->rect .x , stat->pixel /src.cols - stat->rect .y ),
4213- Scalar (255 ), &rect, Scalar (stat->level ), Scalar (0 ), flags );
4214- rect.width += 2 ;
4215- rect.height += 2 ;
4216- region = region (rect);
4192+ const Point seed_pt (stat->pixel %src.cols , stat->pixel /src.cols );
4193+ uchar seed_v = src.at <uchar>(seed_pt);
4194+ CV_Assert ((int )seed_v <= stat->level );
4195+
4196+ floodFill ( src (stat->rect ),
4197+ region_mask,
4198+ seed_pt - stat->rect .tl (),
4199+ Scalar (255 ), NULL , Scalar (/* stat->level*/ 255 ), Scalar (0 ), flags );
42174200
42184201 vector<vector<Point> > contours;
42194202 vector<Vec4i> hierarchy;
4220- findContours ( region, contours, hierarchy, RETR_TREE, CHAIN_APPROX_NONE, Point (0 , 0 ) );
4221-
4222- for (size_t j=0 ; j < contours[0 ].size (); j++)
4223- contours[0 ][j] += (stat->rect .tl ()-Point (1 ,1 ));
4203+ findContours ( region, contours, hierarchy, RETR_TREE, CHAIN_APPROX_NONE, stat->rect .tl () );
42244204
42254205 regions.push_back (contours[0 ]);
42264206 }
4227-
42284207}
42294208
42304209}
0 commit comments