Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

Webcam->.avi - Webcam->.png etc etc


  • Please log in to reply
10 replies to this topic
EmanResu
  • Members
  • 5 posts
  • Last active: Apr 20 2012 10:52 AM
  • Joined: 31 Mar 2011
I saw a link to the OpenCV library posted in AFH the other day and remembered using it a while back. Not finding much about it on the forums, I decided to make a quick wrapper for it.

OpenCV is a complete webcam (or any other camera) library that allows you to easily capture and save webcam streams and play them back. Actually, it is a massive library that allows you to do about anything you can imaging with a webcam or image, but I focused only on the capture/save part :)

The example script demonstrates grabbing a single frame from the camera and saving it as a .png file. It then captures video encoded with a user-selected codec and saves it to an .avi file.

This zip containing the example script/wrapper and required dll: <!-- m -->https://ahknet.autoh...bcam/webcam.zip<!-- m -->

Wrapper:
/* OpenCV can be found here: http://opencv.willowgarage.com/wiki/
/* Please read the included 'OpenCV library license.txt' file for the OpenCV license.
/*
/* The included libraries can be found here: http://sourceforge.net/projects/opencvlibrary/files/opencv-win/2.1/
/* The were taken from the OpenCV-2.1.0-win32-vs2008.exe download.
/*
/* The OpenCV library exports a HUGE ammount of functions. This wrapper just scratches the
/* surface & serves as a basic template. No guarantees that everything here is correct.
*/

CV_CAP_ANY	:= 0 ; autodetect
CV_CAP_MIL	:= 100 ; MIL proprietary drivers
CV_CAP_VFW	:= 200 ; platform native
CV_CAP_V4L	:= 200
CV_CAP_V4L2	:= 200
CV_CAP_FIREWARE	:= 300 ; IEEE 1394 drivers
CV_CAP_FIREWIRE	:= 300
CV_CAP_IEEE1394	:= 300
CV_CAP_DC1394		:= 300
CV_CAP_CMU1394	:= 300
CV_CAP_STEREO	:= 400 ; TYZX proprietary drivers
CV_CAP_TYZX		:= 400
CV_TYZX_LEFT	:= 400
CV_TYZX_RIGHT	:= 401
CV_TYZX_COLOR	:= 402
CV_TYZX_Z			:= 403
CV_CAP_QT	:= 500 ; QuickTime
CV_CAP_UNICAP	:= 600 ; Unicap drivers
CV_CAP_DSHOW	:= 700 ; DirectShow (via videoInput)
CV_CAP_PVAPI	:= 800 ; PvAPI, Prosilica GigE SDK
CV_WINDOW_AUTOSIZE	:= 1

CV_FOURCC(c1,c2,c3,c4){
	return % (Asc(c1)&255)+((Asc(c2)&255)<<8)+((Asc(c3)&255)<<16)+((Asc(c4)&255)<<24)
}
cvNamedWindow(wn,flags){
	return DllCall("highgui210\cvNamedWindow","AStr",wn,"Int",flags,"Cdecl")
}
cvDestroyWindow(wn){
	DllCall("highgui210\cvDestroyWindow","AStr",wn,"Cdecl")
}
cvCaptureFromCAM(index){
	return DllCall("highgui210\cvCreateCameraCapture","Int",index,"Cdecl")
}
cvReleaseCapture(cap){
	DllCall("highgui210\cvReleaseCapture","UIntP",cap,"Cdecl")
}
cvQueryFrame(cap){
	return DllCall("highgui210\cvQueryFrame","UInt",cap,"Cdecl")
}
cvShowImage(window,image){
	DllCall("highgui210\cvShowImage","AStr",window,"UInt",image,"Cdecl")
}
cvSaveImage(fn,frame){
	return DllCall("highgui210\cvSaveImage","AStr",fn,"UInt",frame,"Cdecl")
}
cvCreateVideoWriter(fn,fourcc,fps,ByRef frame_size,is_color = 1){
	return DllCall("highgui210\cvCreateVideoWriter","AStr",fn,"UInt",fourcc,"Double",fps,"UInt",frame_size,"Int",is_color,"Cdecl")
}
cvWriteFrame(writer,image){
	return DllCall("highgui210\cvWriteFrame","UInt",writer,"UInt",image,"Cdecl")
}
cvReleaseVideoWriter(writer){
	DllCall("highgui210\cvReleaseVideoWriter","UIntP",writer,"Cdecl")
}
cvGrabFrame(cap){
	return DllCall("highgui210\cvGrabFrame","UInt",cap,"Cdecl")
}
cvRetrieveFrame(cap){
	return DllCall("highgui210\cvRetrieveFrame","UInt",cap,"Cdecl")
}
cvWaitKey(delay){
	return DllCall("highgui210\cvWaitKey","Int",delay,"Cdecl")
}
cvGetTickCount(){
	return DllCall("cxcore210\cvGetTickCount","UInt",0,"Cdecl")
}
cvGetTickFrequency(){
	return DllCall( "cxcore210\cvGetTickFrequency","UInt",0,"Cdecl")
}



