OpenCV查找凸壳

9
我有一组离散点的图像,如下所示: discrete mask 我想重构或者上采样这张图片(我不确定应该用哪个词),使得结果图像像这样: after-processed mask 它不需要和示例图像完全相同,但是主要思路是填充原始图像。
我已经有了一个初步的想法。但是在第一步之后,我不知道该如何继续。我的想法是首先使用kmeans分隔图像并找出不同的对象。我已成功完成这一步骤。Kmeans后的图像如下所示: object 1 mask object 2object 3 mask
Kmeans后,我想使用find contour或类似于concave的方法来获得这些形状的轮廓,并使用如填充孔洞之类的函数填充形状。然而,我发现“find contour”不起作用,它会将每个单独的像素都视为轮廓。
我考虑的另一种方法是使用插值。但我不确定是否可以使用这么稀疏的点。是否有人对如何实现这个有任何想法?我不确定自己的方法是否正确,我接受任何解决方案。
非常感谢!

1
我认为“上采样”不是你要找的术语。 - Mark Ransom
@MarkRansom 是的,我不确定应该使用什么术语。有什么建议吗? - user1964417
1个回答

6
看一下形态学变换。我们可以先使用一个大卷积核,比如size为(15,15)的MORPH_ELLIPSE进行膨胀操作。然后再使用相同大小的卷积核进行腐蚀操作来缩小斑块。请查看这里的文档。请注意,OpenCV还提供了链接或序列化的形态学操作。请参见这里。然后你会发现我的建议是一个“闭合”操作。 更新: 我尝试使用简单的膨胀和轮廓来得出图像中显示的结果。结果似乎满足问题的一般要求。
同样,应用程序中“实时”的含义没有具体说明,但这组操作可以快速执行,并且可以轻松地应用于30fps的应用程序。 Contoured image 以下是代码片段:
// Convert image to grayscale
cvtColor(src, gray, CV_BGR2GRAY);
threshold(gray, gray, 128.0, 128.0, THRESH_BINARY);

// Dilate to fill holes
dilate(gray, dest, getStructuringElement(MORPH_ELLIPSE, Size(13,13)));

// Find contours
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
findContours(dest, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0,0)); 

  // Prune contours
  float maxArea = 0.0f;
  for (size_t i = 0; i< contours.size(); i++)
     {
       if (contourArea(contours[i]) >= maxArea)
         {
            maxArea = contourArea(contours[i]);
         }
     } 

  float minArea = 0.20f * maxArea;
  vector<vector<Point> > prunedContours;
  for (size_t i = 0; i< contours.size(); i++)
     {
       if (contourArea(contours[i]) >= minArea)
         {
           prunedContours.push_back(contours[i]);
         }
     }

// Smooth the contours
vector<vector<Point> > smoothedContours;
  smoothedContours.resize(prunedContours.size());
  for (size_t i=0;i<prunedContours.size();i++)
    {
    vector<float> x;
    vector<float> y;

    const size_t n = prunedContours[i].size();

    for (size_t j=0;j<n;j++)
      {
        x.push_back(prunedContours[i][j].x);
        y.push_back(prunedContours[i][j].y);
      }

    Mat G;
    transpose(getGaussianKernel(11,4.0,CV_32FC1),G);

    vector<float> xSmooth;
    vector<float> ySmooth;

    filter2D(x,xSmooth, CV_32FC1, G);
    filter2D(y,ySmooth, CV_32FC1, G);

    for (size_t j=0;j<n;j++)
      {
        smoothedContours[i].push_back(Point2f(xSmooth[j],ySmooth[j]));
      }
    }

我曾考虑过形态学方法。但如果我们有不同的对象,并且无法实时处理,则此方法不稳定。 - user1964417
两个注释:上述形态操作速度相当快,很可能可以在GPU上加速(取决于平台)。您能澄清一下“不稳定”吗?这听起来像是您问题的另一个限制,因为形态操作通常被认为是稳定的(在没有太多意外情况下运行)。 - Throwback1986
我所说的不稳定是指形态学取决于您使用的对象以及不同对象的外观。我的系统需要实时工作,无论是什么对象,都必须在不调整形态参数的情况下完成。 - user1964417
1
再次强调,可能还有其他限制因素:形态学运算符似乎非常适合满足所述需求,即“我想使用查找轮廓或类似凹面的函数来获取这些形状的轮廓并使用填充孔等函数来填充形状。” 形态学运算符可以填充您图像中所示的形状,以产生包含每个“对象”轮廓的单个轮廓。 - Throwback1986

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接