【问题标题】:how to get the coordinates of a contour如何获取轮廓的坐标
【发布时间】:2017-03-11 05:18:34
【问题描述】:

我使用的是 OpenCV4Android 2.4.11 版,并且正在检测相机检索到的帧中的任何矩形形状。如下图 1 所示,我在检测到的对象周围绘制了黑色轮廓,以及我想要做什么 也就是说,要获得绘制轮廓的所有坐标,只绘制黑色。我尝试的是,如下面的 code_1 所示,我得到最大轮廓和最大轮廓的索引并将它们保存在 “最大轮廓”和“最大轮廓索引”。然后,我使用

绘制轮廓
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));
    }

查找角:

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:

image_2:

更新 我不想拥有边界矩形的坐标,我想要的是黑色轮廓的确切坐标。如图 3 所示,我从代码中获得的坐标是红色和黄色圆圈所在的位置..但我正在寻找能够访问黑线“轮廓”的坐标,因此我可以在其上绘制一些圆圈,如图所示图像_3。绿色的点只是为了告诉你我想要的坐标。

image_3:

【问题讨论】:

  • 应该给我较小的 x 坐标、最小的 y 坐标、最大的 x 坐标和最大的 y 坐标。 这些是坐标的边界框。您可能想要 approxPolyDP 之后的 4 个角来代替
  • @Miki 正如您在我的代码中看到的那样,我有以下行“Imgproc.approxPolyDP(contour2f, approxCurve, approxDistance, true);”黑色轮廓是否包含在“approxCurve”中??
  • 黑色轮廓为largestContour
  • @Miki 但是当将“largestContour”传递给 this.mFindCorners = new FindCorners(largestContour.toArray());双 [] 线 = this.mFindCorners.getCords();当我围绕存储在“绳索”中的坐标画一个圆圈时,我得到像 image_2 中所示的角,边界矩形不是黑色轮廓
  • 现在在FindCorners 中,您正在计算黑色计数的边界矩形,然后在左上角和右下角绘制圆圈。如果这不是您想要做的,您究竟想要做什么?您可以发布一张您手动绘制您想要获得的点的图像吗?

标签: opencv image-processing object-detection opencv4android opencv-contour


【解决方案1】:

您的问题是您已经分别对 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]);

【讨论】:

    猜你喜欢
    • 2015-07-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多