首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在Emgu包装器中使用UMat

在Emgu包装器中使用UMat
EN

Stack Overflow用户
提问于 2015-07-02 07:35:35
回答 1查看 3.9K关注 0票数 0

我已经做了一个应用程序,我应用HSV过滤器的图像,然后试图跟踪特定的颜色。我想使用UMat,因为我需要图像的计算在GPU中,而不是在CPU中。

在下面的代码中,我先取一个Image<Bgra, Byte>,然后用HSV颜色格式转换成UMat格式。然而,当我分割频道时,我会得到每个频道的3个频道(例如。hsvChannels有三个渠道;我不知道为什么会这样)。最后,我不能应用过滤器,因为当我使用inRangeImage方法时,我得到了一个只有一个通道和错误形式的CvInvoke.Copy“未知数组格式”的图像。

应用程序不是最好的,但我想首先了解UMat图像格式是如何工作的,然后尝试改进它。

代码语言:javascript
运行
复制
        private UMat CvAndHsvImage(Image<Bgra, Byte> imgFrame, byte lowerHue, byte upperHue, byte lowerSat, byte upperSat, byte lowerBright, byte upperBright,
        byte erosion = 0, byte dilate = 0, bool hue = false, bool sat = false, bool bright = false, bool invert = false)
    {
        // First convert the input image to hsv so we can change the channels
        //Image<Hsv, Byte> hsvImage = imgFrame.Convert<Hsv, Byte>();
        UMat hsvImage = new UMat();
        UMat bgrImage = new UMat();
        CvInvoke.CvtColor(imgFrame, bgrImage, ColorConversion.Bgra2Bgr);
        CvInvoke.CvtColor(bgrImage, hsvImage, ColorConversion.Bgr2Hsv);

        // Final image that will be returned.
        UMat ResultImage = new UMat();
        UMat ResultImageH = new UMat();
        UMat ResultImageS = new UMat();
        UMat ResultImageV = new UMat();

        UMat[] hsvChannels = new UMat[3];
        hsvChannels = hsvImage.Split();

        UMat img1 = inRangeImage(hsvChannels[0], lowerHue, upperHue);
        UMat img2 = inRangeImage(hsvChannels[1], lowerSat, upperSat);
        UMat img3 = inRangeImage(hsvChannels[2], lowerBright, upperBright);


        #region checkBox Color Mode
        // Evaluation of the check box for each filter. Return the right image
        if (hue)
        {
            CvInvoke.cvCopy(img1, ResultImageH, IntPtr.Zero);
        }
        if (sat)
            //ResultImageS = img2;
            CvInvoke.cvCopy(img2, ResultImageS, IntPtr.Zero);
        if (bright)
            //ResultImageV = img3;
            CvInvoke.cvCopy(img3, ResultImageS, IntPtr.Zero);

        if (hue && !sat && !bright)
            ResultImage = ResultImageH;
        if (!hue && sat && !bright)
            ResultImage = ResultImageS;
        if (!hue && !sat && bright)
            ResultImage = ResultImageV;

        if (hue && sat && !bright)
        {
            CvInvoke.BitwiseAnd(ResultImageH, ResultImageS, ResultImageH);
            ResultImage = ResultImageH;
        }

        if (hue && !sat && bright)
        {
            CvInvoke.BitwiseAnd(ResultImageH, ResultImageV, ResultImageH);
            ResultImage = ResultImageH;
        }

        if (!hue && sat && bright)
        {
            CvInvoke.BitwiseAnd(ResultImageS, ResultImageV, ResultImageS);
            ResultImage = ResultImageS;
        }

        if (hue && sat && bright)
        {
            CvInvoke.BitwiseAnd(ResultImageH, ResultImageS, ResultImageH);
            CvInvoke.BitwiseAnd(ResultImageH, ResultImageV, ResultImageH);
            ResultImage = ResultImageH;
        }
        #endregion

        UMat grayImage = new UMat();

        CvInvoke.CvtColor(ResultImage, bgrImage, ColorConversion.Hsv2Bgr);
        CvInvoke.CvtColor(bgrImage, grayImage, ColorConversion.Bgr2Gray);

        hsvImage.Dispose();
        bgrImage.Dispose();

        return grayImage;

    }

    /// <summary>
    /// Method to define the upper and lower values of the channels of HSV image
    /// </summary>
    /// <param name="hsvImage">Image in HSV and Byte format</param>
    /// <param name="lower">Lower value to be applied</param>
    /// <param name="upper">Upper value to be applied</param>
    /// <returns>Grayscale image with the applied range</returns>
    private UMat inRangeImage(UMat hsvImage, int lower, int upper)
    {
        UMat resultImage = new UMat();
        UMat lowerBorder = new UMat(hsvImage.Rows, hsvImage.Cols, DepthType.Cv8U, 3);
        UMat upperBorder = new UMat(hsvImage.Rows, hsvImage.Cols, DepthType.Cv8U, 3);

        lowerBorder.SetTo(new Gray(lower).MCvScalar);
        upperBorder.SetTo(new Gray(upper).MCvScalar);

        CvInvoke.InRange(hsvImage, lowerBorder, upperBorder, resultImage);

        // Dispose the image due to causing memory leaking.
        lowerBorder.Dispose();
        upperBorder.Dispose();

        return resultImage;

    }
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-08-09 08:07:13

在我看来,在Emgu.CV中,这是一个bug,因为我看到了同样的行为。

尝试使用CvInvoke.Split()代替如下所示:

代码语言:javascript
运行
复制
private UMat CvAndHsvImage(Image<Bgra, Byte> imgFrame, byte lowerHue, byte upperHue, byte lowerSat, byte upperSat, byte lowerBright, byte upperBright,
    byte erosion = 0, byte dilate = 0, bool hue = false, bool sat = false, bool bright = false, bool invert = false)
{
    // <snip>

    // Final image that will be returned.
    UMat ResultImage = new UMat();
    UMat ResultImageH = new UMat();
    UMat ResultImageS = new UMat();
    UMat ResultImageV = new UMat();

    // << Replaced this >>
    // UMat[] hsvChannels = new UMat[3];
    // hsvChannels = hsvImage.Split();
    // << with this >>
    VectorOfUMat hsvChannels = new VectorOfUMat();
    CvInvoke.Split(hsvImage, hsvChannels);

    // </snip>
}

此方法似乎给出了预期的CV_8UC1 UMats。

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

https://stackoverflow.com/questions/31178283

复制
相关文章

相似问题

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