opencv - 查找轮廓在模拟图像上发现太多轮廓
问题描述
我想找到分段岩石的二值图像的轮廓。opencv 的 findContours 函数存在一些问题。
轮廓大小约为 1000,而二值图像的轮廓可能约为 30-50。
当我绘制所有轮廓时,它们似乎是二进制图像中黑色边界的一个不错的表示。但是当我只绘制某个随机索引的一个轮廓时,它会显示一个小轮廓。
图片如下:
- 二进制图像
- 所有索引的轮廓
- 随机轮廓索引的轮廓。小绿色轮廓
我想拥有与二进制图像一样的确切数量的轮廓。
代码 :
std::vector<std::vector<cv::Point>> contours;
std::vector<cv::Vec4i> hierarchy;
cv::findContours(input_image, contours,hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_NONE);
for( int i = 0; i < (int)contours.size(); i++)
{
cv::drawContours(input_rgb_image, contours, 512 , cv::Scalar(0,255,0), 1, 8, hierarchy,1);
}
解决方案
我会尝试几件事:
- 双边滤波器而不是模糊。它以类似于模糊的方式平滑事物,但也尝试保留边界,这有利于分割。缺点 - 它的计算成本很高,但你可能会发现“你的”参数可以免费播放
- 分水岭之前的模糊+均值偏移分割。Blur 会像预期的那样起作用,meanshift 将平均并连接具有相似颜色的轮廓,因此使轮廓的数量更小。根据参数,meanshift 也很昂贵。只是玩它。
更高级的是之后的轮廓分析。您可以根据以下条件联合一些邻居:
- 直方图在某些 hsv 通道上的相似性;
- 轮廓属性,例如圆度。如果两个联合邻居的圆度优于其中任何一个的圆度,则它们可以联合。像这样的东西。
圆度计算:
float calcRoundness(std::vector<cv::Point> &contour, double area)
{
float p = cv::arcLength(contour, true);
if (p == 0)
return 0;
float k = (4 * M_PI * area) / pow(p, 2);
/* 1 is circle, 0.75 - squared area, etc. */
return k;
}
推荐阅读
- javascript - 不同模式的不同CSS?
- asp.net-core - 有没有办法使用 Razor Pages 进行动态路由?
- .net - 当事件中心关闭或连接字符串错误时,EventHubClient.CreateFromConnectionString / SendAsync 如何
- python - 无法将请求的地址分配给 ssserver config.json
- css - 使用 CSS 在缺少替代文本的图像上覆盖颜色
- python - 如何修改蒙版使其完美圆形
- amazon-web-services - 如何允许用户删除 S3 存储桶中的对象?
- javascript - 如何在 vuejs 路由器链接中传递 laravel 变量?
- bash - bash:在bash文件的倒数第二行添加一个包含10行数据的变量
- swift - Swift - 以编程方式向堆栈视图添加标签