1

I'm stuck porting code from one of the answers from Python to C++ and I was hoping someone can help do that and also clarify a part of the process.

The answer I'm talking about - https://stackoverflow.com/a/11366549

I'm at the step where centroids are being sorted (one before the last). The code in question does the job, but I'm unsure how to get the same result using C++ without making the code much longer.

centroids = np.array(centroids,dtype = np.float32)
c = centroids.reshape((100,2))
c2 = c[np.argsort(c[:,1])]

b = np.vstack([c2[i*10:(i+1)*10][np.argsort(c2[i*10:(i+1)*10,0])] for i in xrange(10)])
bm = b.reshape((10,10,2))

The way I want to achieve this is doing following:

  • The initial centroids array is already sorted in a way (highest y value Point has the index 0, the lowest has 99), so I'd like to invert it, making the array sorted top to bottom.

  • After that it's just a matter of sorting through rows (sorting 10 rows with 10 columns by x axis)

I believe that's all that has to be done, but I cannot find an elegant way to code this (without using vector, and sorting manually).

I also don't quite understand the last step, where the image is being warped (making it hard to port), so if anyone could provide some insight as to what's being done in this part and possibly C++ equivalent to this, I'd appreciate it.

output = np.zeros((450,450,3),np.uint8)
for i,j in enumerate(b):
    ri = i/10
    ci = i%10
    if ci != 9 and ri!=9:
        src = bm[ri:ri+2, ci:ci+2 , :].reshape((4,2))
        dst = np.array( [ [ci*50,ri*50],[(ci+1)*50-1,ri*50],[ci*50,(ri+1)*50-1],[(ci+1)*50-1,(ri+1)*50-1] ], np.float32)
        retval = cv2.getPerspectiveTransform(src,dst)
        warp = cv2.warpPerspective(res2,retval,(450,450))
        output[ri*50:(ri+1)*50-1 , ci*50:(ci+1)*50-1] = warp[ri*50:(ri+1)*50-1 , ci*50:(ci+1)*50-1].copy()

I'm just learning both OpenCV and C++, and I know this is probably trivial so I hope someone can spare some time and provide somewhat basic answer.

EDIT

As per request, here's the code. I've dealt with the first part, still unsure if this is the right way to go.

#pragma mark Correcting the defects
findContours(res, contours, RETR_LIST, CHAIN_APPROX_SIMPLE);
vector<cv::Point> centroids;
centroids.reserve(100);

for (int i = 0; i < contours.size(); i++) {
    vector<cv::Point> contour = contours.at(i);
    Moments mom = moments(contour);
    cv::Point center = cv::Point(int(mom.m10 / mom.m00), int(mom.m01 / mom.m00));
    centroids.push_back(center);
}

std::reverse(centroids.begin(), centroids.end());

struct {
    bool operator()(const cv::Point p1, const cv::Point p2) {
        return p1.x < p2.x;
    }
} pointXGreater;

for (int i = 0; i < 10; i++) {
    std::sort(centroids.begin() + i * 10, centroids.begin() + (i + 1) * 10, pointXGreater);
}

Mat b(centroids);
Mat bm = b.reshape(10, 10);

After drawing the centroids on the image with their indices, it seems that they are correct.

Now I'm stuck on the last part trying to decipher Python code not really knowing what it does. So far I got this:

Mat output = Mat::zeros(450, 450, CV_8U);

for (int i = 0; i < centroids.size(); i++) {
    cv::Point j = centroids.at(i);

    int ri = i / 10;
    int ci = i % 10;

    if (ci != 9 && ri != 9) {
        Mat src = ??
        Mat dst = ??
        Mat retval = getPerspectiveTransform(src, dst);
        Mat warp;
        warpPerspective(res2, warp, retval, (450, 450));
        Mat output = ??
    }
}

I'll keep on trying to make sense of it, but some help would really be appreciated since this kind of Python syntax isn't very friendly especially if you don't really know what's being done.

4

1 回答 1

1

经过一段时间的头部撞击后,这就是我想出的(似乎有效)

#pragma mark Correcting the defects
findContours(res, contours, RETR_LIST, CHAIN_APPROX_SIMPLE);
vector<cv::Point> centroids;
centroids.reserve(100);

for (int i = 0; i < contours.size(); i++) {
    vector<cv::Point> contour = contours.at(i);
    Moments mom = moments(contour);
    cv::Point center = cv::Point(int(mom.m10 / mom.m00), int(mom.m01 / mom.m00));
    centroids.push_back(center);
}

std::reverse(centroids.begin(), centroids.end());

struct {
    bool operator()(const cv::Point p1, const cv::Point p2) {
        return p1.x < p2.x;
    }
} pointXGreater;

for (int i = 0; i < 10; i++) {
    std::sort(centroids.begin() + i * 10, centroids.begin() + (i + 1) * 10, pointXGreater);
}

Mat bm = Mat(centroids);
bm = bm.reshape(2, 10);

Mat output(450, 450, CV_8UC3, CV_RGB(1, 1, 1));

for (int i = 0; i < centroids.size(); i++) {
    int ri = i / 10;
    int ci = i % 10;

    if (ci != 9 && ri != 9) {
        cv::Point2f src[4];
        src[0] = cv::Point2f(bm.at<cv::Point>(ri, ci).x, bm.at<cv::Point>(ri, ci).y);
        src[1] = cv::Point2f(bm.at<cv::Point>(ri, ci + 1).x, bm.at<cv::Point>(ri, ci + 1).y);
        src[2] = cv::Point2f(bm.at<cv::Point>(ri + 1, ci).x, bm.at<cv::Point>(ri + 1, ci).y);
        src[3] = cv::Point2f(bm.at<cv::Point>(ri + 1, ci + 1).x, bm.at<cv::Point>(ri + 1, ci + 1).y);

        cv::Point2f dst[4];
        dst[0] = cv::Point2f(ci * 50, ri * 50);
        dst[1] = cv::Point2f((ci + 1) * 50 - 1, ri * 50);
        dst[2] = cv::Point2f(ci * 50, (ri + 1) * 50 - 1);
        dst[3] = cv::Point2f((ci + 1) * 50 - 1, (ri + 1) * 50 - 1);

        Mat retval = getPerspectiveTransform(src, dst);
        Mat warp;
        warpPerspective(res2, warp, retval, cv::Size(450, 450));

        for (int j = ri * 50; j < (ri + 1) * 50 - 1; j++) {
            for (int k = ci * 50; k < (ci + 1) * 50 - 1; k++) {
                output.at<Vec3b>(j, k) = warp.at<Vec3b>(j, k);
            }
        }
    }
}
于 2013-08-31T18:38:42.750 回答