Record( capDev=0,fn="video.avi",fourcc=-1,fps=9.97,w=640,h=480,isColor=1 ){
	Global CV_WINDOW_AUTOSIZE
	
	capture := 0
	VarSetCapacity( size,8,0 )
	NumPut( w,size,0,"Int")
	NumPut( h,size,4,"Int")
	
	; Grab a capture device
	capture := cvCaptureFromCAM( capDev )
	if( !capture )
	{
		MsgBox, 16, cvCaptureFromCAM Error, ErrorLevel=%ErrorLevel%`nA_LastError=%A_LastError%
		ExitApp
	}

	; Create the video writer
	writer := cvCreateVideoWriter( fn,fourcc,fps,size,isColor )
	If ( !writer )
	{
		MsgBox, 16,cvCreateVideoWriter Error, ErrorLevel=%ErrorLeveL%`nA_LastError=%A_LastError%
		ExitApp
	}
	
	; Create the preview window
	cvNamedWindow( fn,CV_WINDOW_AUTOSIZE )

	; Don't need the auto-delay here...
	batch := A_BatchLines
	SetBatchLines, -1
	
	; Capture loop
	While( 1 ) {
		img := cvQueryFrame( capture ) ; Capture a frame
		cvWriteFrame( writer,img ) ; Write that frame to file
		cvShowImage( fn,img ) ; Show the frame in the preview window
		if ( ( cvWaitKey( 30 )&255 ) == 27 )	; Break if Escape key is pressed
			break
	}
	
	SetBatchLines, %A_BatchLines%
	
	; Cleanup
	cvReleaseVideoWriter( writer )
	cvReleaseCapture( capture )
	cvDestroyWindow( fn )
}



SaveFrame( capDev=0,fn="capture.jpg" ){
	; Grab a capture device
	capture := cvCaptureFromCAM( capDev )
	if( !capture )
	{
		MsgBox, 16, Error, Unable to find a suitable capture device.
		ExitApp
	}
	
	; Grab & save the image
	cvSaveImage( fn, cvQueryFrame( capture ) )
	
	; Cleanup
	cvReleaseCapture( capture )
}
Example:
#NoEnv
SetWorkingDir %A_ScriptDir%
OnExit, Exiting
	
#include CV_Wrapper.ahk

hLib := DllCall( "LoadLibrary", "Str", "highgui210.dll" )
if ( !hLib )
{
	MsgBox, 16, LoadLibrary, hLib=%hLib%`nErrorLevel=%ErrorLeveL%`nA_LastError=%A_LastError%
	ExitApp
}

; Grab a single frame and save it to disk
; Just SaveFrame() will work also
SaveFrame( CV_CAP_ANY,"CamShot.png")


