opencv查找轮廓并配色
2022-11-04 本文已影响0人
寽虎非虫003
记录目的
每次都要重新理解得到的层级树应该怎么处理,很麻烦,所以记一下,方便以后直接用。
查找轮廓
单纯查找轮廓部分的代码,输入图按照opencv要求就行
vector<vector<Point>> contours; // 轮廓
// 轮廓嵌套关系,分别表示第i个轮廓的后一个轮廓、前一个轮廓、子轮廓、父轮廓的索引编号
vector<Vec4i> hierarchy;
// CV_RETR_TREE 建立等级树,这个要注意判面积
cv::findContours(thresh, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE);
绘制
这是查完之后开始进行绘制着色
// 两层之间的环才需要着色,其余不需要
RsltMat = Mat::zeros(thresh.size(), CV_8UC3);
vector<Scalar> colors;
for (size_t i = 0; i < contours.size(); i++)
{
colors.push_back(icvprGetRandomColor());
}
if (contours.size())
{
int out = 0;
int idxColor = 0;
bool bColor(true);
mergeDrawContours(RsltMat, contours, hierarchy,
colors, out, idxColor,
bColor);
}
这是具体的颜色生成和绘制代码,其实外面的颜色生成可以放到内部的递归里面去
/** ***************************************************************************
* @brief 递归绘制所有轮廓,相邻的两层中判定为内层的不着色
*
* @param[in] src 需要绘制的图
* @param[in] contours 所有轮廓
* @param[in] hierarchy 所有轮廓之间的层级关系和相邻关系
* @param[in] colors 所有的颜色
* @param[in] idxDraw 当前需要绘制的轮廓编号
* @param[in] idxColor 当前绘制的轮廓的颜色编号
* @param[in] bColor 是否需要着色
* @return int
* ************************************************************************** */
int mergeDrawContours(Mat &src, vector<vector<Point>> &contours,
vector<Vec4i> &hierarchy,
vector<Scalar> &colors,
int &idxDraw,
int &idxColor,
bool bColor)
{
int nResult = 0;
if (idxDraw >= 0)
{
if (bColor)
{
cv::drawContours(src, contours, idxDraw, colors[idxColor], -1);
}
else
{
cv::drawContours(src, contours, idxDraw, Scalar(0, 0, 0), -1);
}
// 每次着色之后,需要使用下一个颜色。
if (bColor)
{
idxColor++;
}
#ifdef _DEBUG
string s = to_string(idxDraw) + " " + to_string(bColor) + " " + to_string(idxColor);
cv::putText(src, s, contours[idxDraw][0],
cv::HersheyFonts::FONT_HERSHEY_PLAIN, 1.f, Scalar(0, 0, 255));
#endif
}
int inner = hierarchy[idxDraw][2];
if (inner >= 0)
{
// 内层不填充颜色
mergeDrawContours(src, contours, hierarchy,
colors, inner, idxColor,
!bColor);
}
int next = hierarchy[idxDraw][0];
if (next >= 0)
{
mergeDrawContours(src, contours, hierarchy,
colors, next, idxColor,
bColor);
}
return nResult;
}
cv::Scalar icvprGetRandomColor()
{
uchar r = rand() % 256;
uchar g = rand() % 256;
uchar b = rand() % 256;
return cv::Scalar(b, g, r);
}
效果
效果图原图