sheldon90
sheldon90

Reputation: 115

Can't Draw SharpGL(openGL wrapper) object in EMGU CV

I've been working with emgu cv(opencv wrapper to capture images from a webcam and using its functions to proccess this images. I also detect the hand and track the hand movement...

Now, I need to draw a kind of earth or just an object according to the hand position, for which sharpGL is perfect for perspective transformation and so on. My problem is that I can't achieve that.

I don't know how to say to sharpGL "you guy, draw that object within this hand tracking window" Is it impossible what I want to do? I am desperate... any help would be great. Thanks in advance

see this video if you're still confused about what I meant (http://www.youtube.com/watch?v=ccL4t36sVvg)

so far, I've just translated this code http://blog.damiles.com/2008/10/opencv-opengl/ into C#

and here's code snippet

private void openGLControl_OpenGLInitialized(object sender, EventArgs e)
        {
            //  TODO: Initialise OpenGL here.

            //  The texture identifier.
            uint[] textures = new uint[1];

            //  Get the OpenGL object.
            OpenGL gl = openGLControl1.OpenGL;

            //texture.Create(gl);

            //  Get one texture id, and stick it into the textures array.
            gl.GenTextures(1, textures);

            //  Bind the texture.
            gl.BindTexture(OpenGL.GL_TEXTURE_2D, textures[0]);

            //  A bit of extra initialisation here, we have to enable textures.
            gl.Enable(OpenGL.GL_TEXTURE_2D);

            //  Specify linear filtering.
            gl.TexParameter(OpenGL.GL_TEXTURE_2D, OpenGL.GL_TEXTURE_MIN_FILTER, OpenGL.GL_NEAREST);
            gl.TexParameter(OpenGL.GL_TEXTURE_2D, OpenGL.GL_TEXTURE_MAG_FILTER, OpenGL.GL_NEAREST);

            gl.PixelStore(OpenGL.GL_UNPACK_ALIGNMENT, 1);

            //  Set the clear color.
            gl.ClearColor(1.0f, 1.0f, 1.0f, 1.0f);
        }


private void openGLControl_Resized(object sender, EventArgs e)
        {
            //  TODO: Set the projection matrix here.

            //  Get the OpenGL object.
            OpenGL gl = openGLControl1.OpenGL;
            //  Set the projection matrix.
            gl.MatrixMode(OpenGL.GL_PROJECTION);

            //  Load the identity.
            gl.LoadIdentity();

            //  Create a perspective transformation.
            gl.Perspective(60.0f, (double)Width / (double)Height, 0.01, 100.0);

            //  Use the 'look at' helper function to position and aim the camera.
            gl.LookAt(-5, 5, -5, 0, 0, 0, 0, 1, 0);

            //  Set the modelview matrix.
            gl.MatrixMode(OpenGL.GL_MODELVIEW);
        }

and finally draw an 3D object

private void openGLControl_OpenGLDraw(object sender, PaintEventArgs e)
        {
            //  Get the OpenGL object.
            OpenGL gl = openGLControl1.OpenGL;

            if (capture == null)
            {
                this.start_capture();
            }

            if (capture != null)
            {
                Image<Bgr, Byte> ImageFrame = capture.QueryFrame();

                //I'm trying to use some algorithm using the code from sample (sharpGLTextureExample)
                //first, I make an Bitmap object that I take from queryframe(convert it to bitmap first)
                Bitmap image = new Bitmap(ImageFrame.ToBitmap());


                //  Clear the color and depth buffer.
                gl.Clear(OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT);
                //ImageFrame.Draw(new Rectangle(2, 2, 2, 2), new Bgr(Color.Aqua), 2);


                //  Load the identity matrix.
                gl.LoadIdentity();

                //then, Lock the image bits (so that we can pass them to OGL).
                BitmapData bitmapData = image.LockBits(new Rectangle(0, 0, image.Width, image.Height),
                ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);

                gl.BindTexture(OpenGL.GL_TEXTURE_2D, textures[0]);
                //gl.TexImage2D(OpenGL.GL_TEXTURE_2D, 0, (int)OpenGL.GL_RGBA, ImageFrame.Width, ImageFrame.Height, 0, OpenGL.GL_RGBA, OpenGL.GL_UNSIGNED_BYTE, ImageFrame);
                gl.TexImage2D(OpenGL.GL_TEXTURE_2D, 0, (int)OpenGL.GL_RGBA, ImageFrame.Width, ImageFrame.Height, 0, OpenGL.GL_RGBA, OpenGL.GL_UNSIGNED_BYTE, bitmapData.Scan0);


                //gl.Begin(OpenGL.GL_QUADS);

                //gl.TexCoord(0, 0); gl.Vertex(-1, -1, 0);
                //gl.TexCoord(1, 0); gl.Vertex(1, -1, 0);
                //gl.TexCoord(1, 5); gl.Vertex(1, 1, 0);
                //gl.TexCoord(0, 1); gl.Vertex(-1, 1, 0);
                //gl.End();

                //gl.Flush();

                //texture.Bind(gl);
                //
                //CamImageBox.Image = ImageFrame;
            }

        }

