Emgucv转换<hsv,byte =“”>()图像</hsv,>

时间:2014-01-13 20:15:57

标签: c# opencv image-processing kinect emgucv

我遇到了EmguCV的问题。我使用了一个演示应用程序,并根据我的需要进行了编辑。 它涉及以下功能:

public override Image<Gray, byte> DetectSkin(Image<Bgr, byte> Img, IColor min, IColor max)
        {
            Image<Hsv, Byte> currentHsvFrame = Img.Convert<Hsv, Byte>();
            Image<Gray, byte> skin = new Image<Gray, byte>(Img.Width, Img.Height);
            skin = currentHsvFrame.InRange((Hsv)min,(Hsv)max);
            return skin;
        }

在演示应用程序中,图像来自视频。这个框架是由视频制作的,如下所示:

 Image<Bgr, Byte> currentFrame;
grabber = new Emgu.CV.Capture(@".\..\..\..\M2U00253.MPG");            
            grabber.QueryFrame();
currentFrame = grabber.QueryFrame();

在我的应用程序中,Image来自microsoft kinect流。

我使用以下功能:

private void SensorColorFrameReady(object sender, ColorImageFrameReadyEventArgs e)
        {
            using (ColorImageFrame colorFrame = e.OpenColorImageFrame())
            {
                if (colorFrame != null)
                {
                    // Copy the pixel data from the image to a temporary array
                    colorFrame.CopyPixelDataTo(this.colorPixels);

                    // Write the pixel data into our bitmap
                    this.colorBitmap.WritePixels(
                        new Int32Rect(0, 0, this.colorBitmap.PixelWidth, this.colorBitmap.PixelHeight),
                        this.colorPixels,
                        this.colorBitmap.PixelWidth * sizeof(int),
                        0);

                    Bitmap b = BitmapFromWriteableBitmap(this.colorBitmap);
                    currentFrame = new Image<Bgr, byte>(b);
                    currentFrameCopy = currentFrame.Copy();
                    skinDetector = new YCrCbSkinDetector();

                    Image<Gray, Byte> skin = skinDetector.DetectSkin(currentFrame, YCrCb_min, YCrCb_max);


                }
            }
        }
private static System.Drawing.Bitmap BitmapFromWriteableBitmap(WriteableBitmap writeBmp)
        {
            System.Drawing.Bitmap bmp;
            using (System.IO.MemoryStream outStream = new System.IO.MemoryStream())
            {
                BitmapEncoder enc = new BmpBitmapEncoder();
                enc.Frames.Add(BitmapFrame.Create((BitmapSource)writeBmp));
                enc.Save(outStream);
                bmp = new System.Drawing.Bitmap(outStream);
            }
            return bmp;
        }

现在,演示应用程序正常运行,而我的则不然。我给出了以下例外: exception

而且,此处的图片包含以下内容: enter image description here

我真的不明白这个例外。而且,现在,当我运行演示时,工作应用程序,图像,包含: enter image description here

在我看来,这是完全一样的。我真的不明白这一点。非常欢迎帮助!

1 个答案:

答案 0 :(得分:1)

为了方便起见,我已经为您上传了一个可用的WPF解决方案到我一直在构建的代码参考sourceforge页面:

http://sourceforge.net/projects/emguexample/files/Capture/Kinect_SkinDetector_WPF.zip/download https://sourceforge.net/projects/emguexample/files/Capture/

这是使用EMGU x64 2.42设计和测试的,因此在项目的Lib文件夹中,您将找到引用的dll。如果您使用的是其他版本,则需要删除当前的引用,并将其替换为您正在使用的版本。

其次,项目的设计就像代码引用库中的所有项目一样,从Emgu.CV.Example文件夹构建到.. \ EMGU 2.XXX \ bin ..全局bin目录中,opencv编译库在其中文件夹x86或x64。

如果您努力使代码正常工作,我可以提供所有组件,但我讨厌重新分发您已经拥有的所有opencv文件,如果您需要,请告诉我。

您需要手动调整主窗口的大小以显示两个图像,因为我没有花多少时间玩布局。

所以代码......

