documentacion c++ opencv rectangles

c++ - documentacion - opencv 3.4 1 python documentation



OpenCV groupRectangles-obteniendo rectángulos agrupados y no agrupados (3)

Estoy usando OpenCV y quiero agrupar rectángulos que tienen una superposición significativa. He intentado usar groupRectangles para esto, que toma un argumento de umbral de grupo. Con un umbral de 0, no realiza ninguna agrupación, y con un umbral de 1 solo devuelve rectángulos que fueron el resultado de al menos 2 rectángulos. Por ejemplo, dados los rectángulos de la izquierda en la imagen de abajo, terminas con los 2 rectángulos de la derecha:

Lo que me gustaría terminar es con 3 rectángulos. El 2 a la derecha en la imagen de arriba, más el rectángulo en la parte superior derecha de la imagen a la izquierda que no se superpone con ningún otro rectángulo. ¿Cuál es la mejor manera de lograr esto?


Al revisar groupRectangles() en el código fuente de opencv-3.3.0:

if( groupThreshold <= 0 || rectList.empty() ) { // ...... return; }

Vi que si groupThreshold se establece en menor o igual a 0, la función simplemente regresará sin hacer ninguna agrupación.

Por otro lado, el siguiente code eliminó todos los rectángulos que no tienen más que similitudes de groupThreshold de groupThreshold .

// filter out rectangles which don''t have enough similar rectangles if( n1 <= groupThreshold ) continue;

Eso explica por qué con groupThreshold = 1 solo hay rectángulos con al menos 2 superposiciones en la salida.

Una posible solución podría ser modificar el código fuente que se muestra arriba (reemplazando n1 <= groupThreshold con n1 < groupThreshold ) y volver a compilar OpenCV.


La solución con la que terminé fue duplicar todos los rectángulos iniciales antes de llamar a groupRectangles . De esa manera, se garantiza que cada rectángulo de entrada se agrupará con al menos otro rectángulo, y aparecerá en la salida:

int size = rects.size(); for( int i = 0; i < size; i++ ) { rects.push_back(Rect(rects[i])); } groupRectangles(rects, 1, 0.2);


Un poco tarde para la fiesta, sin embargo, la solución de "duplicación" no me funcionó correctamente. También tuve otro problema donde los rectángulos combinados se solaparían y tendrían que combinarse.

Así que se me ocurrió una solución excesiva (podría requerir el compilador C ++ 14). Aquí está el ejemplo de uso:

std::vector<cv::Rect> rectangles, test1, test2, test3; rectangles.push_back(cv::Rect(cv::Point(5, 5), cv::Point(15, 15))); rectangles.push_back(cv::Rect(cv::Point(14, 14), cv::Point(26, 26))); rectangles.push_back(cv::Rect(cv::Point(24, 24), cv::Point(36, 36))); rectangles.push_back(cv::Rect(cv::Point(37, 20), cv::Point(40, 40))); rectangles.push_back(cv::Rect(cv::Point(20, 37), cv::Point(40, 40))); test1 = rectangles; test2 = rectangles; test3 = rectangles; //Output format: {Rect(x, y, width, height), ...} //Merge once mergeRectangles(test1); //Output rectangles: test1 = {Rect(5, 5, 31, 31), Rect(20, 20, 20, 20)} //Merge until there are no rectangles to merge mergeRectangles(test2, true); //Output rectangles: test2 = {Rect(5, 5, 35, 35)} //Override default merge (intersection) function to merge all rectangles mergeRectangles(test3, false, [](const cv::Rect& r1, const cv::Rect& r2) { return true; }); //Output rectangles: test3 = {Rect(5, 5, 35, 35)}

Función:

void mergeRectangles(std::vector<cv::Rect>& rectangles, bool recursiveMerge = false, std::function<bool(const cv::Rect& r1, const cv::Rect& r2)> mergeFn = nullptr) { static auto defaultFn = [](const cv::Rect& r1, const cv::Rect& r2) { return (r1.x < (r2.x + r2.width) && (r1.x + r1.width) > r2.x && r1.y < (r2.y + r2.height) && (r1.y + r1.height) > r2.y); }; static auto innerMerger = [](std::vector<cv::Rect>& rectangles, std::function<bool(const cv::Rect& r1, const cv::Rect& r2)>& mergeFn) { std::vector<std::vector<std::vector<cv::Rect>::const_iterator>> groups; std::vector<cv::Rect> mergedRectangles; bool merged = false; static auto findIterator = [&](std::vector<cv::Rect>::const_iterator& iteratorToFind) { for (auto groupIterator = groups.begin(); groupIterator != groups.end(); ++groupIterator) { auto foundIterator = std::find(groupIterator->begin(), groupIterator->end(), iteratorToFind); if (foundIterator != groupIterator->end()) { return groupIterator; } } return groups.end(); }; for (auto rect1_iterator = rectangles.begin(); rect1_iterator != rectangles.end(); ++rect1_iterator) { auto groupIterator = findIterator(rect1_iterator); if (groupIterator == groups.end()) { groups.push_back({rect1_iterator}); groupIterator = groups.end() - 1; } for (auto rect2_iterator = rect1_iterator + 1; rect2_iterator != rectangles.end(); ++rect2_iterator) { if (mergeFn(*rect1_iterator, *rect2_iterator)) { groupIterator->push_back(rect2_iterator); merged = true; } } } for (auto groupIterator = groups.begin(); groupIterator != groups.end(); ++groupIterator) { auto groupElement = groupIterator->begin(); int x1 = (*groupElement)->x; int x2 = (*groupElement)->x + (*groupElement)->width; int y1 = (*groupElement)->y; int y2 = (*groupElement)->y + (*groupElement)->height; while (++groupElement != groupIterator->end()) { if (x1 > (*groupElement)->x) x1 = (*groupElement)->x; if (x2 < (*groupElement)->x + (*groupElement)->width) x2 = (*groupElement)->x + (*groupElement)->width; if (y1 >(*groupElement)->y) y1 = (*groupElement)->y; if (y2 < (*groupElement)->y + (*groupElement)->height) y2 = (*groupElement)->y + (*groupElement)->height; } mergedRectangles.push_back(cv::Rect(cv::Point(x1, y1), cv::Point(x2, y2))); } rectangles = mergedRectangles; return merged; }; if (!mergeFn) mergeFn = defaultFn; while (innerMerger(rectangles, mergeFn) && recursiveMerge); }