but the output always return an white, no texture on it...

I've also consindering to use Texture class, but it's no use..because there's no method which the input parameter is the frame...

Upvotes: 0

Views: 2258

Answers (1)

From your code and help from http://basic4gl.wikispaces.com/2D+Drawing+in+OpenGL, I got SharpGL displaying a video from EmguCV

public partial class FormSharpGLTexturesSample : Form
{
    Capture capture;
    public FormSharpGLTexturesSample()
    {
        InitializeComponent();

        //  Get the OpenGL object, for quick access.
        SharpGL.OpenGL gl = this.openGLControl1.OpenGL;

        //  A bit of extra initialisation here, we have to enable textures.
        gl.Enable(OpenGL.GL_TEXTURE_2D);
        gl.Disable(OpenGL.GL_DEPTH_TEST);

        //  Create our texture object from a file. This creates the texture for OpenGL.

        capture = new Capture(@"Video file here");
    }

    private void openGLControl1_OpenGLDraw(object sender, RenderEventArgs e)
    {
        //  Get the OpenGL object, for quick access.
        SharpGL.OpenGL gl = this.openGLControl1.OpenGL;
        int Width = openGLControl1.Width;
        int Height = openGLControl1.Height;

        gl.Clear(OpenGL.GL_COLOR_BUFFER_BIT);
        gl.LoadIdentity();

        var frame = capture.QueryFrame();
        texture.Destroy(gl);
        texture.Create(gl, frame.Bitmap);

        //  Bind the texture.
        texture.Bind(gl);

        gl.Begin(OpenGL.GL_QUADS);

        gl.TexCoord(0.0f, 0.0f); gl.Vertex(0, 0, 0);
        gl.TexCoord(1.0f, 0.0f); gl.Vertex(Width, 0, 0);
        gl.TexCoord(1.0f, 1.0f); gl.Vertex(Width, Height, 0);
        gl.TexCoord(0.0f, 1.0f); gl.Vertex(0, Height, 0);

        gl.End();

        gl.Flush();
    }



    //  The texture identifier.
    Texture texture = new Texture();

    private void openGLControl1_Resized(object sender, EventArgs e)
    {
        SharpGL.OpenGL gl = this.openGLControl1.OpenGL;
        //  Create an orthographic projection.
        gl.MatrixMode(MatrixMode.Projection);
        gl.LoadIdentity();

        // NOTE: Basically no matter what I do, the only points I see are those at
        // the "near" surface (with z = -zNear)--in this case, I only see green points
        gl.Ortho(0, openGLControl1.Width, openGLControl1.Height, 0, 0, 1);

        //  Back to the modelview.
        gl.MatrixMode(MatrixMode.Modelview);
    }
}

I hope it helps.

After some experiments, I could use TexImage2D but only with images having a width and height be a power of two

Instead of:

var frame = capture.QueryFrame();
texture.Destroy(gl);
texture.Create(gl, frame.Bitmap);

It can be replaced by the following block to update the data of the picture. I would like to know how to remove the need to call Resize.

var frame = capture.QueryFrame();
frame = frame.Resize(256, 256, Emgu.CV.CvEnum.INTER.CV_INTER_NN);
Bitmap Bitmap = frame.Bitmap;
BitmapData bitmapData = Bitmap.LockBits(new Rectangle(0, 0, Bitmap.Width, Bitmap.Height),
    ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);

gl.BindTexture(OpenGL.GL_TEXTURE_2D, textures[0]);
gl.TexImage2D(OpenGL.GL_TEXTURE_2D, 0, OpenGL.GL_RGBA, Bitmap.Width, Bitmap.Height, 0, OpenGL.GL_BGR, OpenGL.GL_UNSIGNED_BYTE, bitmapData.Scan0);

gl.TexParameter(OpenGL.GL_TEXTURE_2D, OpenGL.GL_TEXTURE_MIN_FILTER, OpenGL.GL_LINEAR); // Required for TexImage2D
gl.TexParameter(OpenGL.GL_TEXTURE_2D, OpenGL.GL_TEXTURE_MAG_FILTER, OpenGL.GL_LINEAR); // Required for TexImage2D

Upvotes: 1

Related Questions