Utiliser une webcam et traiter l'image (API)

Partagez votre expérience de PureBasic avec les autres utilisateurs.
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Message par Thyphoon »

Voilà en modifiant cette ligne ça marche aussi bien avec les multiples 1, 2, 4 ! Mais bon pour être sur de ma logique faudra que Oliv m'explique !
En tout cas je constate que la detection est similaire en 1, 2, 4 pour un bloc de cette taille ! donc on gagne de la vitesse et la detection est identique ...

Code : Tout sélectionner

 If dif > ((Largeur*Hauteur)/Mult*8/25) : Debug "Detection" : EndIf ; et celui ci pour modifier la détection 
vous pouvez testé en changeant la dernière valeur de la fonction detection ! dans ces lignes :

Code : Tout sélectionner

    Detection(0,0,50,50,1,#Mult) 
  Else 
    Detection(0,0,50,50,0,#Mult) 
  EndIf 
et amélioration de la routine mirroir

Code : Tout sélectionner

hdc.l = GetDC_(0) 
ReleaseDC_(0, hdc) 
;0 flip horizontal
;1 flip vertical
;2 flip horizontal et vertical
Procedure MirrorImage(image.l, Direction.l) 
UseImage(image)
  hdc = StartDrawing(ImageOutput()) 
    Height = ImageHeight() 
    Width = ImageWidth() 
    If Direction=0 Or  Direction=2
      StretchBlt_(hdc, 0, Height-1, Width, -Height, hdc, 0, 0, Width, Height, #SRCCOPY) 
    EndIf
    If Direction=1 Or  Direction=2
      StretchBlt_(hdc, Width-1, 0, -Width, Height, hdc, 0, 0, Width, Height, #SRCCOPY) 
    EndIf 
  StopDrawing() 
EndProcedure 
Oliv
Messages : 2117
Inscription : mer. 21/janv./2004 18:39

Message par Oliv »

Thyphoon a écrit :

Code : Tout sélectionner

hdc.l = GetDC_(0) 
ReleaseDC_(0, hdc) 
;0 flip horizontal
;1 flip vertical
;2 flip horizontal et vertical
Procedure MirrorImage(image.l, Direction.l) 
UseImage(image)
  hdc = StartDrawing(ImageOutput()) 
    Height = ImageHeight() 
    Width = ImageWidth() 
    If Direction=0 Or  Direction=2
      StretchBlt_(hdc, 0, Height-1, Width, -Height, hdc, 0, 0, Width, Height, #SRCCOPY) 
    EndIf
    If Direction=1 Or  Direction=2
      StretchBlt_(hdc, Width-1, 0, -Width, Height, hdc, 0, 0, Width, Height, #SRCCOPY) 
    EndIf 
  StopDrawing() 
EndProcedure 
Le UseImage(image) n'est pas utile ici car Image est un identifiant windows et non PureBasic.

Pour la procédure détection() ton while reviens à la même chose que mon for next si ce n'est que l'on comprend moins bien, en tout cas, c'est encore Le Soldat Inconnu qui a raison, on a oublié + X et +Y

Sinon quand tu augmentes la zone de détection, c'est normal de devoir augmenter le nombre de pixels à atteindre pour détecter car tu en as beaucoup plus, donc il te faut une marge d'erreur plus grande. Je vais réorganiser tout ça demain, et je vais surement aussi récupérer les images avec un(e) (comment on dit ?) CallBack ce qui gagnera en ressources.

Sinon bravo pour le mirroir :D
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Message par Thyphoon »

merci pour le mirroire !! :o) mais j'avoue que ce n'est pas de mois !!! on m'a beaucoup aider

oui je comprends ! je pense que pour la detection ça serait bien de passer un %de la zone qui a changer active la detection
est ce que tu vois ce que je veux dire ?
car là si je me trompe pas ta variable dif s'incrémente de+1 des qu'une pixel a changé ! donc en vérité si dif> 80%des pixels de la zone alors detection !! :o) au lieu du valeur fixe qui est valable que pour cette zone là !
:P
Oui je suis d'accord le while n'est pas tres claire ...il a juste l'interet de pouvoir faire l'equivalent d'un "step" variable
Oliv
Messages : 2117
Inscription : mer. 21/janv./2004 18:39

Message par Oliv »

Voilà, j'ai repris ton code, modifié 2-3 choses et ajouté un "detection par pourcentages"(pas vraiment des pourcents mais bon, pas grave), ça marche plutôt bien :D .
@Typhoon : Pour les sprites 3D je ne trouve pas ça très utile car après pour calculer la détection quand tu le réduit de 29 pixels :? donc ta première méthode va plus vite pour le mirroir. Sinon pour "Mult", très bonne idée, mauvaise application lol, tu l'avais mis un peu trop souvent, et pas tjrs au bonne endroit, dès que j'ai le temps je te promet je le remet :D :D

Code : Tout sélectionner

; Utilise la librairie effect du Soldat Inconnu pour gagnger du temps 


;- Declarations 
; Constantes 
Enumeration 
  #Principale 
  #AviCap32 
EndEnumeration 

; Structures 

; Listes 

; Buffer 

; Tableaux 
Dim Image(320 - 1,240 - 1) : Dim TDetection(320 - 1,240 - 1) 

; Variables 
Sortie.b : hWndPreview.l 

Global hWndPreview,Sortie,a.l,Test.l 



;  *****************************               Procedures               *********************** 

;Exeption pour les contstantes cap, je les mettrai en Enumeration plus tard 
#WM_CAP_START = #WM_USER 

#WM_CAP_GET_CAPSTREAMPTR = #WM_CAP_START + 1 

#WM_CAP_SET_CALLBACK_ERROR = #WM_CAP_START + 2 
#WM_CAP_SET_CALLBACK_STATUS = #WM_CAP_START + 3 
#WM_CAP_SET_CALLBACK_YIELD = #WM_CAP_START + 4 
#WM_CAP_SET_CALLBACK_FRAME = #WM_CAP_START + 5 
#WM_CAP_SET_CALLBACK_VIDEOSTREAM = #WM_CAP_START + 6 
#WM_CAP_SET_CALLBACK_WAVESTREAM = #WM_CAP_START + 7 
#WM_CAP_GET_USER_DATA = #WM_CAP_START + 8 
#WM_CAP_SET_USER_DATA = #WM_CAP_START + 9 
    
#WM_CAP_DRIVER_CONNECT = #WM_CAP_START + 10 
#WM_CAP_DRIVER_DISCONNECT = #WM_CAP_START + 11 
#WM_CAP_DRIVER_GET_NAME = #WM_CAP_START + 12 
#WM_CAP_DRIVER_GET_VERSION = #WM_CAP_START + 13 
#WM_CAP_DRIVER_GET_CAPS = #WM_CAP_START + 14 

#WM_CAP_FILE_SET_CAPTURE_FILE = #WM_CAP_START + 20 
#WM_CAP_FILE_GET_CAPTURE_FILE = #WM_CAP_START + 21 
#WM_CAP_FILE_ALLOCATE = #WM_CAP_START + 22 
#WM_CAP_FILE_SAVEAS = #WM_CAP_START + 23 
#WM_CAP_FILE_SET_INFOCHUNK = #WM_CAP_START + 24 
#WM_CAP_FILE_SAVEDIB = #WM_CAP_START + 25 

#WM_CAP_EDIT_COPY = #WM_CAP_START + 30 

#WM_CAP_SET_AUDIOFORMAT = #WM_CAP_START + 35 
#WM_CAP_GET_AUDIOFORMAT = #WM_CAP_START + 36 

#WM_CAP_DLG_VIDEOFORMAT = #WM_CAP_START + 41 
#WM_CAP_DLG_VIDEOSOURCE = #WM_CAP_START + 42 
#WM_CAP_DLG_VIDEODISPLAY = #WM_CAP_START + 43 
#WM_CAP_GET_VIDEOFORMAT = #WM_CAP_START + 44 
#WM_CAP_SET_VIDEOFORMAT = #WM_CAP_START + 45 
#WM_CAP_DLG_VIDEOCOMPRESSION = #WM_CAP_START + 46 

#WM_CAP_SET_PREVIEW = #WM_CAP_START + 50 
#WM_CAP_SET_OVERLAY = #WM_CAP_START + 51 
#WM_CAP_SET_PREVIEWRATE = #WM_CAP_START + 52 
#WM_CAP_SET_SCALE = #WM_CAP_START + 53 
#WM_CAP_GET_STATUS = #WM_CAP_START + 54 
#WM_CAP_SET_SCROLL = #WM_CAP_START + 55 

#WM_CAP_GRAB_FRAME = #WM_CAP_START + 60 
#WM_CAP_GRAB_FRAME_NOSTOP = #WM_CAP_START + 61 

#WM_CAP_SEQUENCE = #WM_CAP_START + 62 
#WM_CAP_SEQUENCE_NOFILE = #WM_CAP_START + 63 
#WM_CAP_SET_SEQUENCE_SETUP = #WM_CAP_START + 64 
#WM_CAP_GET_SEQUENCE_SETUP = #WM_CAP_START + 65 
#WM_CAP_SET_MCI_DEVICE = #WM_CAP_START + 66 
#WM_CAP_GET_MCI_DEVICE = #WM_CAP_START + 67 
#WM_CAP_STOP = #WM_CAP_START + 68 
#WM_CAP_ABORT = #WM_CAP_START + 69 

#WM_CAP_SINGLE_FRAME_OPEN = #WM_CAP_START + 70 
#WM_CAP_SINGLE_FRAME_CLOSE = #WM_CAP_START + 71 
#WM_CAP_SINGLE_FRAME = #WM_CAP_START + 72 

#WM_CAP_PAL_OPEN = #WM_CAP_START + 80 
#WM_CAP_PAL_SAVE = #WM_CAP_START + 81 
#WM_CAP_PAL_PASTE = #WM_CAP_START + 82 
#WM_CAP_PAL_AUTOCREATE = #WM_CAP_START + 83 
#WM_CAP_PAL_MANUALCREATE = #WM_CAP_START + 84 

;// Following added post VFW 1.1 
#WM_CAP_SET_CALLBACK_CAPCONTROL = #WM_CAP_START + 85 

;// Defines end of the message range 
#WM_CAP_END = #WM_CAP_SET_CALLBACK_CAPCONTROL 




Procedure Cap_Stop() 
  ProcedureReturn SendMessage_(hWndPreview,#WM_CAP_STOP,0,0) 
EndProcedure 


Procedure CAP_DRIVER_DISCONNECT() 
  ProcedureReturn SendMessage_(hWndPreview,#WM_CAP_DRIVER_DISCONNECT,0,0) 
EndProcedure 

Procedure capCreateCaptureWindowA(lpszWindowName.s,dwStyle.l,x.l,y.l,Width.l,Height.l,hWndParent.l,nId.l) 
    ProcedureReturn CallFunction(#AviCap32,"capCreateCaptureWindowA", lpszWindowName, dwStyle, x, y,Width,Height,hWndParent,nId) 
EndProcedure 


Procedure capDriverConnect(i.b) 
   ProcedureReturn SendMessage_(hWndPreview,#WM_CAP_DRIVER_CONNECT,i,0) 
EndProcedure 


Procedure capPreviewRate(Rate.b) 
   ProcedureReturn SendMessage_(hWndPreview,#WM_CAP_SET_PREVIEWRATE,Rate,0) 
EndProcedure 


Procedure capPreview(Flag.b) 
   ProcedureReturn SendMessage_(hWndPreview,#WM_CAP_SET_PREVIEW,Flag,0) 
EndProcedure 


Procedure capCaptureStop() 
   ProcedureReturn SendMessage_(hWndPreview,#WM_CAP_STOP,0,0) 
EndProcedure 


Procedure capDriverDisconnect() 
   ProcedureReturn SendMessage_(hWndPreview,#WM_CAP_DRIVER_DISCONNECT,0,0) 
EndProcedure 


Procedure capGrabFrameNoStop() 
   ProcedureReturn SendMessage_(hWndPreview,#WM_CAP_GRAB_FRAME_NOSTOP,0,0) 
EndProcedure 


Procedure capEditCopy() 
   ProcedureReturn SendMessage_(hWndPreview,#WM_CAP_EDIT_COPY,0,0) 
EndProcedure 


Procedure MirrorImage(image.l, Direction.l) 
  hdc = StartDrawing(ImageOutput()) 
    Height = ImageHeight() 
    Width = ImageWidth() 
    If Direction 
      StretchBlt_(hdc, 0, Height-1, Width, -Height, hdc, 0, 0, Width, Height, #SRCCOPY) 
    Else 
      StretchBlt_(hdc, Width-1, 0, -Width, Height, hdc, 0, 0, Width, Height, #SRCCOPY) 
    EndIf 
  StopDrawing() 
EndProcedure 

Procedure Affichage() 
  StartDrawing(ScreenOutput()) 
    DrawImage(1,0,0) 
    LineXY(50,50,50,150,$FFFFFF) 
    LineXY(50,150,150,150,$FFFFFF) 
    LineXY(150,150,150,50,$FFFFFF) 
    LineXY(150,50,50,50,$FFFFFF) 
  StopDrawing() 
  FlipBuffers() 
  ClearScreen(170,170,170) 
EndProcedure 


Procedure Clavier() 
  ExamineKeyboard() 
  If KeyboardPushed(#PB_Key_Escape) : Sortie = 1 : EndIf 
EndProcedure 


; Action à 0 reprends une nouvelle image et à 1 compare 
Procedure Detection(X.l,Y.l,Largeur.l,Hauteur.l,Action.b,Detection) 
  If Action = 1 
    n = X 
    While n < Largeur + X
      n + 1 
      nn = Y 
      While nn < Hauteur + Y
      nn + 1 
        TDetection(n,nn) = ColorGrey(Image(n,nn)) 
      Wend 
    Wend 
  Else
    Zone.l = (Largeur * Hauteur)
    n = X 
    While n < Largeur + X 
      n + 1
      nn = Y 
      While nn < Hauteur +Y
      nn + 1  
        If Abs(Red(TDetection(n,nn)) - Red(ColorGrey(Image(n,nn)))) < 30 ; Ici c'est surtout pour compenser le bruit 
          id + 1 
        Else 
          dif + 1 ; Typhoon : Si on enlève pas  "* mult" on va se retrouver avec une détection fausée 
        EndIf 
      Wend 
    Wend  
   ; Debug dif 
  EndIf
  
  If dif > 0
    If (Zone/dif) >= Detection : Debug "Detection" : EndIf 
  EndIf
EndProcedure 


Procedure Webcam() 
  Shared Test 
  capGrabFrameNoStop() 
  capEditCopy() 
  ImageID.l = GetClipboardData(#PB_ClipboardImage) 
  ; ImageID = ImageSymmetryV(ImageID) 
  

  StartDrawing(ImageOutput()) 
    DrawImage(ImageID,0,0) 
  StopDrawing()    
  MirrorImage(0, 0) 
 
  GetImageBits(UseImage(0),@Image()) 
  
  StartDrawing(ScreenOutput()) 
    DrawImage(UseImage(0),0,0) 
  StopDrawing() 
  If Test = 0 
    Test = 1 
    Detection(50,50,50,50,1,0) 
  Else 
    Detection(50,50,50,50,0,10) ; Détecte si 10% des pixels changent
  EndIf 
EndProcedure 








; Initialisations 
If InitSprite() = 0 Or InitKeyboard() = 0 
  MessageRequester("Erreur","Le DirectX ne peux pas être initialisé.",#MB_ICONError) 
EndIf 


; Ouverture de la DLL 
If OpenLibrary(#AviCap32,"avicap32.dll") = 0 
  MessageRequester("Erreur","La DLL avicap32.dll ne peut pas être ouverte.",#MB_ICONError) 
EndIf 


; Création de la fenêtre pour la preview 
OpenWindow(#Principale,0,0,340,260,#PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_TitleBar | #PB_Window_ScreenCentered,"WebCam - Preview") 
;  | #WS_VISIBLE 

; Creation de la fenêtre de preview 
hWndPreview = capCreateCaptureWindowA("Preview",#WS_CHILD,0,0,320,240,WindowID(#Principale),0); Le denier paramètre celon le MSDN est "Window identifier", je ne vois pas à quoi il sert. 
; On "se connecte" au driver 
capDriverConnect(0) 
; On active la preview 
capPreview(#True) 
; On met le le nombre de rafarichissemnt/seconde de la preview, mettre 15 si vous avez une caméra 15 images seconde max. 
capPreviewRate(0) 
  
; Ouverture de l'écran 
OpenWindowedScreen(WindowID(#Principale),10,10,320,240,0,0,0) 

CreateImage(0,320,240) ; On créer l'image pour faire la symetrie 

Delay(5000) ; attend que la caméra fasse le réglage des couleurs 
Repeat 
  ClearScreen(150,150,150) 
  Select WindowEvent() 
    Case #PB_Event_CloseWindow 
      Sortie = 1 
  EndSelect 
  
  
  ; Gère le clavier 
  Clavier() 
  
  ; Gère la WebCam 
  WebCam() 
  
  ; Gère l'affichage 
  Affichage() 
  
  Delay(5) 
Until Sortie = 1 

; On arrête la fenêtre de capture 
capCaptureStop() 
; On libère la caméra : très important pour la réutiliser après et fermer l'EXE rapidement 
capDriverDisconnect() 
; On ferme les fenêtres 
DestroyWindow_(hWndPreview) 
CloseWindow(#Principale) 
; On freme la DLL 
CloseLibrary(#AviCap32) 


End
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Message par Thyphoon »

génial ! :o)
demain matin j'essaye ton code :oP
Répondre