0

我正在使用OpenCV4Android版本2.4.11,我正在检测由相机检索的帧中的任何矩形形状。如下图image_1所示,我在被检测物体周围绘制了一个黑色轮廓,并且我正在尝试执行的操作是获取绘制轮廓的所有坐标,这个坐标只能以黑色绘制。我试过的是,如下面code_1所示,我得到最大轮廓和最大轮廓的索引,并分别将它们保存在 “largestContour”和“largest_contour_index”中。然后,我用如何获得轮廓的坐标

Imgproc.drawContours(mMatInputFrame, contours, largest_contour_index, new Scalar(0, 0, 0), 2, 8, hierachy, 0, new Point()); 

画出轮廓,然后我通过最大轮廓类FindCorners的点,因为我想找到在黑画出的轮廓的具体坐标如下:

this.mFindCorners = new FindCorners(largestContour.toArray()); 
double[] cords = this.mFindCorners.getCords(); 

下面的代码行:

double[] cords = this.mFindCorners.getCords(); 

应该给我小了x坐标,最小y坐标,最大x坐标和最大y坐标。但是当我围绕我从“this.mFindCorners.getCords()获得的坐标绘制一个圆圈;”我在下面的image_2中找到了类似 的东西,这只是BoundingRect的边角。

其实我不想从boundingRect我希望能够访问到被探测到的物体围绕在巴尔克画出的轮廓的坐标

请让我知道如何让轮廓的坐标的任何坐标本身?

code_1

if (contours.size() > 0) { 
     for (int i = 0; i < contours.size(); i++) { 
      contour2f = new MatOfPoint2f(contours.get(i).toArray()); 
      approxDistance = Imgproc.arcLength(contour2f, true) * .01;//.02 
      approxCurve = new MatOfPoint2f(); 
      Imgproc.approxPolyDP(contour2f, approxCurve, approxDistance, true); 
      points = new MatOfPoint(approxCurve.toArray()); 

      double area = Math.abs(Imgproc.contourArea(points, true)); 
      if (points.total() >= 4 && area >= 40000 && area <= 200000) { 
       if (area > largest_area) { 
        largest_area = area; 
        largest_contour_index = i; 
        pointsOfLargestContour = points; 
        largestContour = contours.get(i); 
       } 
      } 
     } 

     if (largest_area > 0) { 
      Imgproc.drawContours(mMatInputFrame, contours, largest_contour_index, new Scalar(0, 0, 0), 2, 8, hierachy, 0, new Point()); 

      this.mFindCorners = new FindCorners(largestContour.toArray()); 
      double[] cords = this.mFindCorners.getCords(); 

      Core.circle(mMatInputFrame, new Point(cords[0], cords[1]), 10, new Scalar(255, 0, 0)); 
      Core.circle(mMatInputFrame, new Point(cords[2], cords[3]), 10, new Scalar(255, 255, 0)); 
     } 

FindCorners

public class FindCorners { 
private final static String TAG = FragOpenCVCam.class.getSimpleName(); 

private ArrayList<Double> mlistXCords = null; 
private ArrayList<Double> mlistYCords = null; 
private double mSmallestX; 
private double mSmallestY; 
private double mLargestX; 
private double mLargestY; 
private double[] mCords = null; 

public FindCorners(Point[] points) { 
    this.mlistXCords = new ArrayList<>(); 
    this.mlistYCords = new ArrayList<>(); 
    this.mCords = new double[4]; 

    Log.d(TAG, "points.length: " + points.length); 

    for (int i = 0; i < points.length; i++) { 
     this.mlistXCords.add(points[i].x); 
     this.mlistYCords.add(points[i].y); 
    } 

    //ascending 
    Collections.sort(this.mlistXCords); 
    Collections.sort(this.mlistYCords); 

    this.mSmallestX = this.mlistXCords.get(0); 
    this.mSmallestY = this.mlistYCords.get(0); 
    this.mLargestX = this.mlistXCords.get(this.mlistXCords.size() - 1); 
    this.mLargestY = this.mlistYCords.get(this.mlistYCords.size() - 1); 

    this.mCords[0] = this.mSmallestX; 
    this.mCords[1] = this.mSmallestY; 
    this.mCords[2] = this.mLargestX; 
    this.mCords[3] = this.mLargestY; 
} 

public double[] getCords() { 
    return this.mCords; 
} 

}

IMAGE_1

enter image description here

IMAGE_2

enter image description here

更新 我不希望有边界矩形的坐标,我想有是,黑色轮廓的精确坐标。如image_3所示,我从代码中得到的坐标是红色和黄色圆圈所在的位置......但我正在寻找可以访问黑色“轮廓线”的坐标,以便我可以在其上画一些圆圈IMAGE_3。绿色的斑点只是为了向你展示我想要坐标的位置。

IMAGE_3

enter image description here

+0

_should给我小了x坐标,最小y坐标,最大x坐标和最大Y型coordinates._这些** **是边界的坐标框。你可能需要'approxPolyDP'后面的4个角,而不是像你在我的代码中看到的 – Miki

+0

@Miki,我有以下行:“Imgproc.approxPolyDP(contour2f,approxCurve,approxDistance,true);”是“approxCurve”中的黑色轮廓包络? – user2121

+0

黑色轮廓是'largestContour' – Miki

回答

0

你的问题是,你已分别排序X和Y的和显而易见的是,你的算法会发现红色和黄色的点。 我可以建议如下算法:

int min_x=INF, min_x_index, min_y=1000, min_y_index; 
int max_x=-1, max_x_index, max_y=-1, max_y_index; 
for (int i = 0; i < points.length; i++) 
    { 
     if(points[i].x < min_x) { min_x = points[i].x; min_x_index = i; } 
     if(points[i].x > max_x) { max_x = points[i].x; max_x_index = i; } 
     if(points[i].y < min_y) { min_y = points[i].y; min_y_index = i; } 
     if(points[i].y > max_y) { max_y = points[i].y; max_y_index = i; } 
    } 
Point corner1(points[min_x_index]); 
Point corner2(points[min_y_index]); 
Point corner3(points[max_x_index]); 
Point corner4(points[max_y_index]);