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 からの座標は必要ありません。balck で検出されたオブジェクトの周りに描画される輪郭の座標にアクセスしたい

輪郭自体の座標を取得する方法を教えてください。

コード_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;
}

}

画像_1 :

ここに画像の説明を入力

画像_2 :

ここに画像の説明を入力

更新 私は境界四角形の座標を持ちたくありません。私が欲しいのは、黒い輪郭の正確な座標です。image_3に示すように、コードから取得している座標は、赤と黄色の円がある場所です..しかし、黒い線の「輪郭」の座標にアクセスできるように探しているので、に示すように円を描くことができます画像_3. 緑色のスポットは、座標を取得したい場所を示すためのものです。

画像_3 :

ここに画像の説明を入力

4

1 に答える 1

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]);
于 2016-12-25T17:32:11.290 に答える