c# - Emgu object detection using MatchShapes for connected components with holes -
i've been working on shape matching function, using emgu, detecting objects given template of object , target image in find it. target image can contain multiple instances of template.
the function built works reasonably well. have 1 concern. if template has more 1 hole, function not give correct answer.
here important part of code:
private image<bgr, byte> drawcontours(image<gray, byte> image, contour<point> contours, bgr color, int thickness, int maxlevel) { image<bgr, byte> resultimage = new image<bgr, byte>(image.size); resultimage = image.convert<bgr, byte>(); cvinvoke.cvdrawcontours(resultimage, contours, color.mcvscalar, color.mcvscalar, maxlevel, thickness, line_type.cv_aa, new point(0, 0)); return resultimage; } private contour<point> getedgecontours(image<gray, byte> image, image<gray, byte> mask, int threshold) { cvinvoke.cvthreshold(image, image, 255, 255, thresh.cv_thresh_binary | thresh.cv_thresh_otsu); image = image.dilate(3).erode(3); contour<point> cont = image.findcontours(chain_approx_method.cv_chain_approx_tc89_l1, retr_type.cv_retr_ccomp); return cont; } private polygon mcvbox2d2polygon(mcvbox2d box) { system.windows.media.pointcollection polypoints = new system.windows.media.pointcollection(); foreach (var p in box.getvertices()) polypoints.add(new system.windows.point(p.x, p.y)); polygon poly = new polygon(); poly.points = polypoints; return poly; } private bool processshapematching(ref image<gray, byte> templateimage , out image<gray, byte> targetimage) { positions = new list<polygon>(); contour<point> templatecontours = getedgecontours(templateimage, null, 100); contour<point> targetcontours = getedgecontours(targetimage, maskimage, 100); mcvbox2d box = templatecontours.getminarearect(); double precision = 0.0001; double distancethreshold = 0.4; int nccomplevels = 2; // connected components have 2 levels. 1 of outer boundary en possibly 1 inner boundaries (holes) using (memstorage storage = new memstorage()) //allocate storage contour approximation { //find largest connected component countour in template contour<point> templatecontour = new contour<point>(storage); double largestarea = 0; (contour<point> cont = templatecontours; cont != null; cont = cont.hnext) if (cont.area > largestarea) templatecontour = cont; if (templatecontour == null) throw new nullreferenceexception("no contours found in template image"); // reduce nr of vertices in template polygons templatecontour = templatecontour.approxpoly(templatecontour.perimeter * precision, nccomplevels, storage); // reduce nr of vertices in target polygons if (templatecontour.area > targetimage.height * targetimage.width / 1000) //only consider contours plausible area { double distance = 0; (contour<point> targetcontour = targetcontours; targetcontour != null; targetcontour = targetcontour.hnext) { if (targetcontour.area < targetimage.height * targetimage.width / 1000) //only consider contours plausible area continue; contour<point> approximatedtargetcontour = targetcontour.approxpoly(targetcontour.perimeter * precision, nccomplevels, storage); distance += templatecontour.matchshapes(approximatedtargetcontour, contours_match_type.cv_contours_match_i3); imageviewer.show(drawcontours(targetimage, approximatedtargetcontour, new bgr(color.cyan), 2, 0), "contour"); //this smelly part, works when number of holes in template 0 or 1 // in template , target shapes if ((templatecontour.vnext != null) && (targetcontour.vnext != null)) distance += templatecontour.matchshapes(approximatedtargetcontour, contours_match_type.cv_contours_match_i3); if ((templatecontour.vnext != null) && (targetcontour.vnext == null)) continue; // no match if ((templatecontour.vnext == null) && (targetcontour.vnext != null)) continue; // no match //http://stackoverflow.com/questions/15555615/equivalent-of-hierarchy-in-emgu if (distance > distancethreshold) continue; // have match, let's add position positions.add(mcvbox2d2polygon(targetcontour.getminarearect())); // draw annotation image<bgr, byte> imageanotated = drawcontours(targetimage, approximatedtargetcontour, new bgr(color.salmon), 2, nccomplevels); mcvbox2d boxi = approximatedtargetcontour.getminarearect(); imageanotated.draw(boxi, new bgr(color.turquoise), 2); imageviewer.show(imageanotated, string.format("current contour {0}", distance)); } } } return false; }
i hoping suggestions on how compare innards of shape, meaning holes in connected component. maybe there standard ways overlooking?
thanks in advance!
Comments
Post a Comment