I am working on C# and using OpenTK
(OpenGL wrapper) and EmguCV
(OpenCV wrapper).
What I want to do is easy to understand: Grab the webcam video stream and put it on a GLControl
.
I have a static class
called Capturer
which has a method that captures a frame and returns it as a cv::Mat
wrapped object:
internal static void Initialize()
{
cap = new VideoCapture(1);
cap.SetCaptureProperty(Emgu.CV.CvEnum.CapProp.Fps, 25);
cap.SetCaptureProperty(Emgu.CV.CvEnum.CapProp.FrameWidth, 1920);
cap.SetCaptureProperty(Emgu.CV.CvEnum.CapProp.FrameHeight, 1080);
}
internal static Mat GetCurrentFrame()
{
mat = cap.QueryFrame();
if (!mat.IsEmpty)
{
return mat;
}
return null;
}
Now in my GLControl
Load event
I initialize the capturer and OpenGL:
Capturer.Initialize();
GL.ClearColor(Color.Blue);
GL.Enable(EnableCap.Texture2D);
GL.Viewport(-glControl1.Width, -glControl1.Height, glControl1.Width * 2, glControl1.Height * 2);
And finally, in the GLControl
Paint event
:
GL.Clear(ClearBufferMask.ColorBufferBit);
GL.MatrixMode(MatrixMode.Projection);
GL.LoadIdentity();
Mat m = Capturer.GetCurrentFrame();
if (m != null)
{
GL.GenTextures(1, out textureId);
GL.BindTexture(TextureTarget.Texture2D, this.textureId);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (float)TextureMinFilter.Nearest);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (float)TextureMagFilter.Linear);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (float)TextureWrapMode.Clamp);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (float)TextureWrapMode.Clamp);
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgb, 1920, 1080, 0, OpenTK.Graphics.OpenGL.PixelFormat.Bgr, PixelType.UnsignedByte, m.DataPointer);
}
m.Dispose();
glControl1.SwapBuffers();
glControl1.Invalidate();
This is showing a full Blue screen. I think the error is on m.DataPointer
.
(I have tried rendering the frames with Bitmap
using the property m.Bitmap
and it works but the performance is so bad.)
Drawing a rectangle bounding the GLControl
solved it:
GL.Begin(PrimitiveType.Quads);
GL.TexCoord2(0, 0); GL.Vertex2(0, 0);
GL.TexCoord2(0, 1); GL.Vertex2(0, 1);
GL.TexCoord2(1, 1); GL.Vertex2(1, 1);
GL.TexCoord2(1, 0); GL.Vertex2(1, 0);
GL.End();
m.Dispose();
Be sure to dispose the object after drawing the frame so you will not run out of memory.