为啥我的 copyTo 函数没有将掩码复制到正确的 Mat 上?

Posted

技术标签:

【中文标题】为啥我的 copyTo 函数没有将掩码复制到正确的 Mat 上?【英文标题】:Why is my copyTo function Not copying the mask to the correct Mat?为什么我的 copyTo 函数没有将掩码复制到正确的 Mat 上? 【发布时间】:2016-01-13 16:26:53 【问题描述】:

我从以下图片开始,命名为rgbaMat4Mask.bmp

然后我把它转成HSV,然后用inRange()找轮廓,得到下面的Mat命名为maskedMat

然后我继续在一个名为newMatWithMask 的新创建的空Mat 上绘制第一个轮廓(较大的轮廓),它​​的大小与第一张图像的大小相同 我从开始:

到目前为止一切顺利,但问题现在开始了。我创建了一个新的Mat 并赋予它与第一个轮廓(较大的轮廓)相同的大小 strong>,然后将其背景颜色设置为new Scalar(120, 255, 255)。然后我使用copyTo 函数将newMat4MaskFinished 复制到其中。 但生成的Mat 的大小与轮廓的大小不一样,其背景颜色也不设置为蓝色的new Scalar(120, 255, 255)

它是一个与整个蒙版大小相同的图像,并且具有黑色背景。为什么? 我做错了什么?

public void doProcessing(View view) 
        // READING THE RGBA MAT
        Mat rgbaMat4Mask = Highgui.imread("/mnt/sdcard/DCIM/rgbaMat4Mask.bmp");

        // CONVERTING TO HSV
        Mat hsvMat4Mask = new Mat();
        Imgproc.cvtColor(rgbaMat4Mask, hsvMat4Mask, Imgproc.COLOR_BGR2HSV);
        Highgui.imwrite("/mnt/sdcard/DCIM/hsvMat4Mask.bmp", hsvMat4Mask);//check

        // CREATING A FILTER/MASK FOR RED COLORED BLOB
        Mat maskedMat = new Mat();
        Core.inRange(hsvMat4Mask, new Scalar(0, 100, 100), new Scalar(10, 255, 255), maskedMat);
        Highgui.imwrite("/mnt/sdcard/DCIM/maskedMat.bmp", maskedMat);// check

        // COPYING THE MASK TO AN EMPTY MAT
        // STEP 1:
        List<MatOfPoint> contours = new ArrayList<MatOfPoint>();
        Imgproc.findContours(maskedMat, contours, new Mat(), Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_NONE);

        //STEP 2: 
        Mat newMat4Mask = new Mat(rgbaMat4Mask.rows(), rgbaMat4Mask.cols(), CvType.CV_8UC1);
        newMat4Mask.setTo(new Scalar(0));
        Imgproc.drawContours(newMat4Mask, contours, 0, new Scalar(255), -1);//TODO Using -1 instead of CV_FILLED.
        Highgui.imwrite("/mnt/sdcard/DCIM/newMatWithMask.bmp", newMat4Mask);// check


        //STEP 3
        Log.i(TAG, "HAPPY rows:"+contours.get(0).rows()+"   columns:"+contours.get(0).cols());
        Mat newMatwithMaskFinished = new Mat(contours.get(0).rows(), contours.get(0).cols(), CvType.CV_8UC3);
        newMatwithMaskFinished.setTo(new Scalar(120, 255, 255));
        rgbaMat4Mask.copyTo(newMatwithMaskFinished, newMat4Mask);
        Highgui.imwrite("/mnt/sdcard/DCIM/newMatwithMaskFinished.bmp", newMatwithMaskFinished);//check*/
    

【问题讨论】:

【参考方案1】:

您的newMatwithMaskFinished 的大小应与rgbaMat4MasknewMat4Mask 相同。

Mat newMatwithMaskFinished = new Mat(rgbaMat4Mask.rows(), rgbaMat4Mask.cols(), CvType.CV_8UC3);

如果您只想拥有较大圆圈的Mat,并且具有透明背景,那么您需要:

1) 创建newMatwithMaskFinished 类型为CV_8UC4

Mat newMatwithMaskFinished = new Mat(rgbaMat4Mask.rows(), rgbaMat4Mask.cols(), CvType.CV_8UC4);

2) 设置透明背景:

newMatwithMaskFinished.setTo(new Scalar(0, 0, 0, 0));

3) 使用boundingRect 计算您感兴趣的轮廓的边界框box

4) 将rgbaMat4Mask 转换为 4 个通道(除非已经),使用cvtColor(..., COLOR_BGR2BGRA),我们称之为rgba

5) 将rgba 复制到newMatwithMaskFinished,使用掩码newMat4Mask

6) 在box 上裁剪newMatwithMaskFinished,使用submat 方法

【讨论】:

哦。所有这一切背后的目标是只拥有一个更大的红色圆圈的垫子。我所追求的最终效果是裁剪rgbaMat,这样就只剩下较大的红色斑点,而其他所有东西(即背景和较小的红色斑点)都被丢弃了。这不可能吗? “如果你只想拥有一个更大圆圈的垫子,带有自定义背景..” - 我需要带有 no 背景的更大圆圈。我只需要更大的圆圈 那么,透明背景? 是的,透明背景就可以了 关于你的更新,说我做Rect contourROI = Imgproc.boundingRect(contours.get(0)); Mat detectedBlobRectangle = newMatwithMaskFinished.submat(contourROI);,我会得到一个矩形。它的背景仍然是黑色的。

以上是关于为啥我的 copyTo 函数没有将掩码复制到正确的 Mat 上?的主要内容,如果未能解决你的问题,请参考以下文章

xml 将掩码添加到输入字段

如何将掩码应用于后端视图?

使用openCV copyTo函数时用255初始化矩阵?

如何将掩码卡号而不是完整的卡号发送到 Sabre AirTicketLLSRQ api?

C++ opencv copyTo() 函数的执行中断

掩码设置为0时不生成核心文件