#c #opencv #vector
#c #opencv #вектор
Вопрос:
для каждого контура я хочу поместить его отверстия в отдельный вектор <of holes>. По умолчанию в OpenCV 2.* у нас есть 2 варианта — использовать OpenCV 1.* древовидная структура и выполнить итерацию по ней, как показано в этом руководстве, чтобы разобраться с vector<Vec4i>
немного упрощенной, но похожей на OpenCV 1.0 древовидной структурой, которую std::vector< std::vector<Point> >
вы можете получить из findContours
. Дерево — это решетка, когда вам нужно знать наследование — «что помещается внутри чего». Но часто вам действительно нужен просто набор областей и его отверстий. (для векторизации и подобных задач).
В настоящее время у меня есть такой код:
#include <opencv2/opencv.hpp>
using namespace cv;
int main( )
{
Mat black = Mat::zeros(Size(100, 100), CV_8UC1);
for(int i = 0; i <= 35; i)
{
for (int k = 0; k <=35; k)
{
black.row(i).col(k) = 255;
}
}
for(int i = 10; i <= 15; i)
{
for (int k = 10; k <=15; k)
{
black.row(i).col(k) = 0;
}
}
for(int i = 25; i <= 30; i)
{
for (int k = 25; k <=30; k)
{
black.row(i).col(k) = 0;
}
}
for(int i = 45; i <= 75; i)
{
for (int k = 45; k <= 75; k)
{
black.row(i).col(k) = 255;
}
}
for(int i = 55; i <= 65; i)
{
for (int k = 55; k <=65; k)
{
black.row(i).col(k) = 0;
}
}
for(int i = 57; i <= 62; i)
{
for (int k = 57; k <=62; k)
{
black.row(i).col(k) = 255;
}
}
namedWindow("Display Image", CV_WINDOW_AUTOSIZE);
imshow("Display Image", black);
std::vector< std::vector<Point> > contours;
vector<Vec4i> hierarchy;
if(sum(black).val[0] > 0.0)
{
findContours(black, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);
}
else
{
std::cout << "It's a black image, so I'm not going to do anything..." << std::endl;
}
for(int i = 0; i < contours.size(); i)
{
std::cout << "counter " << i << ":" << std::endl;
std::cout << hierarchy[i][0] << " " << hierarchy[i][1] << " " << hierarchy[i][2] << hierarchy[i][3] << std::endl;
for (int k = 0; k < contours[i].size(); k)
{
std::cout << "t point " << k << " x: " << contours[i][k].x << "; y: " << contours[i][k].y << std::endl;
}
}
waitKey(0);
std::cin.get();
return 0;
}
Интересно, можно ли изменить std::vector< std::vector<Point> > contours;
на что-то вроде std::vector< std::pair<std::vector<Point>, std::vector<std::vector<Point> > > contours;
, где пара состоит из контура: вектор его отверстий. Возможно ли это и как реализовать такую вещь с помощью OpenCV 2.3?
Обновить:
Я имел в виду что-то вроде этого (плохой, нехороший стиль C …) фрагмента кода, который я создал:
struct vector_object
{
std::vector<Point> border;
std::vector< std::vector<Point> > holes;
};
std::vector<vector_object> container;
void store_vector_hole(std::vector< std::vector<Point> > amp;holes, std::vector< std::vector<Point> > amp; contours, std::vector<Vec4i> amp; hierarchy, const int amp; cid);
void store_vectror_countors(std::vector< std::vector<Point> > amp; contours, std::vector<Vec4i> amp; hierarchy, const int amp; cid);
void store_vector_hole(std::vector< std::vector<Point> > amp;holes, std::vector< std::vector<Point> > amp; contours, std::vector<Vec4i> amp; hierarchy, const int amp; cid)
{
holes.push_back(contours[cid]);
if (hierarchy[cid][2] >= 0) // holes in holes == real poligons
{
store_vectror_countors( contours, hierarchy, hierarchy[cid][2]);
}
if (hierarchy[cid][0] >= 0) // holes on same level of depth == another holes of this poligon
{
store_vector_hole(holes, contours, hierarchy, hierarchy[cid][0]);
}
return;
}
void store_vectror_countors(std::vector< std::vector<Point> > amp; contours, std::vector<Vec4i> amp; hierarchy, const int amp; cid)
{
if (hierarchy[cid][0]>= 0)
store_vectror_countors(contours, hierarchy, hierarchy[cid][0]);
vector_object current;
current.border = contours[cid];
if ((hierarchy[cid][0]<= 0) amp;amp; (hierarchy[cid][2] <= 0))
{
container.push_back(current);
return;
}
if(hierarchy[cid][2] >= 0) // h
{
store_vector_hole(current.holes, contours, hierarchy, hierarchy[cid][2]);
}
container.push_back(current);
return;
}
который вы активируете с помощью:
//...
findContours(black, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE);
store_vectror_countors(contours, hierarchy, 0);
Есть идеи по повышению надежности и соответствия C ?
Ответ №1:
Вы пытались извлечь их в виде дерева контуров? Используйте флаг CV_RETR_TREE в findContours, и это должно дать вам именно то, что вы хотите.
Комментарии:
1. Вы имеете в виду наличие
std::map< std::vector<Point>, std::vector< std::vector<Point> > > contours;
вызоваfindContours(black, contours, CV_RETR_TREE , CV_CHAIN_APPROX_SIMPLE);
? Это не будет компилироваться (error C2665: 'cv::findContours' : none of the 2 overloads could convert all the argument types
)2. В то время как это
std::vector< std::pair<std::vector<Point>, std::vector< std::vector<Point> > > > contours;
findContours(black, contours, CV_RETR_TREE , CV_CHAIN_APPROX_SIMPLE);
БУДЕТ СКОМПИЛИРОВАНО И УМРЕТ ВО ВРЕМЯ ВЫПОЛНЕНИЯ СOpenCV Error: Assertion failed (type == type0 || (CV_MAT_CN(type) == CV_MAT_CN(t ype0) amp;amp; ((1 << type0) amp; fixedDepthMask) != 0)) in unknown function, file D:Pro jectsOpenCV-2.3.0modulescoresrcmatrix.cpp, line 1239