/*
/*	FOURCC codecs - All may not work/work correctly
/*
/*	CV_FOURCC("M","J","P","G")    = motion-jpeg codec (does not work well)
/*	CV_FOURCC("M", "P", "4", "2") = MPEG-4.2 codec
/*	CV_FOURCC("D", "I", "V", "3")  = MPEG-4.3 codec
/*	CV_FOURCC("D", "I", "V", "X")  = MPEG-4 codec
/*	CV_FOURCC("U", "2", "6", "3")  = H263 codec
/*	CV_FOURCC("I", "2", "6", "3")   = H263I codec
/*	CV_FOURCC("F", "L", "V", "1")   = FLV1 codec
/*
/*	More here: http://www.fourcc.org/codecs.php
*/

; Record from cam until the Escape key is pressed
; Just Record() will work also
Record( CV_CAP_ANY			; Prefered device index
			,"MyVideo.avi"	; File name for the video
			,-1								; Encoding (see above for FOURCC values, -1=ask)
			,9.97							; Desired frames-per-second
			,340							; Captured video width
			,280							; Captured video height
			,1 )							; Color flag (0=greyscale,non-0=color)

ExitApp

Exiting:
	if ( hLib )
		DllCall( "FreeLibrary", "UInt", hLib )
ExitApp

PS: Requires AHK_L x32

[edit]Bugfix & cleanup...
Press Enter To Exit...

specter333
  • Members
  • 627 posts
  • Last active: Oct 07 2016 07:43 AM
  • Joined: 15 Jan 2007
Wow, what perfect timing. We started a discussion in the help forums late last night about using a webcam to control a "Blink to Click" function for assisted computer browsing. EyeBlink:: Send {Click}

I've been thinking through several ideas about how to accomplish this and getting screen caps from a webcam is one of the leading technique ideas.

Just getting started so I don't know how it's going to go but having this library already in place makes things much simpler.

Thanks

*EmanResu
  • Guests
  • Last active:
  • Joined: --

Wow, what perfect timing. We started a discussion in the help forums late last night about using a webcam to control a "Blink to Click" function for assisted computer browsing. EyeBlink:: Send {Click}


I'm not sure this would be useful in that case because normally only one program can access a camera at a time, and his tracking software will already be using the one he'd want to check.

I think that's more a case for Pixel/Image search in the window that shows the circles around the eyes that he mentioned.

Anyhow, eye tracking/blink detection can be done with OpenCV, see:
http://nashruddin.co...V_Eye_Detection
http://nashruddin.co...k-user-eye.html
http://opencv-code.c... ... _Detection

:)

JamesC
  • Guests
  • Last active:
  • Joined: --
Any way to specify the image size when doing a capture? I see it is possible with video capture but not image capture.

AndhiT
  • Members
  • 25 posts
  • Last active: Oct 04 2011 07:22 AM
  • Joined: 06 Sep 2011
Nice Job. Do you plan to write a wrapper for Eigenface functions? (i.e. face detection / face recognition).

aaronbewza
  • Members
  • 466 posts
  • Last active: Feb 05 2013 08:40 AM
  • Joined: 20 Feb 2011
this ROCKS! I've attached my webcam to my microscope and this is what I now can see (much better than jamming my eye up to it lol) :

Posted Image

Posted Image

This is a piece of human peripheral nerve @ 100x and then 400x magnification.
Thank you for this, it is very useful :)

EDIT: bug report... it does not want to close, even when I press and hold ESC only the gui is closed but the script keeps running. Even right-clicking the tray icon and selecting "exit" will not work unless ESC has been pressed first.
When I assign a hotkey 'C' to take an image capture, it freezes the display and in SCITE (in the output window on the bottom of the screen) it shows this, over and over again looping like mad:
OpenCV Error: Sizes of input arguments do not match (image size is different from the currently set frame size) in CvVideoWriter_VFW::writeFrame, file ..\..\..\..\ocv\opencv\src\highgui\cvcap_vfw.cpp

