DrawContours странное поведение?

Я отфильтровываю маленькие капли из двоичного изображения (контуры, площадь которых меньше порога). маска - это двоичное изображение.

Если я прокомментирую строку

 drawContours(mask, contours, -1, Scalar(255), CV_FILLED, 8);

тогда я получаю странные результаты, когда сохраняю маску после заполнения 0 маленькими каплями.

Также не понимаю, почему это работает, когда строка не закомментирована, потому что после

drawContours(mask, contours, -1, Scalar(255), CV_FILLED, 8);

маска логически должна совпадать с маской ввода (за исключением границы в 1 пиксель вокруг изображения)

void FilterSmallBlobs(Mat &mask, float minArea)
{
    //as side effect this code extends inner holes with 1 pixel border and removes 1 pixels border from image border.

    vector<vector<Point>> contours;
    //findContours(mask, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);
    findContours(mask, contours, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);

    vector<vector<Point>> badContours; //contours to erase
    for (int i = 0; i < (int)contours.size(); i++)
    {
        if(contourArea(contours[i]) <= minArea)
            badContours.push_back(contours[i]);
    }

    //drawContours(mask, contours, -1, Scalar(255), CV_FILLED, 8);
    drawContours(mask, badContours, -1, Scalar(0), CV_FILLED, 8);
}

что я получаю

что я хочу

Таким образом, я не понимаю, когда drawContours искажает начальную маску, когда я заполняю плохие контуры?

1 ответ

Решение

Как указано в документации для findContours

Примечание. Исходное изображение модифицируется этой функцией.

Таким образом, в вашем случае вы видите некоторые части измененного изображения, в то время как другие части покрыты, поскольку вы рисуете маленькие капли как черные.

Этот фрагмент кода должен прояснить это:

#include <opencv2\opencv.hpp>
using namespace cv;

int main()
{
    Mat1b img = imread("path_to_image", IMREAD_GRAYSCALE);

    vector<vector<Point>> contours;

    Mat1b will_be_modified = img.clone();
    findContours(will_be_modified, contours, RETR_LIST, CHAIN_APPROX_SIMPLE);

    for (int i = 0; i < contours.size(); ++i)
    {
        if (contourArea(contours[i]) < 3000)
        {
            drawContours(img, contours, i, Scalar(0), CV_FILLED);
        }
    }

    imshow("img", img);
    imshow("After findContours", will_be_modified);
    waitKey();

    return 0;
}

Результат:

введите описание изображения здесь

Изображение передано findContours:

введите описание изображения здесь

Другие вопросы по тегам