搜索一个轮廓是否存在于另一个轮廓内
Search if a contour exists inside another contour
我有两个轮廓向量 OUTERCONT 和 INNERCONT 在 openCV 中定义为 vector(vector(Points))。我想检查内部是否存在一个轮廓 another.I 还想知道每个 OUTERCONT 内部存在多少个轮廓。
我目前正在每个轮廓周围绘制一个 minEnclosingRect 并检查以下内容:
for (int i = 0; i < outerrect.size(); i++)
{
count = 0;
for (int j = 0; j < innerrect.size(); j++)
{
bool is_inside = ((innerrect[j] & outerrect[i]) == innerrect[j]);
if (is_inside == 1)
count++;
}
if (count > 0)
{
//DO SOMETHING
}
cout << count << endl;
这似乎不起作用,它总是 returns 计数为 120 左右的某个数字,这是不正确的。您能否建议任何更改以使其正常工作?
注意:我不能使用层次结构,因为这是从 2 个不同的函数返回的两组独立的轮廓。
我知道 PointPloygon 测试是一个选项,但你能建议更多的方法吗?
这是我从评论中得出的想法:
// stacked contours
int main(int argc, char* argv[])
{
cv::Mat input = cv::imread("C:/Whosebug/Input/Contours_in_Contours.png");
cv::Mat input_red = cv::imread("C:/Whosebug/Input/Contours_in_Contours_RED.png");
cv::Mat reds;
cv::inRange(input_red, cv::Scalar(0, 0, 200), cv::Scalar(50, 50, 255), reds);
std::vector<std::vector<cv::Point> > contours1;
cv::findContours(reds, contours1, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
cv::Mat input_yellow = cv::imread("C:/Whosebug/Input/Contours_in_Contours_YELLOW.png");
cv::Mat yellows;
cv::inRange(input, cv::Scalar(0, 200, 200), cv::Scalar(0, 255, 255), yellows);
std::vector<std::vector<cv::Point> > contours2;
cv::findContours(yellows, contours2, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
// now we have 2 sets of contours and want to find out whether contours of set2 are completely within a contour of contours1 without hierarchy information.
std::vector<cv::Mat> masks1;
std::vector<int> nMaskPixels1;
// for each contour in contours1: create a contour mask:
for (int i = 0; i < contours1.size(); ++i)
{
cv::Mat mask1 = cv::Mat::zeros(input.size(), CV_8UC1);
cv::drawContours(mask1, contours1, i, cv::Scalar::all(255), -1); // draw filled
int nPixel1 = cv::countNonZero(mask1);
masks1.push_back(mask1);
nMaskPixels1.push_back(nPixel1);
}
std::vector<cv::Mat> masks2;
std::vector<int> nMaskPixels2;
// for each contour in contours2: test whether it is completely within the reference contour:
for (int j = 0; j < contours2.size(); ++j)
{
cv::Mat mask2 = cv::Mat::zeros(input.size(), CV_8UC1);
cv::drawContours(mask2, contours2, j, cv::Scalar::all(255), -1); // draw filled
int nPixel2 = cv::countNonZero(mask2);
masks2.push_back(mask2);
nMaskPixels2.push_back(nPixel2);
}
for (int i = 0; i < masks1.size(); ++i)
{
cv::Mat mask1 = masks1[i];
// draw mask again for visualization:
cv::Mat outIm = input.clone();
cv::drawContours(outIm, contours1, i, cv::Scalar(0, 0, 0), 3);
for (int j = 0; j < masks2.size(); ++j)
{
cv::Mat mask2 = masks2[j];
cv::Mat overlap = mask1 & mask2;
int nOverlapPixels = cv::countNonZero(overlap);
if (nOverlapPixels == 0) continue; // no overlap at all. Test next contour.
if (nOverlapPixels == nMaskPixels2[j] && nOverlapPixels < nMaskPixels1[i])
{
// second contour is completely within first contour
cv::drawContours(outIm, contours2, j, cv::Scalar(0, 255, 0), 3);
}
else if (nOverlapPixels == nMaskPixels2[j] && nOverlapPixels == nMaskPixels1[i])
{
// both contours are identical
std::cout << "WARNING: " << "contours " << i << " and " << j << " are identical" << std::endl;
}
else if (nOverlapPixels < nMaskPixels2[j] && nOverlapPixels == nMaskPixels1[i])
{
// first contour is completely within second contour
std::cout << "WARNING: " << "contour " << i << " of the first set is inside of " << j << std::endl;
}
else if (nOverlapPixels < nMaskPixels2[j] && nOverlapPixels < nMaskPixels1[i])
{
// both contours intersect
cv::drawContours(outIm, contours2, j, cv::Scalar(255, 0, 255), 3);
}
}
cv::imshow("contours", outIm);
cv::imwrite("C:/Whosebug/Output/contours.png", outIm);
cv::waitKey(0);
}
cv::imshow("input", input);
cv::waitKey(0);
return 0;
}
此代码将从这 2 个图像创建两组轮廓:
计算轮廓蒙版并进行比较。
每个轮廓将显示结果。黑色轮廓是参考,绿色是完全在参考范围内的轮廓,紫色是交叉轮廓。
我正在使用此图像绘制结果:
得到这些结果:
轮廓1:
轮廓2:
轮廓3:
轮廓4:
轮廓5:
如您所见,未检测到孤立的黄色轮廓与任何这些红色轮廓相交或包含在其中。
我有两个轮廓向量 OUTERCONT 和 INNERCONT 在 openCV 中定义为 vector(vector(Points))。我想检查内部是否存在一个轮廓 another.I 还想知道每个 OUTERCONT 内部存在多少个轮廓。 我目前正在每个轮廓周围绘制一个 minEnclosingRect 并检查以下内容:
for (int i = 0; i < outerrect.size(); i++)
{
count = 0;
for (int j = 0; j < innerrect.size(); j++)
{
bool is_inside = ((innerrect[j] & outerrect[i]) == innerrect[j]);
if (is_inside == 1)
count++;
}
if (count > 0)
{
//DO SOMETHING
}
cout << count << endl;
这似乎不起作用,它总是 returns 计数为 120 左右的某个数字,这是不正确的。您能否建议任何更改以使其正常工作?
注意:我不能使用层次结构,因为这是从 2 个不同的函数返回的两组独立的轮廓。
我知道 PointPloygon 测试是一个选项,但你能建议更多的方法吗?
这是我从评论中得出的想法:
// stacked contours
int main(int argc, char* argv[])
{
cv::Mat input = cv::imread("C:/Whosebug/Input/Contours_in_Contours.png");
cv::Mat input_red = cv::imread("C:/Whosebug/Input/Contours_in_Contours_RED.png");
cv::Mat reds;
cv::inRange(input_red, cv::Scalar(0, 0, 200), cv::Scalar(50, 50, 255), reds);
std::vector<std::vector<cv::Point> > contours1;
cv::findContours(reds, contours1, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
cv::Mat input_yellow = cv::imread("C:/Whosebug/Input/Contours_in_Contours_YELLOW.png");
cv::Mat yellows;
cv::inRange(input, cv::Scalar(0, 200, 200), cv::Scalar(0, 255, 255), yellows);
std::vector<std::vector<cv::Point> > contours2;
cv::findContours(yellows, contours2, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
// now we have 2 sets of contours and want to find out whether contours of set2 are completely within a contour of contours1 without hierarchy information.
std::vector<cv::Mat> masks1;
std::vector<int> nMaskPixels1;
// for each contour in contours1: create a contour mask:
for (int i = 0; i < contours1.size(); ++i)
{
cv::Mat mask1 = cv::Mat::zeros(input.size(), CV_8UC1);
cv::drawContours(mask1, contours1, i, cv::Scalar::all(255), -1); // draw filled
int nPixel1 = cv::countNonZero(mask1);
masks1.push_back(mask1);
nMaskPixels1.push_back(nPixel1);
}
std::vector<cv::Mat> masks2;
std::vector<int> nMaskPixels2;
// for each contour in contours2: test whether it is completely within the reference contour:
for (int j = 0; j < contours2.size(); ++j)
{
cv::Mat mask2 = cv::Mat::zeros(input.size(), CV_8UC1);
cv::drawContours(mask2, contours2, j, cv::Scalar::all(255), -1); // draw filled
int nPixel2 = cv::countNonZero(mask2);
masks2.push_back(mask2);
nMaskPixels2.push_back(nPixel2);
}
for (int i = 0; i < masks1.size(); ++i)
{
cv::Mat mask1 = masks1[i];
// draw mask again for visualization:
cv::Mat outIm = input.clone();
cv::drawContours(outIm, contours1, i, cv::Scalar(0, 0, 0), 3);
for (int j = 0; j < masks2.size(); ++j)
{
cv::Mat mask2 = masks2[j];
cv::Mat overlap = mask1 & mask2;
int nOverlapPixels = cv::countNonZero(overlap);
if (nOverlapPixels == 0) continue; // no overlap at all. Test next contour.
if (nOverlapPixels == nMaskPixels2[j] && nOverlapPixels < nMaskPixels1[i])
{
// second contour is completely within first contour
cv::drawContours(outIm, contours2, j, cv::Scalar(0, 255, 0), 3);
}
else if (nOverlapPixels == nMaskPixels2[j] && nOverlapPixels == nMaskPixels1[i])
{
// both contours are identical
std::cout << "WARNING: " << "contours " << i << " and " << j << " are identical" << std::endl;
}
else if (nOverlapPixels < nMaskPixels2[j] && nOverlapPixels == nMaskPixels1[i])
{
// first contour is completely within second contour
std::cout << "WARNING: " << "contour " << i << " of the first set is inside of " << j << std::endl;
}
else if (nOverlapPixels < nMaskPixels2[j] && nOverlapPixels < nMaskPixels1[i])
{
// both contours intersect
cv::drawContours(outIm, contours2, j, cv::Scalar(255, 0, 255), 3);
}
}
cv::imshow("contours", outIm);
cv::imwrite("C:/Whosebug/Output/contours.png", outIm);
cv::waitKey(0);
}
cv::imshow("input", input);
cv::waitKey(0);
return 0;
}
此代码将从这 2 个图像创建两组轮廓:
计算轮廓蒙版并进行比较。
每个轮廓将显示结果。黑色轮廓是参考,绿色是完全在参考范围内的轮廓,紫色是交叉轮廓。
我正在使用此图像绘制结果:
得到这些结果:
轮廓1:
轮廓2:
轮廓3:
轮廓4:
轮廓5:
如您所见,未检测到孤立的黄色轮廓与任何这些红色轮廓相交或包含在其中。