OpenCV Error: Incorrect size of input array (Non-positive cols or rows) in unknown function, file ..\..\..\..\ocv\opencv\src\cxcore\cxarray.cpp

This error points to line 85 of CV_Wrapper.ahk, and I have no idea what's going on. Any thoughts? I've placed the contents of CV_Wrapper into the main script, underneath all the code, but this happens even if CV_Wrapper is left as its own file and is included.

*EmanResu
  • Guests
  • Last active:
  • Joined: --
I'm not sure what your modified script is to capture the image, but it sounds like you have the script recording an AVI file at the same time? Intentional?

To set 'C' up to capture a single image, it should look like this:
#NoEnv
SetWorkingDir %A_ScriptDir%
OnExit, Exiting
	
#include CV_Wrapper.ahk

OnExit, Exiting
index := 0

hLib := DllCall( "LoadLibrary", "Str", "highgui210.dll" )
if ( !hLib )
{
	MsgBox, 16, LoadLibrary, hLib=%hLib%`nErrorLevel=%ErrorLeveL%`nA_LastError=%A_LastError%
	ExitApp
}

; Grab a single frame and save it to disk
; Just SaveFrame() will work also
c::
	index++
	SaveFrame( CV_CAP_ANY,"CamShot" . index . ".png")
Return

Esc::ExitApp

Exiting:
	if ( hLib )
		DllCall( "FreeLibrary", "UInt", hLib )
ExitApp

Glad it was useful and those are some nice pics!

  • Guests
  • Last active:
  • Joined: --

Do you plan to write a wrapper for Eigenface functions? (i.e. face detection / face recognition).


Sorry, missed this until now.

I don't have plans to wrap any more of this library right now. I just don't have the time atm. It would be nice if someone would wrap it and share, tho. :)

I had planned to try some OCR with it but never got around to it. That's my plan once I have some free time.

aaronbewza
  • Members
  • 466 posts
  • Last active: Feb 05 2013 08:40 AM
  • Joined: 20 Feb 2011
There is no change at all with your suggestion. I had the "c" button
mapped exactly the same and in the same location (except for the
index++ command, very nice!). This is what I have (function is at bottom
instead of separate script) :
#NoEnv
SetWorkingDir %A_ScriptDir%
OnExit, Exiting

;#include CV_Wrapper.ahk ; This is at the bottom of the script instead of included

OnExit, Exiting
index := 0

hLib := DllCall( "LoadLibrary", "Str", "highgui210.dll" )
if ( !hLib )
{
   MsgBox, 16, LoadLibrary, hLib=%hLib%`nErrorLevel=%ErrorLeveL%`nA_LastError=%A_LastError%
   ExitApp
}

;	FOURCC codecs - All may not work/work correctly
;	CV_FOURCC("M","J","P","G")    = motion-jpeg codec (does not work well)
;	CV_FOURCC("M", "P", "4", "2") = MPEG-4.2 codec
;	CV_FOURCC("D", "I", "V", "3")  = MPEG-4.3 codec
;	CV_FOURCC("D", "I", "V", "X")  = MPEG-4 codec
;	CV_FOURCC("U", "2", "6", "3")  = H263 codec
;	CV_FOURCC("I", "2", "6", "3")   = H263I codec
;	CV_FOURCC("F", "L", "V", "1")   = FLV1 codec

;	More here: http://www.fourcc.org/codecs.php

; Record from cam until the Escape key is pressed
; Just Record() will work also

Record( CV_CAP_ANY			; Prefered device index
			,"MyVideo.avi"	; File name for the video
			,CV_FOURCC("D", "I", "V", "X")	; MPEG-4 Encoding (see above for FOURCC values, use -1 to have a choice)
			,9.97							; Desired frames-per-second
			,340							; Captured video width
			,280							; Captured video height
			,1 )							; Color flag (0=greyscale,non-0=color)
