我遇到了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;
}
现在,演示应用程序正常运行,而我的则不然。我给出了以下例外:
而且,此处的图片包含以下内容:
我真的不明白这个例外。而且,现在,当我运行演示时,工作应用程序,图像,包含:
在我看来,这是完全一样的。我真的不明白这一点。非常欢迎帮助!
答案 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);
我希望这有助于我在某些时候消除我上传的代码,
干杯