4 Replies - 2589 Views - Last Post: 27 August 2012 - 03:08 PM Rate Topic: -----

#1 Tim Sloane  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 13
  • Joined: 27-August 12

Access a captured frame from a webcam.

Posted 27 August 2012 - 12:53 PM

Hello everyone!

I'm currently trying to write a simple C++ program as an experiment that processes images from a webcam through a QR code reader. I'm using the zxing library and VC++ 2010.

The zxing library takes in an ImageMagick Image Class, so I'm trying to figure out how to turn a frame captured from a webcam into an Image object.

Going by snoopy11's tutorial, I could just create temporary bitmaps that are scanned, but that seems like it would be a lot slower than if I had some way to directly access the captured frame. However, I've Googled WM_CAP_GRAB_FRAME and the Windows Media API for over an hour, and haven't gotten anywhere.

Is there some way I can access the captured webcam frame, without having to go through the clipboard?

Is This A Good Question/Topic? 0
  • +

Replies To: Access a captured frame from a webcam.

#2 Skydiver  Icon User is offline

  • Code herder
  • member icon

Reputation: 3485
  • View blog
  • Posts: 10,742
  • Joined: 05-May 12

Re: Access a captured frame from a webcam.

Posted 27 August 2012 - 02:23 PM

I've not ready Snoopy's tutorial, nor do I know anything about zxing, so take what you read with a grain of salt. I've only glanced at the two lines where he used WM_CAP_GRAB_FRAME and WM_CAP_EDIT_COPY. This seems to be the most efficient way to go about things because you get a DIB format right away, and I think you can pass that along to the ImageMagick Image Class constructors. If the BLOB construcor doesn't detect the DIB, then you can pass in the pixels as needed.

As you've said though, you'd rather get access to the frame data directly.

You must have been Googling and just looking for code, rather than reading and trying to piece together a picture of how things work. I simply searched for "WM_CAP_GRAB_FRAME" in Google and the firs link found was the MSDN documentation: http://msdn.microsof...9(v=vs.85).aspx

In the remarks it says this:

Quote

Remarks
For information about installing callback functions, see the WM_CAP_SET_CALLBACK_ERROR and WM_CAP_SET_CALLBACK_FRAME messages.


Following the link to WM_CAP_SET_CALLBACK_FRAME, where it says this:

Quote

The WM_CAP_SET_CALLBACK_FRAME message sets a preview callback function in the application. AVICap calls this procedure when the capture window captures preview frames. You can send this message explicitly or by using the capSetCallbackOnFrame macro.
:
The capture window calls the callback function before displaying preview frames. This allows an application to modify the frame if desired. This callback function is not used during streaming video capture.


We must be getting warmer.

Following the documentation for the callback function, we see that one of the parameters is VIDEOHDR which contains the image data.

And all of this is confirmed by the MSDN documentation page about VFW and capturing without writing to disk:

Quote

You can use capture services without writing the data to a disk file by using the WM_CAP_SEQUENCE_NOFILE message (or the capCaptureSequenceNoFile macro). This message is useful only in conjunction with callback functions that allow your application to use the video and audio data directly. For example, videoconferencing applications might use this message to obtain streaming video frames. The callback functions would transfer the captured images to the remote computer.


So the open question is: what is the data format of the data pointed to by the VIDEOHDR? I can't confirm, but I suspect that it is just the data bits of a DIB since WM_CAP_GET_VIDEOFORMAT just fills in a BITMAPINFO structure.

And this C# CodeProject seems to confirm that idea: http://www.codeproje...reading-and-VFW
Was This Post Helpful? 0
  • +
  • -

#3 snoopy11  Icon User is offline

  • Engineering ● Software
  • member icon

Reputation: 765
  • View blog
  • Posts: 2,226
  • Joined: 20-March 10

Re: Access a captured frame from a webcam.

Posted 27 August 2012 - 02:46 PM

Hi,

No you dont have to go through the clipboard,
The only reason I do this is because at the time I was interested
in writing my own bitmap saving routine..

You can use WM_CAP_FILE_SAVEDIB

which is defined as (WM_USER + 25) for the ansi version.

Regards

Snoopy.
Was This Post Helpful? 1
  • +
  • -

#4 Tim Sloane  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 13
  • Joined: 27-August 12

Re: Access a captured frame from a webcam.

Posted 27 August 2012 - 02:55 PM

Skydiver,

I appreciate your help. I did read both the WM_CAP_SET_CALLBACK_FRAME and WM_CAP_GRAB_FRAME doc pages. However, I have little to no experience Win32 messages, so I was not able to interpret those pages like you did, and follow them to the pertinent information.

The only reason I mentioned zxing is for background. I wasn't trying to find anything specific for it.

And I especially appreciate the link to the C# project. That will be immensely helpful to me.


Snoopy,

Thanks for the info about WM_CAP_FILE_SAVEDIB (and for your tutorial that got me started in the first place :bigsmile: ). I'll try that out first before trying to access the frame directly.
Was This Post Helpful? 0
  • +
  • -

#5 snoopy11  Icon User is offline

  • Engineering ● Software
  • member icon

Reputation: 765
  • View blog
  • Posts: 2,226
  • Joined: 20-March 10

Re: Access a captured frame from a webcam.

Posted 27 August 2012 - 03:08 PM

Yeah it's quite easy,

All you have to do is ammend case 3: in WM_COMMAND to look like this

case 3:
        {

            //Save to a .bmp file called MyCapture.bmp
            
            LPSTR filename =(LPSTR)"MyCapture.bmp";
            SendMessage(camhwnd,WM_CAP_FILE_SAVEDIB, 0, (LPARAM) filename);
            SendMessage(camhwnd,WM_CAP_DRIVER_CONNECT,0,0);
            SendMessage(camhwnd, WM_CAP_SET_SCALE, true , 0);
            SendMessage(camhwnd, WM_CAP_SET_PREVIEWRATE, 66, 0);
            SendMessage(camhwnd, WM_CAP_SET_PREVIEW, true , 0);
            break;
        }





And thats all...

easy peasy lemon squeezy...
;)
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1