理想图像的外部和内部边缘检测
External and internal Edge Detection for ideal image
我正在寻找一种算法,可以对仅包含两个不同 RGB 值的理想图像进行外部和内部轮廓检测。
下面是我要处理的图像的典型示例(第一个),下一个图像是我自己制作的,显示了我期望的结果。
最后一个是通过 OpenCV demo Software.
提供的演示软件进行 OpenCV Canny 检测的结果
canny 算法并不令人满意,因为它对形状(尤其是角)进行了平滑处理。
是否有任何优雅的算法可以给出与第二张图片相同的结果?
罗伯茨交叉算法是一种使边缘更加锯齿的算法。尽管在您的示例中它很容易受到噪音的影响,但我认为这不会破坏交易。
关于它的工作原理有一个很好的总结,比我自己解释得更好 Here。本质上,您采用 2x2 区域,执行 x 和 y 卷积并近似梯度幅度,因为平方根用于慢速戳。
轮廓提取是最简单的方法:
int main(int argc, char* argv[])
{
cv::Mat input = cv::imread("C:/Whosebug/Input/ContourExtraction.png");
cv::Mat mask;
// create a perfect mask: Easy if you know the 2 colors present in your image:
cv::inRange(input, cv::Scalar(100, 0, 0), cv::Scalar(255, 255, 255), mask);
cv::imshow("mask", mask);
std::vector<std::vector<cv::Point> > contours; // contour points
std::vector<cv::Vec4i> hierarchy; // this will give you the information whether it is an internal or external conotour.
// contour extraction: This will alter the input image, so if you need it later use mask.clone() instead
findContours(mask, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_NONE, cv::Point(0, 0)); // use different CV_CHAIN_APPROX_ if you dont need ALL the points but only the ones that dont lie on a common line
// output images:
cv::Mat contoursExternal = input.clone();
cv::Mat contoursInternal = input.clone();
cv::Mat contoursAll = cv::Mat::zeros(input.size(), CV_8UC1);
// draw contours
for (unsigned int i = 0; i < contours.size(); ++i)
{
cv::drawContours(contoursAll, contours, i, cv::Scalar::all(255), 1);
if (hierarchy[i][3] != -1) cv::drawContours(contoursInternal, contours, i, cv::Scalar::all(255), 1);
else cv::drawContours(contoursExternal, contours, i, cv::Scalar::all(255), 1);
}
cv::imshow("internal", contoursInternal);
cv::imshow("external", contoursExternal);
cv::imshow("all", contoursAll);
cv::imshow("input", input);
cv::waitKey(0);
return 0;
}
给出这些结果:
外轮廓:
内部轮廓:
结果掩码:
我正在寻找一种算法,可以对仅包含两个不同 RGB 值的理想图像进行外部和内部轮廓检测。
下面是我要处理的图像的典型示例(第一个),下一个图像是我自己制作的,显示了我期望的结果。
最后一个是通过 OpenCV demo Software.
提供的演示软件进行 OpenCV Canny 检测的结果canny 算法并不令人满意,因为它对形状(尤其是角)进行了平滑处理。
是否有任何优雅的算法可以给出与第二张图片相同的结果?
罗伯茨交叉算法是一种使边缘更加锯齿的算法。尽管在您的示例中它很容易受到噪音的影响,但我认为这不会破坏交易。
关于它的工作原理有一个很好的总结,比我自己解释得更好 Here。本质上,您采用 2x2 区域,执行 x 和 y 卷积并近似梯度幅度,因为平方根用于慢速戳。
轮廓提取是最简单的方法:
int main(int argc, char* argv[])
{
cv::Mat input = cv::imread("C:/Whosebug/Input/ContourExtraction.png");
cv::Mat mask;
// create a perfect mask: Easy if you know the 2 colors present in your image:
cv::inRange(input, cv::Scalar(100, 0, 0), cv::Scalar(255, 255, 255), mask);
cv::imshow("mask", mask);
std::vector<std::vector<cv::Point> > contours; // contour points
std::vector<cv::Vec4i> hierarchy; // this will give you the information whether it is an internal or external conotour.
// contour extraction: This will alter the input image, so if you need it later use mask.clone() instead
findContours(mask, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_NONE, cv::Point(0, 0)); // use different CV_CHAIN_APPROX_ if you dont need ALL the points but only the ones that dont lie on a common line
// output images:
cv::Mat contoursExternal = input.clone();
cv::Mat contoursInternal = input.clone();
cv::Mat contoursAll = cv::Mat::zeros(input.size(), CV_8UC1);
// draw contours
for (unsigned int i = 0; i < contours.size(); ++i)
{
cv::drawContours(contoursAll, contours, i, cv::Scalar::all(255), 1);
if (hierarchy[i][3] != -1) cv::drawContours(contoursInternal, contours, i, cv::Scalar::all(255), 1);
else cv::drawContours(contoursExternal, contours, i, cv::Scalar::all(255), 1);
}
cv::imshow("internal", contoursInternal);
cv::imshow("external", contoursExternal);
cv::imshow("all", contoursAll);
cv::imshow("input", input);
cv::waitKey(0);
return 0;
}
给出这些结果:
外轮廓:
内部轮廓:
结果掩码: