Seite 1 von 2

Webcam-Bild im Image, mit Kreis gezeichnet

Verfasst: 01.06.2010 13:13
von super_castle
Habe es jetzt geschafft, ein WebcamBild in ein Image zu packen und auch im Video/Image gleichzeitig zu zeichnen.
Kann jetzt schöne Filmtricks mit Video und gezeichneten Bild im Image herstellen.

Genial und Einfach.

Gruss

Code: Alles auswählen

#WM_CAP_START = #WM_USER
#WM_CAP_UNICODE_START = #WM_USER +100
#WM_CAP_PAL_SAVEA = #WM_CAP_START + 81
#WM_CAP_PAL_SAVEW = #WM_CAP_UNICODE_START + 81
#WM_CAP_UNICODE_END = #WM_CAP_PAL_SAVEW
#WM_CAP_ABORT = #WM_CAP_START + 69
#WM_CAP_DLG_VIDEOCOMPRESSION = #WM_CAP_START + 46
#WM_CAP_DLG_VIDEODISPLAY = #WM_CAP_START + 43
#WM_CAP_DLG_VIDEOFORMAT = #WM_CAP_START + 41
#WM_CAP_DLG_VIDEOSOURCE = #WM_CAP_START + 42
#WM_CAP_DRIVER_CONNECT = #WM_CAP_START + 10
#WM_CAP_DRIVER_DISCONNECT = #WM_CAP_START + 11
#WM_CAP_DRIVER_GET_CAPS = #WM_CAP_START + 14
#WM_CAP_DRIVER_GET_NAMEA = #WM_CAP_START + 12
#WM_CAP_DRIVER_GET_NAMEW = #WM_CAP_UNICODE_START + 12
#WM_CAP_DRIVER_GET_VERSIONA = #WM_CAP_START + 13
#WM_CAP_DRIVER_GET_VERSIONW = #WM_CAP_UNICODE_START + 13
#WM_CAP_EDIT_COPY = #WM_CAP_START + 30
#WM_CAP_END = #WM_CAP_UNICODE_END
#WM_CAP_FILE_ALLOCATE = #WM_CAP_START + 22
#WM_CAP_FILE_GET_CAPTURE_FILEA = #WM_CAP_START + 21
#WM_CAP_FILE_GET_CAPTURE_FILEW = #WM_CAP_UNICODE_START + 21
#WM_CAP_FILE_SAVEASA = #WM_CAP_START + 23
#WM_CAP_FILE_SAVEASW = #WM_CAP_UNICODE_START + 23
#WM_CAP_FILE_SAVEDIBA = #WM_CAP_START + 25
#WM_CAP_FILE_SAVEDIBW = #WM_CAP_UNICODE_START + 25
#WM_CAP_FILE_SET_CAPTURE_FILEA = #WM_CAP_START + 20
#WM_CAP_FILE_SET_CAPTURE_FILEW = #WM_CAP_UNICODE_START + 20
#WM_CAP_FILE_SET_INFOCHUNK = #WM_CAP_START + 24
#WM_CAP_GET_AUDIOFORMAT = #WM_CAP_START + 36
#WM_CAP_GET_CAPSTREAMPTR = #WM_CAP_START + 1
#WM_CAP_GET_MCI_DEVICEA = #WM_CAP_START + 67
#WM_CAP_GET_MCI_DEVICEW = #WM_CAP_UNICODE_START + 67
#WM_CAP_GET_SEQUENCE_SETUP = #WM_CAP_START + 65
#WM_CAP_GET_STATUS = #WM_CAP_START + 54
#WM_CAP_GET_USER_DATA = #WM_CAP_START + 8
#WM_CAP_GET_VIDEOFORMAT = #WM_CAP_START + 44
#WM_CAP_GRAB_FRAME = #WM_CAP_START + 60
#WM_CAP_GRAB_FRAME_NOSTOP = #WM_CAP_START + 61
#WM_CAP_PAL_AUTOCREATE = #WM_CAP_START + 83
#WM_CAP_PAL_MANUALCREATE = #WM_CAP_START + 84
#WM_CAP_PAL_OPENA = #WM_CAP_START + 80
#WM_CAP_PAL_OPENW = #WM_CAP_UNICODE_START + 80
#WM_CAP_PAL_PASTE = #WM_CAP_START + 82
#WM_CAP_SEQUENCE = #WM_CAP_START + 62
#WM_CAP_SEQUENCE_NOFILE = #WM_CAP_START + 63
#WM_CAP_SET_AUDIOFORMAT = #WM_CAP_START + 35
#WM_CAP_SET_CALLBACK_CAPCONTROL = #WM_CAP_START + 85
#WM_CAP_SET_CALLBACK_ERRORA = #WM_CAP_START + 2
#WM_CAP_SET_CALLBACK_ERRORW = #WM_CAP_UNICODE_START + 2
#WM_CAP_SET_CALLBACK_FRAME = #WM_CAP_START + 5
#WM_CAP_SET_CALLBACK_STATUSA = #WM_CAP_START + 3
#WM_CAP_SET_CALLBACK_STATUSW = #WM_CAP_UNICODE_START + 3
#WM_CAP_SET_CALLBACK_VIDEOSTREAM = #WM_CAP_START + 6
#WM_CAP_SET_CALLBACK_WAVESTREAM = #WM_CAP_START + 7
#WM_CAP_SET_CALLBACK_YIELD = #WM_CAP_START + 4
#WM_CAP_SET_MCI_DEVICEA = #WM_CAP_START + 66
#WM_CAP_SET_MCI_DEVICEW = #WM_CAP_UNICODE_START + 66
#WM_CAP_SET_OVERLAY = #WM_CAP_START + 51
#WM_CAP_SET_PREVIEW = #WM_CAP_START + 50
#WM_CAP_SET_PREVIEWRATE = #WM_CAP_START + 52
#WM_CAP_SET_SCALE = #WM_CAP_START + 53
#WM_CAP_SET_SCROLL = #WM_CAP_START + 55
#WM_CAP_SET_SEQUENCE_SETUP = #WM_CAP_START + 64
#WM_CAP_SET_USER_DATA = #WM_CAP_START + 9
#WM_CAP_SET_VIDEOFORMAT = #WM_CAP_START + 45
#WM_CAP_SINGLE_FRAME = #WM_CAP_START + 72
#WM_CAP_SINGLE_FRAME_CLOSE = #WM_CAP_START + 71
#WM_CAP_SINGLE_FRAME_OPEN = #WM_CAP_START + 70
#WM_CAP_STOP = #WM_CAP_START + 68

