Распознавать открытые и закрытые формы opencv

как обнаружить открытые и закрытые фигуры в opencv.

enter image description here

Это простые образцы, которые я хочу обнаружить. Я обнаружил прямоугольник, используя findContours и approxPolyDP, и проверяя угол между векторами.

Теперь я хочу обнаружить открытую фигуру, функция approxPolyDP имеет bool для закрытой формы, заданной как true, а также есть проверка на isCounterConvex на возвращаемые точки плюс ограничение contourArea.

Любые идеи, как я должен искать такие изображения.

Ответ 1

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

Здесь мы будем использовать иерархию как

vector< Vec4i > hierarchy

где для i-го контура

hierarchy[i][0] = next contour at the same hierarchical level
hierarchy[i][1] = previous contour at the same hierarchical level
hierarchy[i][2] = denotes its first child contour
hierarchy[i][3] = denotes index of its parent contour

Если для контура я нет следующих, предыдущих, родительских или вложенных контуров, соответствующие элементы hierarchy[i] будут отрицательными. Подробнее см. findContours().

Итак, проверив значение hierarchy[i][2], вы можете решить, что контур принадлежит закрытому или нет, то есть для контура, если hierarchy[i][2] = -1, а затем нет дочернего элемента и он принадлежит открытому.

И еще одна вещь заключается в том, что в функции findContours() вы должны использовать CV_RETR_CCOMP, который извлекает все контуры и организует их в двухуровневую иерархию.

Вот код С++, как реализовать это.

    Mat tmp,thr;
    Mat src=imread("1.png",1);
    cvtColor(src,tmp,CV_BGR2GRAY);
    threshold(tmp,thr,200,255,THRESH_BINARY_INV);

    vector< vector <Point> > contours; // Vector for storing contour
    vector< Vec4i > hierarchy;
    findContours( thr, contours, hierarchy,CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE );

    for( int i = 0; i< contours.size(); i=hierarchy[i][0] ) // iterate through each contour.
    {
        Rect r= boundingRect(contours[i]);
        if(hierarchy[i][2]<0) //Check if there is a child contour
          rectangle(src,Point(r.x-10,r.y-10), Point(r.x+r.width+10,r.y+r.height+10), Scalar(0,0,255),2,8,0); //Opened contour
        else
          rectangle(src,Point(r.x-10,r.y-10), Point(r.x+r.width+10,r.y+r.height+10), Scalar(0,255,0),2,8,0); //closed contour
    }

Результат:

enter image description here

Ответ 2

При правильной постановке проблемы полезный ответ @Haris не следует рассматривать как общее решение для идентификации замкнутых контуров с использованием findContours(),

Одна из причин заключается в том, что заполненный объект не будет иметь внутреннего контура и поэтому возвратит hierarchy[i][2] = -1, что означает, что этот тест сам по себе неправильно маркирует такие контуры, как "открытый".

Контур заполненного объекта не должен иметь дочернего элемента или родителя в иерархии контура, то есть быть на верхнем уровне. Таким образом, для обнаружения замкнутых контуров заполненных объектов, по крайней мере, потребуется дополнительное испытание: if(hierarchy[i][2] < 0 && hierarchy[i][3] < 0).

Я думаю, что ответ @Haris, возможно, сделал эту точку наклонно, но я подумал, что это важно для людей, таких как я, которые изучают, как использовать opencv.

Ответ 3

Ответ зависит от вашего изображения, а точнее, от того, сколько контуров задано, есть ли другие объекты, шум и т.д. В простом случае одного контура заливки заливки, запущенного внутри замкнутого контура, не будет разливаться по всему образ; если он начал снаружи, он не будет посередине. Таким образом, вы сохранили бы белую область в обоих случаях.