忽略另一个内部的连接组件
Ignore connected component inside another one
我正在尝试使用 OpenCV 将背景(绿色区域和浅绿色毛巾)与对象分开,因此我手动分割了以下图像:
通过用红色边框和蓝色着色对象,不应考虑连接的组件,如您在图像右下角看到的那样:
对通道 R 和 B 进行 254 阈值处理后,我得到以下信息:
- 红色频道
- 蓝色频道
如果我使用
完成红色通道的所有轮廓
findContours( bordersRed, contoursRedChannel, hierarchyRedChannel, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, cv::Point(0, 0) );
for (int index = 0; index < contoursRedChannel.size(); index ++)
{
drawContours( bordersRed, contoursRedChannel, index, colorForMask, CV_FILLED, 8, hierarchyRedChannel, 0, cv::Point() );
}
右下角会是这样的:
但我需要的是忽略只包含蓝点的轮廓,以便得到类似的东西:
所以我必须将红色和蓝色通道结合起来才能得到它,但还不知道怎么做。如有任何建议,我们将不胜感激。
谢谢。
您可以使用 floodFill 来做到这一点,前提是您知道要填充的形状内的一个点。
从您的 "Channel red" 开始的结果:
代码:
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace std;
using namespace cv;
int main()
{
// Your image
Mat1b img = imread("path_to_image", IMREAD_GRAYSCALE);
// Assume you know a point inside the shape
Point seed(930, 370);
// Apply floodfill
floodFill(img, seed, Scalar(255));
// Show image
imshow("Result", img);
waitKey();
return 0;
}
更新
用 drawContours(... CV_FILLED)
填充两个蒙版的轮廓后,您可以简单地 XOR 两个蒙版:
代码:
#include <opencv2\opencv.hpp>
#include <vector>
#include <algorithm>
using namespace std;
using namespace cv;
int main()
{
// Load the two mask
Mat1b channel_red_mask = imread("channel_red.png", IMREAD_GRAYSCALE);
Mat1b channel_blue_mask = imread("channel_blue.png", IMREAD_GRAYSCALE);
// Use just the bottom right part
Rect roi(Point(800, 270), Point(channel_red_mask.cols, channel_red_mask.rows));
channel_red_mask = channel_red_mask(roi).clone();
channel_blue_mask = channel_blue_mask(roi).clone();
// Fill all contours, in both masks
{
vector<vector<Point>> contours;
findContours(channel_red_mask.clone(), contours, RETR_LIST, CHAIN_APPROX_SIMPLE);
for (int i = 0; i < contours.size(); ++i)
{
drawContours(channel_red_mask, contours, i, Scalar(255), CV_FILLED);
}
}
{
vector<vector<Point>> contours;
findContours(channel_blue_mask.clone(), contours, RETR_LIST, CHAIN_APPROX_SIMPLE);
for (int i = 0; i < contours.size(); ++i)
{
drawContours(channel_blue_mask, contours, i, Scalar(255), CV_FILLED);
}
}
// XOR the masks
Mat1b xored = channel_red_mask ^ channel_blue_mask;
imshow("XOR", xored);
waitKey();
return 0;
}
我正在尝试使用 OpenCV 将背景(绿色区域和浅绿色毛巾)与对象分开,因此我手动分割了以下图像:
通过用红色边框和蓝色着色对象,不应考虑连接的组件,如您在图像右下角看到的那样:
对通道 R 和 B 进行 254 阈值处理后,我得到以下信息:
- 红色频道
- 蓝色频道
如果我使用
完成红色通道的所有轮廓findContours( bordersRed, contoursRedChannel, hierarchyRedChannel, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, cv::Point(0, 0) );
for (int index = 0; index < contoursRedChannel.size(); index ++)
{
drawContours( bordersRed, contoursRedChannel, index, colorForMask, CV_FILLED, 8, hierarchyRedChannel, 0, cv::Point() );
}
右下角会是这样的:
但我需要的是忽略只包含蓝点的轮廓,以便得到类似的东西:
所以我必须将红色和蓝色通道结合起来才能得到它,但还不知道怎么做。如有任何建议,我们将不胜感激。
谢谢。
您可以使用 floodFill 来做到这一点,前提是您知道要填充的形状内的一个点。
从您的 "Channel red" 开始的结果:
代码:
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace std;
using namespace cv;
int main()
{
// Your image
Mat1b img = imread("path_to_image", IMREAD_GRAYSCALE);
// Assume you know a point inside the shape
Point seed(930, 370);
// Apply floodfill
floodFill(img, seed, Scalar(255));
// Show image
imshow("Result", img);
waitKey();
return 0;
}
更新
用 drawContours(... CV_FILLED)
填充两个蒙版的轮廓后,您可以简单地 XOR 两个蒙版:
代码:
#include <opencv2\opencv.hpp>
#include <vector>
#include <algorithm>
using namespace std;
using namespace cv;
int main()
{
// Load the two mask
Mat1b channel_red_mask = imread("channel_red.png", IMREAD_GRAYSCALE);
Mat1b channel_blue_mask = imread("channel_blue.png", IMREAD_GRAYSCALE);
// Use just the bottom right part
Rect roi(Point(800, 270), Point(channel_red_mask.cols, channel_red_mask.rows));
channel_red_mask = channel_red_mask(roi).clone();
channel_blue_mask = channel_blue_mask(roi).clone();
// Fill all contours, in both masks
{
vector<vector<Point>> contours;
findContours(channel_red_mask.clone(), contours, RETR_LIST, CHAIN_APPROX_SIMPLE);
for (int i = 0; i < contours.size(); ++i)
{
drawContours(channel_red_mask, contours, i, Scalar(255), CV_FILLED);
}
}
{
vector<vector<Point>> contours;
findContours(channel_blue_mask.clone(), contours, RETR_LIST, CHAIN_APPROX_SIMPLE);
for (int i = 0; i < contours.size(); ++i)
{
drawContours(channel_blue_mask, contours, i, Scalar(255), CV_FILLED);
}
}
// XOR the masks
Mat1b xored = channel_red_mask ^ channel_blue_mask;
imshow("XOR", xored);
waitKey();
return 0;
}