InitSprite()
  
OpenWindow(0,0,0,800,600,"camera",#PB_Window_SystemMenu|#PB_Window_SizeGadget|#PB_Window_ScreenCentered)
OpenWindowedScreen(WindowID(0),10,10,500,500,0,0,0)

v_bild=CreateImage(#PB_Any,320,240)

OpenLibrary(0, "avicap32.dll")
*capAddress = GetFunction(0, "capCreateCaptureWindowA")
hWndC = CallFunctionFast(*capAddress, 0, #WS_CHILD | #WS_VISIBLE, 600, 10, 1,1, WindowID(0),1)
SendMessage_(hWndC, #WM_CAP_DRIVER_CONNECT, 0, 0)
SendMessage_(hWndC, #WM_CAP_SET_PREVIEW, #True, 0)
SendMessage_(hWndC, #WM_CAP_SET_PREVIEWRATE, 1, 0)
  
Repeat  
  Event.l = WaitWindowEvent(0) 
  
  SendMessage_(hWnDC, #WM_CAP_EDIT_COPY, 0 , 0)
  GetClipboardImage(v_bild) 
  
  StartDrawing(ImageOutput(v_bild))
    Circle(80,60,25,RGB(255,255,0))
  StopDrawing()
  StartDrawing(ScreenOutput())
    DrawImage(ImageID(v_bild), 20, 10,320,240)
  StopDrawing()
  
  FlipBuffers() 
Until Event = #PB_Event_CloseWindow

SendMessage_(hWndC, #WM_CAP_STOP, 0, 0)
SendMessage_(hWndC, #WM_CAP_DRIVER_DISCONNECT, 0, 0)
DestroyWindow_(hWndC)
CloseLibrary(0)


Re: Webcam-Bild im Image, mit Kreis gezeichnet

Verfasst: 01.06.2010 19:33
von Shadow-Gamer
Kann ich gebrauchen, danke fürs veröffentlichen :allright:

Re: Webcam-Bild im Image, mit Kreis gezeichnet

Verfasst: 02.06.2010 08:47
von dige
Ich würde da lieber direkt auf den FrameBuffer zugreifen
statt über den Umweg Zwischenablage...

Re: Webcam-Bild im Image, mit Kreis gezeichnet

Verfasst: 02.06.2010 11:29
von Jilocasin
Zuman man, während der Code (z.B. im Hintergrund) läuft, überhaupt kein Bild mehr "mal so eben" zwischenspeichern kann :shock:

Re: Webcam-Bild im Image, mit Kreis gezeichnet

Verfasst: 02.06.2010 13:36
von super_castle
Ich würde da lieber direkt auf den FrameBuffer zugreifen
statt über den Umweg Zwischenablage...
Also , das könnt ihr halten wie ein Dachdecker.
Es führen viele Wege nach Rom.... :D

Ändere das doch mal auf den Framebuffer um, mit zeichnen und Videobild gleichzeitig.
Das kann ich nicht.
überhaupt kein Bild mehr "mal so eben" zwischenspeichern kann
Wer damit spielt, wird nicht "mal so eben zwischenspeichern". 8)

Gruss

Re: Webcam-Bild im Image, mit Kreis gezeichnet

Verfasst: 03.06.2010 14:05
von Jilocasin
Habe mich mal hingesetzt und etwas mit den avicap32-Befehlen auseinander gesetzt :mrgreen:

Hoffe es gefällt dir:

Code: Alles auswählen

#WM_CAP_START = #WM_USER
#WM_CAP_UNICODE_START = #WM_USER +100
#WM_CAP_PAL_SAVEA = #WM_CAP_START + 81
#WM_CAP_PAL_SAVEW = #WM_CAP_UNICODE_START + 81
#WM_CAP_UNICODE_END = #WM_CAP_PAL_SAVEW
#WM_CAP_ABORT = #WM_CAP_START + 69
#WM_CAP_DLG_VIDEOCOMPRESSION = #WM_CAP_START + 46
#WM_CAP_DLG_VIDEODISPLAY = #WM_CAP_START + 43
#WM_CAP_DLG_VIDEOFORMAT = #WM_CAP_START + 41
#WM_CAP_DLG_VIDEOSOURCE = #WM_CAP_START + 42
#WM_CAP_DRIVER_CONNECT = #WM_CAP_START + 10
#WM_CAP_DRIVER_DISCONNECT = #WM_CAP_START + 11
#WM_CAP_DRIVER_GET_CAPS = #WM_CAP_START + 14
#WM_CAP_DRIVER_GET_NAMEA = #WM_CAP_START + 12
#WM_CAP_DRIVER_GET_NAMEW = #WM_CAP_UNICODE_START + 12
#WM_CAP_DRIVER_GET_VERSIONA = #WM_CAP_START + 13
#WM_CAP_DRIVER_GET_VERSIONW = #WM_CAP_UNICODE_START + 13
#WM_CAP_EDIT_COPY = #WM_CAP_START + 30
#WM_CAP_END = #WM_CAP_UNICODE_END
#WM_CAP_FILE_ALLOCATE = #WM_CAP_START + 22
#WM_CAP_FILE_GET_CAPTURE_FILEA = #WM_CAP_START + 21
#WM_CAP_FILE_GET_CAPTURE_FILEW = #WM_CAP_UNICODE_START + 21
#WM_CAP_FILE_SAVEASA = #WM_CAP_START + 23
#WM_CAP_FILE_SAVEASW = #WM_CAP_UNICODE_START + 23
#WM_CAP_FILE_SAVEDIBA = #WM_CAP_START + 25
#WM_CAP_FILE_SAVEDIBW = #WM_CAP_UNICODE_START + 25
#WM_CAP_FILE_SET_CAPTURE_FILEA = #WM_CAP_START + 20
#WM_CAP_FILE_SET_CAPTURE_FILEW = #WM_CAP_UNICODE_START + 20
#WM_CAP_FILE_SET_INFOCHUNK = #WM_CAP_START + 24
#WM_CAP_GET_AUDIOFORMAT = #WM_CAP_START + 36
#WM_CAP_GET_CAPSTREAMPTR = #WM_CAP_START + 1
#WM_CAP_GET_MCI_DEVICEA = #WM_CAP_START + 67
#WM_CAP_GET_MCI_DEVICEW = #WM_CAP_UNICODE_START + 67
#WM_CAP_GET_SEQUENCE_SETUP = #WM_CAP_START + 65
#WM_CAP_GET_STATUS = #WM_CAP_START + 54
#WM_CAP_GET_USER_DATA = #WM_CAP_START + 8
#WM_CAP_GET_VIDEOFORMAT = #WM_CAP_START + 44
#WM_CAP_GRAB_FRAME = #WM_CAP_START + 60
#WM_CAP_GRAB_FRAME_NOSTOP = #WM_CAP_START + 61
#WM_CAP_PAL_AUTOCREATE = #WM_CAP_START + 83
#WM_CAP_PAL_MANUALCREATE = #WM_CAP_START + 84
#WM_CAP_PAL_OPENA = #WM_CAP_START + 80
#WM_CAP_PAL_OPENW = #WM_CAP_UNICODE_START + 80
#WM_CAP_PAL_PASTE = #WM_CAP_START + 82
#WM_CAP_SEQUENCE = #WM_CAP_START + 62
#WM_CAP_SEQUENCE_NOFILE = #WM_CAP_START + 63
#WM_CAP_SET_AUDIOFORMAT = #WM_CAP_START + 35
#WM_CAP_SET_CALLBACK_CAPCONTROL = #WM_CAP_START + 85
#WM_CAP_SET_CALLBACK_ERRORA = #WM_CAP_START + 2
#WM_CAP_SET_CALLBACK_ERRORW = #WM_CAP_UNICODE_START + 2
#WM_CAP_SET_CALLBACK_FRAME = #WM_CAP_START + 5
#WM_CAP_SET_CALLBACK_STATUSA = #WM_CAP_START + 3
#WM_CAP_SET_CALLBACK_STATUSW = #WM_CAP_UNICODE_START + 3
#WM_CAP_SET_CALLBACK_VIDEOSTREAM = #WM_CAP_START + 6
#WM_CAP_SET_CALLBACK_WAVESTREAM = #WM_CAP_START + 7
#WM_CAP_SET_CALLBACK_YIELD = #WM_CAP_START + 4
#WM_CAP_SET_MCI_DEVICEA = #WM_CAP_START + 66
#WM_CAP_SET_MCI_DEVICEW = #WM_CAP_UNICODE_START + 66
#WM_CAP_SET_OVERLAY = #WM_CAP_START + 51
#WM_CAP_SET_PREVIEW = #WM_CAP_START + 50
#WM_CAP_SET_PREVIEWRATE = #WM_CAP_START + 52
#WM_CAP_SET_SCALE = #WM_CAP_START + 53
#WM_CAP_SET_SCROLL = #WM_CAP_START + 55
#WM_CAP_SET_SEQUENCE_SETUP = #WM_CAP_START + 64
#WM_CAP_SET_USER_DATA = #WM_CAP_START + 9
#WM_CAP_SET_VIDEOFORMAT = #WM_CAP_START + 45
#WM_CAP_SINGLE_FRAME = #WM_CAP_START + 72
#WM_CAP_SINGLE_FRAME_CLOSE = #WM_CAP_START + 71
#WM_CAP_SINGLE_FRAME_OPEN = #WM_CAP_START + 70
#WM_CAP_STOP = #WM_CAP_START + 68


#VHDR_DONE = 1
#VHDR_PREPARED = 2
#VHDR_INQUEUE = 4
#VHDR_KEYFRAME = 8


Enumeration
  #Gadget_1_Frame
  #Gadget_1_Text
  #Gadget_1_Size
  
  #Gadget_2_Frame
  #Gadget_2_Text
  #Gadget_2_Size
EndEnumeration


Structure VIDEOHDR
  *lpData
  dwBufferLength.l
  dwBytesUsed.l
  dwTimeCaptured.l
  dwUser.l
  dwFlags.l
  *dwReserved[4]
EndStructure


Global psVideoFormat.BITMAPINFO
Global MyImage



Procedure VideoStreamCallback(hWnd, *lpVHdr.VIDEOHDR)
  If *lpVHdr\dwFlags & #VHDR_KEYFRAME
    If IsImage(MyImage) = 0
      MyImage = CreateImage(#PB_Any,  psVideoFormat\bmiHeader\biWidth, psVideoFormat\bmiHeader\biHeight, 32)
    EndIf
    
    If IsImage(MyImage)
      SetGadgetText(#Gadget_2_Size, Str(ImageWidth(MyImage)) + " x " + Str(ImageHeight(MyImage)) + " (" + Str(ImageDepth(MyImage)) + " Bits/Pixel)")
      
      Protected hDC = StartDrawing(ImageOutput(MyImage))
      If hDC
        SetDIBits_(hDC, ImageID(MyImage), 0, psVideoFormat\bmiHeader\biHeight, *lpVHdr\lpData, psVideoFormat, #DIB_RGB_COLORS)
        ; Wir wurschteln hier die Daten des VideoStreamCallbacks in unser PB Image.
        ; Das klappt, weil wir sicher gestellt haben, dass beide aus 32 Bit RGB-Daten bestehen.
        
        Circle(psVideoFormat\bmiHeader\biWidth / 2, psVideoFormat\bmiHeader\biHeight / 2, 40, Random($FFFFFF))
        DrawText(10, 10, "Hallo Welt!", $FFFFFF, 0)
        
        StopDrawing()
      EndIf
    EndIf
    

  Else
    Debug "Bild ist kein Keyframe. Bin mir allerdings nicht sicher, ob es bei der Preview-Option immer zwangsläufig ein Keyframe sein muss"
  EndIf
EndProcedure


OpenWindow(0, 0, 0, 710, 320, "avicap32", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)

Frame3DGadget(#Gadget_1_Frame, 10, 10, 340, 290, "Skalierte Direktvorschau von avicap32")
  TextGadget(#Gadget_1_Text, 20, 30, 70, 20, "Original:")
  TextGadget(#Gadget_1_Size, 90, 30, 250, 20, "")
  
Frame3DGadget(#Gadget_2_Frame, 360, 10, 340, 290, "Bearbeitetes und zur Darstellung skaliertes PB-Image")
  TextGadget(#Gadget_2_Text, 370, 30, 70, 20, "Größe:")
  TextGadget(#Gadget_2_Size, 440, 30, 250, 20, "")

OpenLibrary(0, "avicap32.dll")
hWndC = CallFunction(0, "capCreateCaptureWindowA", 0, #WS_CHILD | #WS_VISIBLE, 20, 50, 320, 240, WindowID(0), 1)
  SendMessage_(hWndC, #WM_CAP_DRIVER_CONNECT, 0, 0)
  SendMessage_(hWndC, #WM_CAP_SET_PREVIEW, #True, 0)
  SendMessage_(hWndC, #WM_CAP_SET_PREVIEWRATE, 50, 0)
  SendMessage_(hWndC, #WM_CAP_SET_SCALE, 1, 0)
  SendMessage_(hWndC, #WM_CAP_SET_CALLBACK_FRAME, 0, @VideoStreamCallback())
  SendMessage_(hWndC, #WM_CAP_GET_VIDEOFORMAT, SizeOf(psVideoFormat), @psVideoFormat)
    SetGadgetText(#Gadget_1_Size, Str(psVideoFormat\bmiHeader\biWidth) + " x " + Str(psVideoFormat\bmiHeader\biHeight) + " (" + Str(psVideoFormat\bmiHeader\biBitCount) + " Bits/Pixel)")
  
  ; Wir ändern hier also mal hübsch das Format, in dem wir das Bild gerne hätten.
  ; Standardmäßig ist es oft bei Webcams nur in 16 Bit, dann müssten wir soviel herumrechnen und könnten es uns nicht mit SetDIBits einfach machen.
  ; Das gesetzte Videoformat wird auch nach Programmende beibehalten, d.h. beim nächsten Start wird die Vorschau von avicap32 bereits hier oben ein 32-Bit Bild liefern!
  
  psVideoFormat\bmiHeader\biBitCount = 24
  psVideoFormat\bmiHeader\biCompression = #BI_RGB
  psVideoFormat\bmiHeader\biSizeImage = 0
  psVideoFormat\bmiHeader\biClrUsed = 0
  psVideoFormat\bmiHeader\biClrImportant = 0
  If SendMessage_(hWndC, #WM_CAP_SET_VIDEOFORMAT, SizeOf(psVideoFormat), @psVideoFormat) = 0
    Debug "Konnte Videoformat nicht setzen!"
  Endif
  
  



Repeat
  Event.l = WaitWindowEvent(0)
  
  If IsImage(MyImage)
    StartDrawing(WindowOutput(0))
      DrawImage(ImageID(MyImage), 370, 50, 320, 240)
    StopDrawing()
  EndIf
  
Until Event = #PB_Event_CloseWindow

SendMessage_(hWndC, #WM_CAP_STOP, 0, 0)
SendMessage_(hWndC, #WM_CAP_DRIVER_DISCONNECT, 0, 0)
DestroyWindow_(hWndC)
CloseLibrary(0)
Getestet mit PB 4.5 Beta4 und Webcam.

Re: Webcam-Bild im Image, mit Kreis gezeichnet

Verfasst: 03.06.2010 19:56
von super_castle
hm...., ich sehe links das Webcam-Video-Bild und rechts nur den flackernden Kreis und "Hallo..." und wo ist das Videobild dort drin ? :o

Purebasic 4.5 RC 2

gruss

Re: Webcam-Bild im Image, mit Kreis gezeichnet

Verfasst: 03.06.2010 20:41
von Jilocasin
Huch.. das wundert mich. Also der VideoCallback wird ja wohl aufgerufen, sonst hättest du keinen Kreis/Text. Kannst du eventuell mal rpüfen, ob das SetDIBits_(), sowie das SendMessage_() mit #WM_CAP_SET_VIDEOFORMAT einen Wert <> 0 zurückgibt?

Re: Webcam-Bild im Image, mit Kreis gezeichnet

Verfasst: 03.06.2010 21:47
von coder
Ein einfügen von

Code: Alles auswählen

SendMessage_(hWndC, #WM_CAP_GET_VIDEOFORMAT, SizeOf(psVideoFormat), @psVideoFormat)
SetGadgetText(#Gadget_1_Size, Str(psVideoFormat\bmiHeader\biWidth) + " x " + Str(psVideoFormat\bmiHeader\biHeight) + " (" + Str(psVideoFormat\bmiHeader\biBitCount) + " Bits/Pixel)")
nach

Code: Alles auswählen

SendMessage_(hWndC, #WM_CAP_SET_VIDEOFORMAT, SizeOf(psVideoFormat), @psVideoFormat)
scheint das Problem zu lösen (zu mindestens bei mir) und fragt mich nicht wieso... :|

Re: Webcam-Bild im Image, mit Kreis gezeichnet

Verfasst: 03.06.2010 21:51
von Jilocasin
Wenn du nach dem SET nochmal das GET aufrufst aktualisiert sich ja wieder der BITMAPINFOHEADER.. scheinbar kann dann das SET nicht richtig ausgeführt werden. :?