c# - Detect display corners with Emgu -
i want detect display on image (more precisely corners). segment image in display color , not display color:
image<gray, byte> segmentedimage = greyimage.inrange(new gray(180), new gray(255)); then use corner harris find corners:
emgu.cv.image<emgu.cv.structure.gray, byte> harrisimage = new image<emgu.cv.structure.gray, byte>(greyimage.size); cvinvoke.cornerharris(segmentedimage, harrisimage, 2); cvinvoke.normalize(harrisimage, harrisimage, 0, 255, normtype.minmax, depthtype.cv32f); there white pixels in corners, cannot access them:
for (int j = 0; j < harrisimage.rows; j++) { (int = 0; < harrisimage.cols; i++) { console.writeline(harrisimage[j, i].intensity); } } it writes 0s. how can access them? , if can access them, how can find 4 corners of screen in harris image? there function find perspectively transformed rectangle points?
edit:
on opencv irc said findcontours not precise. , when try run on segmentedimage, this:
(ran findcontours on segmentedimage, approxpolydp , drew found contour on original greyscale image)
cannot find contours more precise...
edit2: cannot work me. code, exact same result... here full emgu code:
emgu.cv.image<emgu.cv.structure.gray, byte> imageframegrey = new image<emgu.cv.structure.gray, byte>(bitmap); image<gray, byte> segmentedimage = imageframegrey.inrange(new gray(180), new gray(255)); // rid of small objects int morph_size = 2; mat element = cvinvoke.getstructuringelement(emgu.cv.cvenum.elementshape.rectangle, new system.drawing.size(2 * morph_size + 1, 2 * morph_size + 1), new system.drawing.point(morph_size, morph_size)); cvinvoke.morphologyex(segmentedimage, segmentedimage, emgu.cv.cvenum.morphop.open, element, new system.drawing.point(-1, -1), 1, emgu.cv.cvenum.bordertype.default, new mcvscalar()); // find edges form rectangles list<rotatedrect> boxlist = new list<rotatedrect>(); using (vectorofvectorofpoint contours = new vectorofvectorofpoint()) { cvinvoke.findcontours(segmentedimage, contours, null, emgu.cv.cvenum.retrtype.external, chainapproxmethod.chainapproxsimple); int count = contours.size; (int = 0; < count; i++) { using (vectorofpoint contour = contours[i]) using (vectorofpoint approxcontour = new vectorofpoint()) { cvinvoke.approxpolydp(contour, approxcontour, cvinvoke.arclength(contour, true) * 0.01, true); if (cvinvoke.contourarea(approxcontour, false) > 10000) { if (approxcontour.size == 4) { bool isrectangle = true; system.drawing.point[] pts = approxcontour.toarray(); linesegment2d[] edges = emgu.cv.pointcollection.polyline(pts, true); (int j = 0; j < edges.length; j++) { double angle = math.abs(edges[(j + 1) % edges.length].getexteriorangledegree(edges[j])); if (angle < 80 || angle > 100) { isrectangle = false; break; } } if (isrectangle) boxlist.add(cvinvoke.minarearect(approxcontour)); } } } } }
so promised tried myself. in c++ should adopt easy emgu. first rid of small object in segmented image opening:
int morph_elem = cv_shape_rect; int morph_size = 2; mat element = getstructuringelement(morph_elem, size(2 * morph_size + 1, 2 * morph_size + 1), point(morph_size, morph_size)); // apply opening morphologyex(segmentedimage, segmentedimage_open, cv_mop_open, element); then detect contours , take large ones , check rectangular shape:
vector< vector<point>> contours; findcontours(segmentedimage_open, contours, cv_retr_external, cv_chain_approx_simple); each (vector<point> var in contours) { double area = contourarea(var); if (area> 30000) { vector<point> approx; approxpolydp(var, approx, 0.01*arclength(var, true), true); if (4 == approx.size()) //rectangular shape { // } } } here result contour in red , approximated curve in green:
edit:
you can improve code increasing approximation factor until contour 4 points or pass threshold. wrap loop around approxpolydp. can define range approximation value , prevent code fail if object differs rectangle.



Comments
Post a Comment