7

2つ(またはそれ以上)の近くの輪郭を接続する機能はありますか?私の入力/出力を見てください。私が何を意味するのかがわかります…</p>

私のコード:

[... some processing ...]

// getting contours
std::vector<std::vector<cv::Point> > contours;
findContours(input, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);

// approximate contours
std::vector<std::vector<cv::Point> > contours_poly( contours.size() );
for( int i = 0; i < contours.size(); i++ ) {
  approxPolyDP(cv::Mat(contours[i]), contours_poly[i], 5, true );
}

// debugging
cv::Scalar colors[3];
colors[0] = cv::Scalar(255, 0, 0);
colors[1] = cv::Scalar(0, 255, 0);
colors[2] = cv::Scalar(0, 0, 255);
for (int idx = 0; idx < contours_poly.size(); idx++) {
  cv::drawContours(output, contours_poly, idx, colors[idx % 3]);
} 

出力 出力

4

2 に答える 2

11

オブジェクト全体の周りにバウンディングボックスが必要なだけなので、このソリューションを思いつきました。

[... some processing ...]

// getting contours
std::vector<std::vector<cv::Point> > contours;
findContours(input, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);

// approximate contours
std::vector<std::vector<cv::Point> > contours_poly( contours.size() );
for( int i = 0; i < contours.size(); i++ ) {
  approxPolyDP(cv::Mat(contours[i]), contours_poly[i], 5, true );
}

// merge all contours into one vector
std::vector<cv::Point> merged_contour_points;
for (int i = 0; i < contours_poly.size(); i++) {
  for (int j = 0; j < contours_poly[i].size(); j++) {
    merged_contour_points.push_back(contours_poly[i][j]);
  }
}

// get rotated bounding box
std::vector<cv::Point> hull;
cv::convexHull(cv::Mat(merged_contour_points),hull);
cv::Mat hull_points(hull);
cv::RotatedRect rotated_bounding_rect = minAreaRect(hull_points);

コショウのノイズを取り除くと、より良い結果が得られる場合があります。

void removePepperNoise(cv::Mat &mask)
{
    for ( int y=2; y<mask.rows-2; y++ ) {
        uchar *pUp2 = mask.ptr(y-2);
        uchar *pUp1 = mask.ptr(y-1);
        uchar *pThis = mask.ptr(y);
        uchar *pDown1 = mask.ptr(y+1);
        uchar *pDown2 = mask.ptr(y+2);
        pThis += 2;
        pUp1 += 2;
        pUp2 += 2;
        pDown1 += 2;
        pDown2 += 2;

        for (int x=2; x<mask.cols-2; x++) {
            uchar value = *pThis; // Get this pixel value (0 or 255). // Check if this is a black pixel that is surrounded by white pixels
            if (value == 0) {
                bool above, left, below, right, surroundings;
                above = *(pUp2 - 2) && *(pUp2 - 1) && *(pUp2) && *(pUp2 + 1) && *(pUp2 + 2);
                left = *(pUp1 - 2) && *(pThis - 2) && *(pDown1 - 2);
                below = *(pDown2 - 2) && *(pDown2 - 1) && *(pDown2) && *(pDown2 + 1) && *(pDown2 + 2);
                right = *(pUp1 + 2) && *(pThis + 2) && *(pDown1 + 2);
                surroundings = above && left && below && right;
                if (surroundings == true) {
                    // Fill the whole 5x5 block as white. Since we know
                    // the 5x5 borders are already white, we just need to
                    // fill the 3x3 inner region.
                    *(pUp1 - 1) = 255;
                    *(pUp1 + 0) = 255;
                    *(pUp1 + 1) = 255;
                    *(pThis - 1) = 255;
                    *(pThis + 0) = 255;
                    *(pThis + 1) = 255;
                    *(pDown1 - 1) = 255;
                    *(pDown1 + 0) = 255;
                    *(pDown1 + 1) = 255;
                    // Since we just covered the whole 5x5 block with
                    // white, we know the next 2 pixels won't be black,
                    // so skip the next 2 pixels on the right.
                    pThis += 2;
                    pUp1 += 2;
                    pUp2 += 2;
                    pDown1 += 2;
                    pDown2 += 2;
                }
            }
            // Move to the next pixel on the right.
            pThis++;
            pUp1++;
            pUp2++;
            pDown1++;
            pDown2++;
        }
    }
}
于 2012-01-25T11:09:27.043 に答える
2

ポイントを通過し、最も近い始点または終点を見つけて、それらを接続するだけです。あなたの場合、輪郭を接続するかどうかを決めるのは難しいです。Adrian Popoviciが言ったような形態が役に立たない場合は、ポイントを接続するかどうかを決定する最大距離を指定する必要があります。

于 2012-01-25T07:22:47.613 に答える