ExitApp

c:: ; Grab a single frame and save it to disk... 'SaveFrame()' will work also
	index++
	SaveFrame( CV_CAP_ANY,"CamShot" . index . ".png")
Return

Esc::ExitApp

Exiting:
	if ( hLib )
		DllCall( "FreeLibrary", "UInt", hLib )
ExitApp

 ; --- CV_Wrapper functions --------------------------------------------------------------------------------------->>

; OpenCV can be found here: http://opencv.willowgarage.com/wiki/
; Please read the included 'OpenCV library license.txt' file for the OpenCV license.
; The included libraries can be found here: http://sourceforge.net/projects/opencvlibrary/files/opencv-win/2.1/
; The were taken from the OpenCV-2.1.0-win32-vs2008.exe download.
;
; The OpenCV library exports a HUGE ammount of functions. This wrapper just scratches the
; surface & serves as a basic template. No guarantees that everything here is correct.


CV_CAP_ANY	:= 0 ; autodetect
CV_CAP_MIL	:= 100 ; MIL proprietary drivers
CV_CAP_VFW	:= 200 ; platform native
CV_CAP_V4L	:= 200
CV_CAP_V4L2	:= 200
CV_CAP_FIREWARE	:= 300 ; IEEE 1394 drivers
CV_CAP_FIREWIRE	:= 300
CV_CAP_IEEE1394	:= 300
CV_CAP_DC1394		:= 300
CV_CAP_CMU1394	:= 300
CV_CAP_STEREO	:= 400 ; TYZX proprietary drivers
CV_CAP_TYZX		:= 400
CV_TYZX_LEFT	:= 400
CV_TYZX_RIGHT	:= 401
CV_TYZX_COLOR	:= 402
CV_TYZX_Z			:= 403
CV_CAP_QT	:= 500 ; QuickTime
CV_CAP_UNICAP	:= 600 ; Unicap drivers
CV_CAP_DSHOW	:= 700 ; DirectShow (via videoInput)
CV_CAP_PVAPI	:= 800 ; PvAPI, Prosilica GigE SDK
CV_WINDOW_AUTOSIZE	:= 1

CV_FOURCC(c1,c2,c3,c4){
	return % (Asc(c1)&255)+((Asc(c2)&255)<<8)+((Asc(c3)&255)<<16)+((Asc(c4)&255)<<24)
}
cvNamedWindow(wn,flags){
	return DllCall("highgui210\cvNamedWindow","AStr",wn,"Int",flags,"Cdecl")
}
cvDestroyWindow(wn){
	DllCall("highgui210\cvDestroyWindow","AStr",wn,"Cdecl")
}
cvCaptureFromCAM(index){
	return DllCall("highgui210\cvCreateCameraCapture","Int",index,"Cdecl")
}
cvReleaseCapture(cap){
	DllCall("highgui210\cvReleaseCapture","UIntP",cap,"Cdecl")
}
cvQueryFrame(cap){
	return DllCall("highgui210\cvQueryFrame","UInt",cap,"Cdecl")
}
cvShowImage(window,image){
	DllCall("highgui210\cvShowImage","AStr",window,"UInt",image,"Cdecl")
}
cvSaveImage(fn,frame){
	return DllCall("highgui210\cvSaveImage","AStr",fn,"UInt",frame,"Cdecl")
}
cvCreateVideoWriter(fn,fourcc,fps,ByRef frame_size,is_color = 1){
	return DllCall("highgui210\cvCreateVideoWriter","AStr",fn,"UInt",fourcc,"Double",fps,"UInt",frame_size,"Int",is_color,"Cdecl")
}
cvWriteFrame(writer,image){
	return DllCall("highgui210\cvWriteFrame","UInt",writer,"UInt",image,"Cdecl")
}
cvReleaseVideoWriter(writer){
	DllCall("highgui210\cvReleaseVideoWriter","UIntP",writer,"Cdecl")
}
cvGrabFrame(cap){
	return DllCall("highgui210\cvGrabFrame","UInt",cap,"Cdecl")
}
cvRetrieveFrame(cap){
	return DllCall("highgui210\cvRetrieveFrame","UInt",cap,"Cdecl")
}
cvWaitKey(delay){
	return DllCall("highgui210\cvWaitKey","Int",delay,"Cdecl")
}
cvGetTickCount(){
	return DllCall("cxcore210\cvGetTickCount","UInt",0,"Cdecl")
}
cvGetTickFrequency(){
	return DllCall( "cxcore210\cvGetTickFrequency","UInt",0,"Cdecl")
}



