为了实现您想要的效果,我们将使用
findContours
。关键点是理解当
mode
设置为
CV_RETR_TREE
时它是如何工作的。在这种情况下,
hierarchy
被构造成每个偶数深度级别包含外部轮廓,而奇数深度级别包含内部轮廓。我们需要做的是遍历层次结构树,并打印与偶数深度级别相关联的轮廓。
首先,我们找到名为original
的图像的轮廓。
typedef std::vector<std::vector<cv::Point> > Contours
typedef std::vector<cv::Vec4i> Hierarchy
Contours contours
Hierarchy hierarchy
cv::findContours(original, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_NONE)
为了在名为
processed
的图像上打印外轮廓,我们需要一个递归函数。
void printExternalContours(cv::Mat img, Contours const& contours, Hierarchy const& hierarchy, int const idx)
{
for(int i = idx; i >= 0; i = hierarchy[i][0])
{
cv::drawContours(img, contours, i, cv::Scalar(255));
for(int j = hierarchy[i][2]; j >= 0; j = hierarchy[j][0])
{
printExternalContours(img, contours, hierarchy, hierarchy[j][2]);
}
}
}
printExternalContours(processed, contours, hierarchy, 0);
下方显示结果,其中original
和processed
并排展示。
![处理后的图](https://istack.dev59.com/KPqlP.webp)
如果您需要绝对的矩形形状,只需使用boundingRect
获取给定点集(在此情况下是每个轮廓)的最小包围矩形,并使用rectangle
进行绘制。换句话说,将
cv::drawContours(img, contours, i, cv::Scalar(255));
cv::rectangle(img, cv::boundingRect(contours[i]), cv::Scalar(255));
findContours
函数需要一张单通道8位图像,因此你可以从原始图像中制作灰度图像,然后对其进行阈值处理以获得完美的黑色背景,或者在你的情况下,也许使用红色通道就足够了,但请确保背景是完全黑色的。
关于findContours
的复杂性,我不能证明它比O(N^2)更好,也没有在快速的谷歌搜索后找到任何相关信息,但我相信OpenCV实现了最好的已知算法。