首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么drawContour()在OpenCV中生成这个奇怪的掩码?

为什么drawContour()在OpenCV中生成这个奇怪的掩码?
EN

Stack Overflow用户
提问于 2016-04-20 05:34:00
回答 1查看 553关注 0票数 0

我从阅读这个Mat开始。

然后,我将其转换为Greyscale,并将Imgproc.canny()应用于它,得到了以下掩码。

然后,我使用Imgproc.findContours()查找等值线,Imgproc.drawContours()Core.putText()用数字标记轮廓:

然后我做了Rect boundingRect = Imgproc.boundingRect(contours.get(0)); Mat submatrix = new Mat(); submatrix = originalMat.submat(boundingRect);来跟踪submatrix

到目前为止,还不错。问题从下面开始:

现在我需要一个submatrix**.的面具因此,我决定使用** Imgproc.drawContours() 来获取掩码:

代码语言:javascript
复制
Mat mask = new Mat(submatrix.rows(), submatrix.cols(), CvType.CV_8UC1);
        List<MatOfPoint> contourList = new ArrayList<>();
        contourList.add(contours.get(0));
        Imgproc.drawContours(mask, contourList, 0, new Scalar(255), -1);

我有下面的面具:

我所期待的是一个填充(白色)菱形的黑色背景。

WHy,我会得到这个意想不到的结果吗?

编辑:

  1. 当我用Mat mask = new Mat(submatrix.rows(), submatrix.cols(), CvType.CV_8UC1);替换Mat mask = Mat.zeros(submatrix.rows(), submatrix.cols(), CvType.CV_8UC1);时,最后一个带有白色垃圾的面罩被一个空的黑色面罩替换-- withOUT上面的任何白色。我拿到了下面的垫子和面具:

  1. 我通过contours.get(0)在等值线列表(名为contours.get(0))中获得了第一个轮廓,并使用这个第一个轮廓来计算Imgproc.boundingRect()以及后来的contourList.add(contours.get(0)); (其中contourList是将在最后一个drawContours()中使用的一个轮廓的列表)。 然后,我开始将contours.get(1)转换为Imgproc.boundingRect()中的contours.get(0),以及contourList.add(); (就在Imgproc.drawContours()之前)。这导致了这个子垫和面具:

  1. 然后,我又回到了contours.get(0) in Imgproc.boundingRect();让contourList.add(contours.get(1));在那里。得到了以下子垫和掩码:

现在我完全无法理解这里发生了什么.

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-04-20 08:38:01

我不确定这在JAVA中是如何处理的(我通常在c++或python中使用c++),但是代码中有一个错误.

contours列表将有一个点列表。这几点将引用原始图像。因此,这意味着,如果图1在x=300, y= 300, width= 100, height=100中,那么当你得到你的子矩阵时,它会试图在一个较小的图像中画出这些点.所以当它试图在100 x 100的图像中绘制点(300,300)时,它就会失败.可能会抛出错误或者根本不画任何东西..。

解决这一问题的方法是,对等高线的每个点执行for循环和减法(在我的示例(300,300)中)。

为什么会有垃圾..。你从来没有初始化过矩阵。在JAVA中不确定,但在c++中,您必须将它们设置为0。我觉得应该是这样:

代码语言:javascript
复制
Mat mask = new Mat(submatrix.rows(), submatrix.cols(), CvType.CV_8UC1, new Scalar(0));

我希望这有帮助:)

编辑

我想我以前没有解释清楚。

你的轮廓是一个点数组(x,y)。这些是代表原始图像中每个轮廓的点的坐标。这个图像有一个大小,而你的子矩阵有一个较小的大小。这些点在这个小的图像边界之外.

你应该做些这样的事情来解决这个问题:

代码语言:javascript
复制
for (int j = 0; j < contours[0].length; j++) {
    contours[0][j].x -= boundingrect.x;
    contours[0][j].y -= boundingrect.y;
}

然后你可以画出等高线,因为它们将在子席的边界上。

我认为在java中也可以直接减去opencv点:

代码语言:javascript
复制
for (int j = 0; j < contours[0].length; j++) {
    contours[0][j] -= boundingrect.tl();
}

但在这种情况下,我不确定,因为我只在c++中尝试过

boundingrect.tl() ->给出了rect的左上角。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36734635

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档