在表格初始化方法中,我检查kinect传感器并为准备好的帧设置事件处理程序。我已经离开了原始阈值和skinDetector类型,虽然我没有使用EMGU版本我只是忘了删除它。您需要使用阈值等等。

            //// Look through all sensors and start the first connected one.
            //// This requires that a Kinect is connected at the time of app startup.
            //// To make your app robust against plug/unplug, 
            //// it is recommended to use KinectSensorChooser provided in Microsoft.Kinect.Toolkit (See components in Toolkit Browser).
            foreach (var potentialSensor in KinectSensor.KinectSensors)
            {
                if (potentialSensor.Status == KinectStatus.Connected)
                {
                    this.KS = potentialSensor;
                    break;
                }
            }

            //If we have a Kinect Sensor we will set it up
            if (null != KS)
            {
                // Turn on the color stream to receive color frames
                KS.ColorStream.Enable(ColorImageFormat.RgbResolution640x480Fps30);
                //Turn on the depth stream to recieve depth frames
                KS.DepthStream.Enable(DepthImageFormat.Resolution640x480Fps30);

                //Start the Streaming process
                KS.Start();
                //Create a link to a callback to deal with the frames
                KS.AllFramesReady += new EventHandler<AllFramesReadyEventArgs>(KS_AllFramesReady);

                //We set up a thread to process the image/disparty map from the kinect
                //Why? The kinect AllFramesReady has a timeout if it has not finished the streams will simply stop
                KinectBuffer = new Thread(ProcessBuffer);

                hsv_min = new Hsv(0, 45, 0);
                hsv_max = new Hsv(20, 255, 255);
                YCrCb_min = new Ycc(0, 131, 80);
                YCrCb_max = new Ycc(255, 185, 135);

                detector = new AdaptiveSkinDetector(1, AdaptiveSkinDetector.MorphingMethod.NONE);
                skinDetector = new YCrCbSkinDetector();
            }

我总是在新线程中使用kinect数据来提高速度,但是如果您计划进行更多繁重的处理,那么您可能希望将其提升为后台工作人员,以便更好地管理。

线程调用ProcessBuffer()方法,您可以忽略所有注释代码,因为这是用于显示深度图像的代码的剩余。我再次使用Marshall复制方法来保持快速,但要寻找的是WPF中的Dispatcher.BeginInvoke,它允许从Kinect线程显示图像。这是必需的,因为我没有处理主线程。

        //This takes the byte[] array from the kinect and makes a bitmap from the colour data for us
        byte[] pixeldata = new byte[CF.PixelDataLength];
        CF.CopyPixelDataTo(pixeldata);
        System.Drawing.Bitmap bmap = new System.Drawing.Bitmap(CF.Width, CF.Height, System.Drawing.Imaging.PixelFormat.Format32bppRgb);
        BitmapData bmapdata = bmap.LockBits(new System.Drawing.Rectangle(0, 0, CF.Width, CF.Height), ImageLockMode.WriteOnly, bmap.PixelFormat);
        IntPtr ptr = bmapdata.Scan0;
        Marshal.Copy(pixeldata, 0, ptr, CF.PixelDataLength);
        bmap.UnlockBits(bmapdata);
        //display our colour frame
        currentFrame = new Image<Bgr, Byte>(bmap);


        Image<Gray, Byte> skin2 = skinDetector.DetectSkin(currentFrame, YCrCb_min, YCrCb_max);
        ExtractContourAndHull(skin2);

        DrawAndComputeFingersNum();

        //Display our images using WPF Dispatcher Invoke as this is a sub thread.
        Dispatcher.BeginInvoke((Action)(() =>
            {
                ColorImage.Source = BitmapSourceConvert.ToBitmapSource(currentFrame);
            }), System.Windows.Threading.DispatcherPriority.Render, null);
        Dispatcher.BeginInvoke((Action)(() =>
            {
                SkinImage.Source = BitmapSourceConvert.ToBitmapSource(skin2);
            }), System.Windows.Threading.DispatcherPriority.Render, null);

我希望这有助于我在某些时候消除我上传的代码,

干杯