Record( capDev=0,fn="video.avi",fourcc=-1,fps=9.97,w=640,h=480,isColor=1 ){
	Global CV_WINDOW_AUTOSIZE
	
	capture := 0
	VarSetCapacity( size,8,0 )
	NumPut( w,size,0,"Int")
	NumPut( h,size,4,"Int")
	
	; Grab a capture device
	capture := cvCaptureFromCAM( capDev )
	if( !capture )
	{
		MsgBox, 16, cvCaptureFromCAM Error, ErrorLevel=%ErrorLevel%`nA_LastError=%A_LastError%
		ExitApp
	}

	; Create the video writer
	writer := cvCreateVideoWriter( fn,fourcc,fps,size,isColor )
	If ( !writer )
	{
		MsgBox, 16,cvCreateVideoWriter Error, ErrorLevel=%ErrorLeveL%`nA_LastError=%A_LastError%
		ExitApp
	}
	
	; Create the preview window
	cvNamedWindow( fn,CV_WINDOW_AUTOSIZE )

	; Don't need the auto-delay here...
	batch := A_BatchLines
	SetBatchLines, -1
	
	; Capture loop
	While( 1 ) {
		img := cvQueryFrame( capture ) ; Capture a frame
		cvWriteFrame( writer,img ) ; Write that frame to file
		cvShowImage( fn,img ) ; Show the frame in the preview window
		if ( ( cvWaitKey( 30 )&255 ) == 27 )	; Break if Escape key is pressed
			break
	}
	
	SetBatchLines, %A_BatchLines%
	
	; Cleanup
	cvReleaseVideoWriter( writer )
	cvReleaseCapture( capture )
	cvDestroyWindow( fn )
}



SaveFrame( capDev=0,fn="capture.jpg" ){
	; Grab a capture device
	capture := cvCaptureFromCAM( capDev )
	if( !capture )
	{
		MsgBox, 16, Error, Unable to find a suitable capture device.
		ExitApp
	}
	
	; Grab & save the image
	cvSaveImage( fn, cvQueryFrame( capture ) )
	
	; Cleanup
	cvReleaseCapture( capture )
}

I'm not sure what is going on but when I press "c" the GUI image is
paused and if I close it, it only reopens paused. If I press ESC then the
GUI disappears but then I have to close the script's process in task
manager to actually exit the script.
It looks like you are short for time, but if you can help figure this out,
I could, and will, make a "Microscope Viewing Utility" with this, with a GUI and save options.

*EmanResu
  • Guests
  • Last active:
  • Joined: --
The problem is that you are trying to take a screen shot at a different resolution while the script is capturing frames and writing to disk.

I haven't dived into it very deep, but if nothing else you can just stop streaming capture when a screenshot needs taken (releasing the device) and then resume streaming capture.

Sloppy but doable until I get a chance to look into it more.

aaronbewza
  • Members
  • 466 posts
  • Last active: Feb 05 2013 08:40 AM
  • Joined: 20 Feb 2011
thank you very much! I will try to make that happen in your absence, that seems like the best way to approach it. :)