C ++ Open CV为相同形状的轮廓绘制一种颜色
C++ Open CV draw one color for the same shape of contour
我在使用 Image Moments 时有这段代码。我想为轮廓的每个形状绘制一次颜色。现在如果我有五个三角形,所有的三角形都用不同的颜色绘制。我想要做的就是一种将形状彼此分开的方法,用相同的颜色绘制它们。
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
findContours(src, contours, hierarchy,
CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);
vector<Moments> mu(contours.size());
vector<Point2f> mc(contours.size());
for (int i = 0; i < contours.size(); i++)
{
mu[i] = moments(Mat(contours[i]), false);
mc[i] = Point2f(mu[i].m10 / mu[i].m00, mu[i].m01 / mu[i].m00);
}
for (int i = 0; i < contours.size(); i++)
{
Scalar color(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
drawContours(dst, contours, i, color, CV_16U, 8, hierarchy);
}
for (int i = 0; i < contours.size(); i++)
{
Scalar color(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
drawContours(dst, contours, i, color, CV_16U, 8, hierarchy);
}
在上面的代码中,Scalar color(.....)
定义了每个轮廓的颜色。目前这是在 for 循环中,因此它为每个轮廓创建一个新颜色。
将 Scalar color(.....)
移出 for 循环,您将只有一种颜色分配给轮廓。
Scalar color(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
for (int i = 0; i < contours.size(); i++)
{
drawContours(dst, contours, i, color, CV_16U, 8, hierarchy);
}
我建议您创建一个标量向量,其中包含您想要的每个形状的颜色。 total_shape 对应于您要着色的形状的一侧。例如,如果您想为包含八边形的形状着色,则 total_shape = 8 + 1。将颜色存储到向量 shape_colors .
std::vector<Scalar> shape_colors;
for (int i = 0; i < total_shape; i++)
{
Scalar color(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
shape_colors.push_back(color);
}
然后当你想给轮廓上色时,检查每个轮廓有多少个点。根据点数,select 来自 shape_color 的颜色,瞧,相同形状的相同配色方案。
但是,根据形状的角度,轮廓结果可能 return 点太多。我们需要使用 approxPolyDP
将轮廓简化为尽可能最简单的形式。这意味着我们希望一个矩形只包含 4 个点,一个三角形包含 3 个点,一个五边形包含 5 个点。本link给出了该功能的详细解释。通过这样做,我们将能够通过它包含的点的总数来确定轮廓的形状。
for (int i = 0; i < contours.size(); i++)
{
cv::Mat approx;
approxPolyDP(contours[i], approx, 30, true);
int n = approx.checkVector(2);
drawContours(dst, contours, i, shape_colors[n],25);
}
完整代码如下:
void process()
{
cv::Mat src;
cv::Mat dst;
cv::RNG rng;
std::string image_path = "Picture1.png";
src = cv::imread(image_path,0);
dst = cv::imread(image_path);
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
cv::threshold(src, src, 120, 255, cv::THRESH_BINARY);
findContours(src, contours, hierarchy,
CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);
int total_shape = 10;
std::vector<Scalar> shape_colors;
for (int i = 0; i < total_shape; i++)
{
Scalar color(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
shape_colors.push_back(color);
}
for (int i = 0; i < contours.size(); i++)
{
cv::Mat approx;
approxPolyDP(contours[i], approx, 30, true);
int n = approx.checkVector(2);
drawContours(dst, contours, i, shape_colors[n],25);
}
cv::imshow("dst", dst);
cv::waitKey(0);
}
结果如下:
我在使用 Image Moments 时有这段代码。我想为轮廓的每个形状绘制一次颜色。现在如果我有五个三角形,所有的三角形都用不同的颜色绘制。我想要做的就是一种将形状彼此分开的方法,用相同的颜色绘制它们。
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
findContours(src, contours, hierarchy,
CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);
vector<Moments> mu(contours.size());
vector<Point2f> mc(contours.size());
for (int i = 0; i < contours.size(); i++)
{
mu[i] = moments(Mat(contours[i]), false);
mc[i] = Point2f(mu[i].m10 / mu[i].m00, mu[i].m01 / mu[i].m00);
}
for (int i = 0; i < contours.size(); i++)
{
Scalar color(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
drawContours(dst, contours, i, color, CV_16U, 8, hierarchy);
}
for (int i = 0; i < contours.size(); i++)
{
Scalar color(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
drawContours(dst, contours, i, color, CV_16U, 8, hierarchy);
}
在上面的代码中,Scalar color(.....)
定义了每个轮廓的颜色。目前这是在 for 循环中,因此它为每个轮廓创建一个新颜色。
将 Scalar color(.....)
移出 for 循环,您将只有一种颜色分配给轮廓。
Scalar color(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
for (int i = 0; i < contours.size(); i++)
{
drawContours(dst, contours, i, color, CV_16U, 8, hierarchy);
}
我建议您创建一个标量向量,其中包含您想要的每个形状的颜色。 total_shape 对应于您要着色的形状的一侧。例如,如果您想为包含八边形的形状着色,则 total_shape = 8 + 1。将颜色存储到向量 shape_colors .
std::vector<Scalar> shape_colors;
for (int i = 0; i < total_shape; i++)
{
Scalar color(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
shape_colors.push_back(color);
}
然后当你想给轮廓上色时,检查每个轮廓有多少个点。根据点数,select 来自 shape_color 的颜色,瞧,相同形状的相同配色方案。
但是,根据形状的角度,轮廓结果可能 return 点太多。我们需要使用 approxPolyDP
将轮廓简化为尽可能最简单的形式。这意味着我们希望一个矩形只包含 4 个点,一个三角形包含 3 个点,一个五边形包含 5 个点。本link给出了该功能的详细解释。通过这样做,我们将能够通过它包含的点的总数来确定轮廓的形状。
for (int i = 0; i < contours.size(); i++)
{
cv::Mat approx;
approxPolyDP(contours[i], approx, 30, true);
int n = approx.checkVector(2);
drawContours(dst, contours, i, shape_colors[n],25);
}
完整代码如下:
void process()
{
cv::Mat src;
cv::Mat dst;
cv::RNG rng;
std::string image_path = "Picture1.png";
src = cv::imread(image_path,0);
dst = cv::imread(image_path);
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
cv::threshold(src, src, 120, 255, cv::THRESH_BINARY);
findContours(src, contours, hierarchy,
CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);
int total_shape = 10;
std::vector<Scalar> shape_colors;
for (int i = 0; i < total_shape; i++)
{
Scalar color(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
shape_colors.push_back(color);
}
for (int i = 0; i < contours.size(); i++)
{
cv::Mat approx;
approxPolyDP(contours[i], approx, 30, true);
int n = approx.checkVector(2);
drawContours(dst, contours, i, shape_colors[n],25);
}
cv::imshow("dst", dst);
cv::waitKey(0);
}
结果如下: