Estrarre e salvare singole immagini da una ripresa video mediante WebCam effettuata con il Componente gb.media: differenze tra le versioni

Da Gambas-it.org - Wikipedia.
Vai alla navigazione Vai alla ricerca
Nessun oggetto della modifica
Nessun oggetto della modifica
 
(17 versioni intermedie di uno stesso utente non sono mostrate)
Riga 1: Riga 1:
A volte può essere necessario estrarre e salvare in appositi file singole immagini di una ripresa video effettuata mediante una WebCam con il Componente ''gb.media''. <SUP>&#091;[[#Note|Nota 1]]&#093;</sup>
A volte può essere necessario estrarre e salvare in appositi file singole immagini di una ripresa video effettuata mediante una WebCam con il Componente ''gb.media''.
<BR>Per fare ciò, sono disponibili alcune modalità.
<BR>Per fare ciò, sono disponibili alcune modalità.


E' il caso di sottolineare che <SPAN Style="text-decoration:underline">bisognerà creare progetti ''QT Application''</span>, altrimenti usando i Componenti GTK detti codici non funzioneranno a dovere.
E' il caso di sottolineare che con riferimento ai progetti in ambiente grafico è preferibile utilizzare le risorse di '''QT''', altrimenti usando i Componenti GTK detti codici potrebbero non funzionare a dovere.




===Usare la Classe "''MediaPlayer''" con una ''PictureBox''===
==Usare la Classe ''MediaPlayer''==
Innanzitutto è possibile usare la Classi "''MediaPlayer''". In particolare, per catturare le singole immagini, si utilizzerà in tal caso la sotto-proprietà "''.Image''" della proprietà "''Video''" della Classe "''MediaPlayer''".
Vediamo come sia possibile usare la Classe ''MediaPlayer'' del Componente gb.media per catturare le singole immagini.
===Usare soltanto la Classe ''MediaPlayer'' con una ''PictureBox''===
In questo caso ci si servirà della sotto-Proprietà ".Image" della Proprietà "Video" della Classe ''MediaPlayer''.


Mostriamo un esempio in ambiente grafico, nel quale si utilizzerà una ''PictureBox'' per mostrare il video:
Mostriamo un esempio in ambiente grafico, nel quale si utilizzerà una ''PictureBox'' per mostrare il video e un'altra per mostrare l'immagine catturata:
Private PictureBox1 As PictureBox
Private PictureBox2 As PictureBox
Private button1 As Button
  Private mp As MediaPlayer
  Private mp As MediaPlayer
   
   
   
   
  '''Public''' Sub Form_Open()
  Public Sub Form_Open()
    
    
  Me.Resize(Screen.AvailableWidth * 0.7, Screen.AvailableHeight * 0.7)
  With PictureBox1 = New PictureBox(Me)
    .X = 0
    .Y = 0
    .W = Me.W * 0.4
    .H = Me.W * 0.4
  End With
  With PictureBox2 = New PictureBox(Me)
    .X = PictureBox1.X + PictureBox1.W + (Me.W * 0.03)
    .Y = 0
    .W = Me.W * 0.4
    .H = Me.W * 0.4
    .Background = Color.SoftYellow
  End With
  With Button1 = New Button(Me) As "Button1"
    .X = PictureBox1.X + (Me.W * 0.03)
    .Y = PictureBox1.X + PictureBox1.H + (Me.W * 0.03)
    .W = Me.W * 0.1
    .H = Me.W * 0.07
  End With
   With mp = new MediaPlayer
   With mp = new MediaPlayer
     .URL = "v4l2:///dev/video0"
     .URL = "v4l2:///dev/video0"
     .SetWindow(PictureBox1)    ' <SUP>&#091;[[#Note|Nota 2]]&#093;</sup>
<FONT Color=gray>' ''...ma anche ad esempio così:''
'  .'''"v4l2:///dev/v4l/by-id/'''usb-Generic_Integrated_Camera_0001-video-index0'''"'''</font>
     .SetWindow(PictureBox1)    ' <SUP>&#091;[[#Note|nota 1]]&#093;</sup>
     .Play()
     .Play()
   End With
   End With
    
  '''End'''
   Mkdir "/tmp/immagini_WebCam"
  End
    
    
   
   
  '''Public''' Sub Button1_Click() <FONT Color=gray>' ''Cliccando sul tasto, si catturerà un'immagine dal video''</font>
  Public Sub Button1_Click() <FONT Color=gray>' ''Cliccando sul tasto, si catturerà un'immagine dal video''</font>
    
    
   Dim im As Image
   Dim im As Image
 
   im = mp.Video.Image
<FONT Color=gray>' ''Cattura un fotogramma dalla webcam e lo salva come immagine di formato PNG:''</font>
 
   With im = mp.Video.Image
  im.Save("/tmp" &/ Format(Now, "dd:mm:yyyy_hh:nn:ss.uu") & ".png")
    .Save("/tmp/immagini_WebCam" &/ Format(Now, "dd:mm:yyyy_hh:nn:ss.uu") & ".png")
    
   End With
   PictureBox1.Image = im
   With Me
    .Center
    .Resize(PictureBox1.X + PictureBox1.W + im.W, im.H)
  End With
With PictureBox2
  .Resize(im.W, im.H)
<FONT Color=gray>' ''Ingrandisce l'immagine mostrata nella "PictureBix" adattandola alle dimensione dell'immagine catturata dalla webcam:''</font>
  .Image = im.Stretch(mp.Video.Image.W, mp.Video.Image.H)
End With
    
    
  '''End'''
  End


 
===Usare le Classi ''MediaPlayer'', ''MediaControl'' con una ''DrawingArea''===
===Usare le Classi "''MediaPlayer''", "''MediaControl''" con una ''DrawingArea''===
E' possibile usare le Classi ''MediaPlayer'' e ''MediaControl''.
E' possibile usare le Classi "''MediaPlayer''" e "''MediaControl''".


Mostriamo di seguito un semplice esempio, nel quale la ripresa sarà mostrata all'interno di una ''DrawingArea'', e sarà salvata ogni secondo - grazie all'uso dell'Oggetto ''Timer'' - un'immagine della ripresa all'interno di un file immagine di formato PNG.
Mostriamo di seguito un semplice esempio, nel quale la ripresa sarà mostrata all'interno di una ''DrawingArea'', e sarà salvata ogni secondo - grazie all'uso dell'Oggetto ''Timer'' - un'immagine della ripresa all'interno di un file immagine di formato PNG.
  Private pl As MediaPlayer
  Private mp As MediaPlayer
  Private im As MediaControl
  Private im As MediaControl
Private drar As DrawingArea
  Private tb As ToggleButton
  Private tb As ToggleButton
  Private tempus As Timer
  Private tempus As Timer
Riga 47: Riga 86:
   
   
   
   
  '''Public''' Sub Form_Open()
  Public Sub Form_Open()
 
  Dim drar As DrawingArea
   Dim flt As MediaFilter
   Dim flt As MediaFilter
   
  With Me
    .W = 700
    .H = 600
  End With
  With drar = New DrawingArea(Me)
    .X = 10
    .Y = 10
    .W = 680
    .H = 480
    .Border = Border.Plain
    .Background = Color.Transparent
  End With
  With tb = New ToggleButton(Me) As "Tasto"
    .X = 500
    .Y = 550
    .W = 80
    .H = 40
    .Text = "Avvia"
  End With
 
  pl = New MediaPlayer As "MediaPlayer"
  flt = New MediaFilter(pl, "video/x-raw,width=640,height=480,framerate=30/1")
  im = New MediaControl(pl, "xvimagesink")
 
  pl.Video.Output = im
  pl.URL = "v4l2:///dev/video0"
 
  im.SetWindow(drar)
 
'''End'''
   
   
  With Me
    .W = Screen.AvailableWidth * 0.75
    .H = Screen.AvailableHeight * 0.75
  End With
  With drar = New DrawingArea(Me)
    .X = Me.W * 0.05
    .Y = Me.H * 0.05
    .W = Me.W * 0.9
    .H = Me.H * 0.8
    .Border = Border.Plain
  End With
  With tb = New ToggleButton(Me) As "Tasto"
    .W = Me.W * 0.1
    .H = Me.H * 0.05
    .X = (Me.W / 2) - (.W / 2)
    .Y = 0
    .Text = "Avvia"
  End With
  If Not Exist("/tmp/immagini") Then Mkdir "/tmp/immagini"
  mp = New MediaPlayer As "MediaPlayer"
  flt = New MediaFilter(mp, "video/x-raw,width=640,height=480,framerate=30/1")
  im = New MediaControl(mp, "xvimagesink")
End
Public Sub Tasto_Click()
  mp.Video.Output = im
  mp.URL = "v4l2:///dev/video0"
<FONT Color=gray>' ''...ma anche ad esempio così:''
'    = '''"v4l2:///dev/v4l/by-id/'''usb-Generic_Integrated_Camera_0001-video-index0'''"'''</font>
   
   
'''Public''' Sub Tasto_Click()
  im.SetWindow(drar)
    
    
   If tb.Value Then
   If tb.Value Then
     pl.Play
     mp.Play
     With tempus = New Timer As "Tempus"
     With tempus = New Timer As "Tempus"
       .Delay = 1000
       .Delay = 1000
       .Start()
       .Start()
     End With
     End With
    tb.Text = "Stop"
   Else
   Else
     pl.Stop
     mp.Stop
     pl.Close
     mp.Close
     tempus.Stop
     tempus.Stop
    tb.Text = "Avvia"
   Endif
   Endif
    
    
  '''End'''
  End
   
   
   
   
  '''Public''' Sub Tempus_Timer()
  Public Sub Tempus_Timer()
 
   Dim img As Image
   Dim img As Image
   Dim s As String
  img = mp.Video.Image
  Inc i
  img.Save("/tmp/immagini/foto_" & CStr(i) & ".png", 100)
  Me.Title = "Immagini catturate: " & CStr(i)
End
 
 
==Uso della Classe ''MediaPipeline''==
Si potrà fare anche uso della Classe ''MediaPipeline'' per catturare singole immagini dalla ripresa video.
 
===Semplice uso delle Classi ''MediaPipeline'' e ''MediaControl''===
====Catturare un solo fotogramma====
Mostriamo un esempio, nel quale si catturerà un singolo fotogramma e si creerà un file immagine di formato JPG:
Public Sub Button1_Click()
  Dim pl As MediaPipeline
   Dim src, enc, snk As MediaControl
  pl = New MediaPipeline
  src = New MediaControl(pl, "v4l2src")
<FONT Color=gray>' ''Cattura un fotogramma dalla webcam e lo salva come immagine jpeg:''</font>
  src["num-buffers"] = 1
  enc = New MediaControl(pl, "jpegenc")
  snk = New MediaControl(pl, "filesink")
  snk["location"] = "/tmp/immagine.jpg"
<FONT Color=gray>' ''Collega fra loro i plugin di "GStreamer":''</font>
  src.LinkTo(enc)
  enc.LinkTo(snk)
<FONT Color=gray>' ''Effettua la ripresa dell'immagine:''</font>
  pl.Play()
    
    
  img = pl.Video.Image
<FONT Color=gray>' ''Con alcune webcam può essere necessario porre una breve pausa per consentire la ripresa dell'immagine:''</font>
  Inc i
  Wait 1
  s = CStr(i)
  img.Save("/tmp/foto_" & s & ".png", 100)
  pl.Stop()
 
  pl.Close()
  Write #File.out, "\rImmagini catturate: " & s
  Print "Cattura immagine effettuata"
 
  '''End'''
  End


====Catturare più fotogrammi====
Mostriamo un esempio, questa volta a ''riga di comando'', nel quale si cattureranno più fotogrammi della ripresa video mediante il plugin "multifilesink" di GStreamer:
Private bo As Boolean
Public Sub Main()
  Dim pl As MediaPipeline
  Dim src, dcb, vcn, enc, snk As MediaControl
  Dim tm As Date
  Dim i As Integer
  If Not Exist("/tmp/IMMAGINI") Then Mkdir "/tmp/IMMAGINI"
  pl = New MediaPipeline
  src = New MediaControl(pl, "v4l2src")
  dcb = New MediaControl(pl, "decodebin")
  vcn = New MediaControl(pl, "videoconvert")
  enc = New MediaControl(pl, "pngenc")
  snk = New MediaControl(pl, "multifilesink")
<FONT Color=gray>' ''Per i nomi dei singoli file PNG si imposta un numero progressivo formato da 5 cifre decimali:''</font>
  snk["location"] = "/tmp/IMMAGINI/frame%05d.png"
<FONT Color=gray>' ''Collega fra loro i plugin di "GStreamer":''</font>
  src.LinkTo(dcb)
  dcb.LinkLaterTo(vcn)
  vcn.LinkTo(enc)
  enc.LinkTo(snk)
<FONT Color=gray>' ''Effettua la ripresa delle immagini:''</font>
  pl.Play()
  tm = Now
  While Not bo
    i = DateDiff(tm, Now, gb.Millisecond)
<FONT Color=gray>' ''Il tempo trascorso dall'inizio della ripresa video viene mostrato in console/Terminale:''</font>
    Write "\rTempo: " & Str(Time(0, 0, 0, i))
    Flush
    Wait 0.01
  Wend
  pl.Stop()
  pl.Close()
  Print "\nCattura immagini effettuata"
<FONT Color=gray>' ''Essendo stato utilizzato l'Evento "Application_Read()", è necessario usare l'istruzione "Quit" per terminare il programma e così per poter creare i singoli file immagine:''</font>
  Quit
End
Public Sub Application_Read() ' Premendo il tasto "Invio" della tastiera si arresta la ripresa video e si chiude il programma
  bo = True
End


===Usare il Metodo ".GetLastImage()" della Classe ''MediaControl'' per catturare singole immagini dalla ripresa video, e utilizzare una ''DrawingArea'' per mostrarle===
===Usare il metodo "''.GetLastImage( )''" della Classe "''MediaControl''" per catturare singole immagini dal video, e utilizzare una ''DrawingArea'' per mostrare la ripresa video===
Quest'altra modalità prevede che:
Quest'altra modalità prevede che:
* sia utilizzata una ''DrawingArea'', come superficie ove mostrare la ripresa video;
* sia utilizzata una ''DrawingArea'', come superficie ove mostrare la ripresa video;
* sia utilizzato il metodo "''.GetLastImage( )''" della Classe "''MediaControl''" per catturare singole immagini dal video.
* sia utilizzato il Metodo ".GetLastImage()" della Classe ''MediaControl'' per catturare singole immagini dal video.


Mostriamo di seguito un esempio pratico, nel quale la cattura delle immagini dalla ripresa video avviene ogni 500 millisecondi:
Mostriamo di seguito un esempio pratico, nel quale la cattura delle immagini dalla ripresa video avviene ogni 500 millisecondi:
Riga 127: Riga 263:
   
   
   
   
  '''Public''' Sub Form_Open()
  Public Sub Form_Open()
    
    
   Dim src, cnv As MediaControl
   Dim src, cnv As MediaControl
Riga 133: Riga 269:
   Dim dr As DrawingArea
   Dim dr As DrawingArea
    
    
  With dr = New DrawingArea(Me)
  With dr = New DrawingArea(Me)
    .X = 10
    .X = 10
    .Y = 10
    .Y = 10
    .W = 640
    .W = 640
    .H = 480
    .H = 480
<FONT Color=gray>' ''Affinché la "DrawingArea" mostri il video, è assolutamente necessario attribuire un colore qualsiasi alla sua proprietà ".Background":''</font>
  End With
    .Background = Color.Black
  End With
    
    
  pl = New MediaPipeline
  pl = New MediaPipeline
    
    
  src = New MediaControl(pl, "v4l2src")
  src = New MediaControl(pl, "v4l2src")
  src["device"] = "/dev/video0"
  src["device"] = "/dev/video0"
<FONT Color=gray>' ''...ma anche ad esempio così:''
'    = '''"/dev/v4l/by-id/'''usb-Generic_Integrated_Camera_0001-video-index0'''"'''</font>
    
    
  ftr = New MediaFilter(pl)
  ftr = New MediaFilter(pl)
  ftr.Filter = "video/x-raw,width=640,height=480,framerate=30/1"
  ftr.Filter = "video/x-raw,width=640,height=480,framerate=30/1"
  cnv = New MediaControl(pl, "videoconvert")
  cnv = New MediaControl(pl, "videoconvert")
  snk = New MediaControl(pl, "xvimagesink")
  snk = New MediaControl(pl, "xvimagesink")
      
      
  src.LinkTo(ftr)
  src.LinkTo(ftr)
  ftr.LinkTo(cnv)
  ftr.LinkTo(cnv)
  cnv.LinkTo(snk)
  cnv.LinkTo(snk)
    
    
  <FONT Color=gray>' ''Imposta la DrawingArea come superficie ove mostrare la ripresa video:''</font>
  <FONT Color=gray>' ''Imposta la DrawingArea come superficie ove mostrare la ripresa video:''</font>
  snk.SetWindow(dr)
  snk.SetWindow(dr)
    
    
  '''End'''
  End
   
   
   
   
  '''Public''' Sub Button1_Click()
  Public Sub Button1_Click()
    
    
   Dim i As Integer
   Dim i As Integer
   Dim drc, s As String
   Dim drc, s As String
    
    
  drc = "/tmp/immagini"
  drc = "/tmp/immagini"
    
    
  If Not Exist(drc) Then
  If Not Exist(drc) Then
    Mkdir drc
    Mkdir drc
  Else
  Else
    For Each s In Dir(drc, "immagine_*", gb.file)
    For Each s In Dir(drc, "immagine_*", gb.file)
      Kill drc &/ s
      Kill drc &/ s
    Next
    Next
  Endif
  Endif
    
    
  pl.Play()
  pl.Play()
    
    
  While pl.State = Media.Playing
  While pl.State = Media.Playing
    snk.GetLastImage().Save(drc &/ "immagine_" & CStr(I) & ".png")
    snk.GetLastImage().Save(drc &/ "immagine_" & CStr(I) & ".png")
    Print "Schermata video salvata nella cartella " & drc
    Print "Schermata video salvata nella cartella " & drc
  <FONT Color=gray>' ''Attende mezzo secondo per catturare un'altra immagine dalla ripresa video:''</font>
  <FONT Color=gray>' ''Attende mezzo secondo per catturare un'altra immagine dalla ripresa video:''</font>
    Wait 0.5
    Wait 0.5
    Inc i
    Inc i
  Wend
  Wend
    
    
  '''End'''
  End
   
   
   
   
  '''Public''' Sub Button2_Click()
  Public Sub Button2_Click()
 
  pl.Stop()
  pl.Stop()
  pl.Close()
  pl.Close()
 
 
  '''End'''
  End
 
 


===Usare il metodo "''.GetScreenshot( )''" della Classe "''DesktopWindow''" per catturare singole immagini dal video, e utilizzare una ''DrawingArea'' per mostrare la ripresa video===
===Usare il Metodo ".GetScreenshot()" della Classe ''DesktopWindow'' e una ''DrawingArea''===
Con questa modalità si raccoglierà mediante il metodo "''.GetScreenshot( )''" della Classe ''DesktopWindow''  <SUP>&#091;[[#Note|Nota 3]]&#093;</sup> quanto appare sulla superficie video utilizzata. Per individuare utilmente tale superficie video, è necessario individuare il suo ''handle''.
Con questa modalità si raccoglierà mediante il Metodo ".GetScreenshot()" della Classe ''DesktopWindow''  <SUP>&#091;[[#Note|nota 2]]&#093;</sup> quanto appare sulla superficie video utilizzata. Per individuare utilmente tale superficie video, è necessario individuare il suo ''handle''.
<BR>E' necessario attivare nell'applicazione Gambas i Componenti "''gb.desktop''" e "''gb.desktop.x11''".
<BR>E' necessario attivare nell'applicazione Gambas i Componenti ''gb.desktop'' e ''gb.desktop.x11''.


Mostriamo di seguito un esempio pratico, nel quale si salverà in un vettore di tipo ''Picture[ ]'' ogni 300 millesimi di secondo un'immagine del video, mostrato all'interno di una ''DrawingArea''. Al termine della ripresa video si provvederà a salvare ciascuna immagine, salvata nel predetto vettore, in un file immagine di tipo ''png''.
Mostriamo di seguito un esempio pratico, nel quale si salverà in un vettore di tipo "Picture[]" ogni 300 millesimi di secondo un'immagine del video, mostrato all'interno di una ''DrawingArea''. Al termine della ripresa video si provvederà a salvare ciascuna immagine, salvata nel predetto vettore, in un file immagine di tipo ''png''.
  Private dr As DrawingArea
  Private dr As DrawingArea
  Private pl As MediaPipeline
  Private pl As MediaPipeline
Riga 209: Riga 343:
   
   
   
   
  '''Public''' Sub Form_Open()
  Public Sub Form_Open()
    
    
Dim src, tim, cnv, snk As MediaControl
  Dim src, tim, cnv, snk As MediaControl
Dim ftr As MediaFilter
  Dim ftr As MediaFilter
    
    
   With dr = New DrawingArea(Me)
   With dr = New DrawingArea(Me)
Riga 219: Riga 353:
     .W = 640
     .W = 640
     .H = 480
     .H = 480
<FONT Color=gray>' ''Affinché la "DrawingArea" mostri il video, è assolutamente necessario attribuire un colore qualsiasi alla sua proprietà ".Background":''</font>
    .Background = Color.Black
   End With
   End With
    
    
Riga 227: Riga 359:
   src = New MediaControl(pl, "v4l2src")
   src = New MediaControl(pl, "v4l2src")
   src["device"] = "/dev/video0"
   src["device"] = "/dev/video0"
<FONT Color=gray>' ''...ma anche ad esempio così:''
'    = '''"/dev/v4l/by-id/'''usb-Generic_Integrated_Camera_0001-video-index0'''"'''</font>
   ftr = New MediaFilter(pl, "video/x-raw,width=640,height=480,framerate=30/1")
   ftr = New MediaFilter(pl, "video/x-raw,width=640,height=480,framerate=30/1")
  <FONT Color=gray>' ''Mostra nel video anche il tempo trascorso dall'avvio della ripresa:''</font>
  <FONT Color=gray>' ''Mostra nel video anche il tempo trascorso dall'avvio della ripresa:''</font>
Riga 240: Riga 375:
   snk.SetWindow(dr)
   snk.SetWindow(dr)
    
    
  '''End'''
  End
   
   
Public Sub Button1_Click()
   
   
'''Public''' Sub Button1_Click()
 
   Dim dw As DesktopWindow
   Dim dw As DesktopWindow
    
    
  <FONT Color=gray>' ''Avvia la ripresa video della WebCam:''</font>
  <FONT Color=gray>' ''Avvia la ripresa video della WebCam:''</font>
  pl.State = Media.Playing
  pl.State = Media.Playing
  pl.Play()
  pl.Play()
    
    
  <FONT Color=gray>' ''Resta in attesa che la WebCam avvi effettivamente la ripresa video:''</font>
  <FONT Color=gray>' ''Resta in attesa che la WebCam avvi effettivamente la ripresa video:''</font>
  Wait 2
  Wait 2
    
    
  dw = New DesktopWindow(dr.Handle)
  dw = New DesktopWindow(dr.Handle)
    
    
  While pl.State = Media.Playing
  While pl.State = Media.Playing
  <FONT Color=gray>' ''Cattura una schermata del contenuto video mostrato in quel momento dalla "DrawingArea":''</font>
  <FONT Color=gray>' ''Cattura una schermata del contenuto video mostrato in quel momento dalla "DrawingArea":''</font>
    pc.Push(dw.GetScreenshot(True))
    pc.Push(dw.GetScreenshot(True))
  <FONT Color=gray>' ''La cattura della schermata avviene ogni 300 millisecondi:''</font>
  <FONT Color=gray>' ''La cattura della schermata avviene ogni 300 millisecondi:''</font>
    Wait 0.3
    Wait 0.3
  Wend
  Wend
        
        
  '''End'''
  End
   
   
   
   
  '''Public''' Sub Button2_Click()    <FONT Color=gray>' ''Questo evento arresta la ripresa video e salva ogni picture in un file .png''</font>
  Public Sub Button2_Click()    <FONT Color=gray>' ''Questo evento arresta la ripresa video e salva ogni picture in un file .png''</font>
 
   Dim i As Integer
   Dim i As Integer
   Dim drc, s As String
   Dim drc, s As String
    
    
  drc = "/tmp/imago"
  drc = "/tmp/immago"
    
    
  pl.Stop
  pl.Stop
    
    
  If Not Exist(drc) Then
  If Not Exist(drc) Then
    Mkdir drc
    Mkdir drc
  Else
  Else
    For Each s In Dir(drc, "picture_*", gb.file)
    For Each s In Dir(drc, "picture_*", gb.file)
      Kill drc &/ s
      Kill drc &/ s
    Next
    Next
  Endif
  Endif
    
    
  For i = 0 To pc.Max
  For i = 0 To pc.Max
    pc[i].Save(drc &/ "picture_" & CStr(i) & ".png", 100)
    pc[i].Save(drc &/ "picture_" & CStr(i) & ".png", 100)
  Next
  Next
    
    
  '''End'''
  End


 
===Usare il Metodo ".GetLastImage()" della Classe ''MediaControl'', ma senza utilizzare una ''DrawingArea''===
===Usare il metodo "''.GetLastImage( )''" della Classe "''MediaControl''" per catturare singole immagini dal video, ma senza utilizzare una ''DrawingArea''===
Quest'altra modalità prevede che:
Quest'altra modalità prevede che:
* non sia utilizzata una ''DrawingArea'', come superficie ove mostrare la ripresa video, bensì una superficie generata automaticamente da ''GStreamer'';
* <U>non</u> sia utilizzata una ''DrawingArea'', come superficie ove mostrare la ripresa video, bensì una superficie generata automaticamente da ''GStreamer'';
* sia utilizzato il metodo "''.GetLastImage( )''" della Classe "''MediaControl''" per catturare singole immagini dal video.
* sia utilizzato il Metodo ".GetLastImage()" della Classe ''MediaControl'' per catturare singole immagini dal video.


Mostriamo di seguito un esempio pratico:
Mostriamo di seguito un esempio pratico:
Riga 300: Riga 434:
   
   
   
   
  '''Public''' Sub Form_Open()
  Public Sub Form_Open()
    
    
   Dim src, cnv As MediaControl
   Dim src, cnv As MediaControl
   Dim ftr As MediaFilter
   Dim ftr As MediaFilter
    
    
  pl = New MediaPipeline
  pl = New MediaPipeline
    
    
  src = New MediaControl(pl, "v4l2src")
  src = New MediaControl(pl, "v4l2src")
  src["device"] = "/dev/video0"
  src["device"] = "/dev/video0"
   ftr = New MediaFilter(pl)
<FONT Color=gray>' ''...ma anche ad esempio così:''
  ftr.Filter = "video/x-raw,width=640,height=480,framerate=30/1"
'   = '''"/dev/v4l/by-id/'''usb-Generic_Integrated_Camera_0001-video-index0'''"'''</font>
  cnv = New MediaControl(pl, "videoconvert")
  snk = New MediaControl(pl, "xvimagesink")
  ftr = New MediaFilter(pl)
  ftr.Filter = "video/x-raw,width=640,height=480,framerate=30/1"
  cnv = New MediaControl(pl, "videoconvert")
  snk = New MediaControl(pl, "xvimagesink")
      
      
  src.LinkTo(ftr)
  src.LinkTo(ftr)
  ftr.LinkTo(cnv)
  ftr.LinkTo(cnv)
  cnv.LinkTo(snk)
  cnv.LinkTo(snk)
    
    
  '''End'''
  End
   
   
   
   
  '''Public''' Sub Button1_Click()
  Public Sub Button1_Click()
    
    
   Dim i As Integer
   Dim i As Integer
   Dim drc, s As String
   Dim drc, s As String
    
    
  drc = "/tmp/immagini"
  drc = "/tmp/immagini"
    
    
  If Not Exist(drc) Then
  If Not Exist(drc) Then
    Mkdir drc
    Mkdir drc
  Else
  Else
    For Each s In Dir(drc, "immagine_*", gb.file)
    For Each s In Dir(drc, "immagine_*", gb.file)
      Kill drc &/ s
      Kill drc &/ s
    Next
    Next
  Endif
  Endif
    
    
  pl.Play()
  pl.Play()
 
  While pl.State = Media.Playing
    snk.GetLastImage().Save(drc &/ "immagine_" & CStr(I) & ".png")
    Print "Schermata video salvata nella cartella " & drc
    Wait 0.5
    Inc i
  Wend
    
    
  While pl.State = Media.Playing
End
    snk.GetLastImage().Save(drc &/ "immagine_" & CStr(I) & ".png")
    Print "Schermata video salvata nella cartella " & drc
    Wait 0.5
  Public Sub Button2_Click()
    Inc i
  Wend
 
  '''End'''
   
   
  pl.Stop()
  pl.Close()
   
   
  '''Public''' Sub Button2_Click()
  End
 
  pl.Stop()
  pl.Close()
 
'''End'''






=Note=
=Note=
[1] Vedi anche questa pagina della WIKI: [[Catturare_un'immagine_con_una_webcam_mediante_il_Componente_gb.media|Catturare un'immagine con una webcam mediante il Componente gb.media]]
[1] Riguardo all'Oggetto grafico da usare con il Metodo ".SetWindow()" della Classe ''MediaPlayer'', B. Minisini ha chiarito che esso necessita di un controllo che abbia una vera finestra X11 (o Wayland), altrimenti si userà il primo controllo genitore con una finestra reale (che di solito è quella di primo livello).
 
[2] Riguardo all'Oggetto grafico da usare con il Metodo ".SetWindow()" della Classe "MediaPlayer", B. Minisini ha chiarito che esso necessita di un controllo che avesse una vera finestra X11 (o ayland), altrimenti se userà il primo controllo genitore con una finestra reale, che di solito è quella di primo livello.


[3] Vedi anche questa pagina della WIKI: [[Generare_un_file_immagine_da_una_DrawingArea#1a_modalit.C3.A0|Generare un file immagine da una DrawingArea]]
[2] Vedi anche questa pagina della WIKI: [[Generare un file immagine da una DrawingArea]]

Versione attuale delle 14:36, 30 ago 2025

A volte può essere necessario estrarre e salvare in appositi file singole immagini di una ripresa video effettuata mediante una WebCam con il Componente gb.media.
Per fare ciò, sono disponibili alcune modalità.

E' il caso di sottolineare che con riferimento ai progetti in ambiente grafico è preferibile utilizzare le risorse di QT, altrimenti usando i Componenti GTK detti codici potrebbero non funzionare a dovere.


Usare la Classe MediaPlayer

Vediamo come sia possibile usare la Classe MediaPlayer del Componente gb.media per catturare le singole immagini.

Usare soltanto la Classe MediaPlayer con una PictureBox

In questo caso ci si servirà della sotto-Proprietà ".Image" della Proprietà "Video" della Classe MediaPlayer.

Mostriamo un esempio in ambiente grafico, nel quale si utilizzerà una PictureBox per mostrare il video e un'altra per mostrare l'immagine catturata:

Private PictureBox1 As PictureBox
Private PictureBox2 As PictureBox
Private button1 As Button
Private mp As MediaPlayer


Public Sub Form_Open()
 
 Me.Resize(Screen.AvailableWidth * 0.7, Screen.AvailableHeight * 0.7)

 With PictureBox1 = New PictureBox(Me)
   .X = 0
   .Y = 0
   .W = Me.W * 0.4
   .H = Me.W * 0.4
 End With
 With PictureBox2 = New PictureBox(Me)
   .X = PictureBox1.X + PictureBox1.W + (Me.W * 0.03)
   .Y = 0
   .W = Me.W * 0.4
   .H = Me.W * 0.4
   .Background = Color.SoftYellow
 End With
 With Button1 = New Button(Me) As "Button1"
   .X = PictureBox1.X + (Me.W * 0.03)
   .Y = PictureBox1.X + PictureBox1.H + (Me.W * 0.03)
   .W = Me.W * 0.1
   .H = Me.W * 0.07
 End With
 With mp = new MediaPlayer
   .URL = "v4l2:///dev/video0"
' ...ma anche ad esempio così:
'  ."v4l2:///dev/v4l/by-id/usb-Generic_Integrated_Camera_0001-video-index0"

   .SetWindow(PictureBox1)     ' [nota 1]
   .Play()
 End With

 Mkdir "/tmp/immagini_WebCam"

End
 

Public Sub Button1_Click() ' Cliccando sul tasto, si catturerà un'immagine dal video
 
 Dim im As Image

' Cattura un fotogramma dalla webcam e lo salva come immagine di formato PNG:
 With im = mp.Video.Image
   .Save("/tmp/immagini_WebCam" &/ Format(Now, "dd:mm:yyyy_hh:nn:ss.uu") & ".png")
 End With
 With Me
   .Center
   .Resize(PictureBox1.X + PictureBox1.W + im.W, im.H)
 End With 
With PictureBox2
  .Resize(im.W, im.H)
' Ingrandisce l'immagine mostrata nella "PictureBix" adattandola alle dimensione dell'immagine catturata dalla webcam:
  .Image = im.Stretch(mp.Video.Image.W, mp.Video.Image.H)
End With
  
End

Usare le Classi MediaPlayer, MediaControl con una DrawingArea

E' possibile usare le Classi MediaPlayer e MediaControl.

Mostriamo di seguito un semplice esempio, nel quale la ripresa sarà mostrata all'interno di una DrawingArea, e sarà salvata ogni secondo - grazie all'uso dell'Oggetto Timer - un'immagine della ripresa all'interno di un file immagine di formato PNG.

Private mp As MediaPlayer
Private im As MediaControl
Private drar As DrawingArea
Private tb As ToggleButton
Private tempus As Timer
Private i As Integer


Public Sub Form_Open()

 Dim flt As MediaFilter

 With Me
   .W = Screen.AvailableWidth * 0.75
   .H = Screen.AvailableHeight * 0.75
 End With
 With drar = New DrawingArea(Me)
   .X = Me.W * 0.05
   .Y = Me.H * 0.05
   .W = Me.W * 0.9
   .H = Me.H * 0.8
   .Border = Border.Plain
 End With
 With tb = New ToggleButton(Me) As "Tasto"
   .W = Me.W * 0.1
   .H = Me.H * 0.05
   .X = (Me.W / 2) - (.W / 2)
   .Y = 0
   .Text = "Avvia"
 End With

 If Not Exist("/tmp/immagini") Then Mkdir "/tmp/immagini"

 mp = New MediaPlayer As "MediaPlayer"
 flt = New MediaFilter(mp, "video/x-raw,width=640,height=480,framerate=30/1")
 im = New MediaControl(mp, "xvimagesink")

End


Public Sub Tasto_Click()

 mp.Video.Output = im
 mp.URL = "v4l2:///dev/video0"
' ...ma anche ad esempio così:
'    = "v4l2:///dev/v4l/by-id/usb-Generic_Integrated_Camera_0001-video-index0"

 im.SetWindow(drar)
 
 If tb.Value Then
   mp.Play
   With tempus = New Timer As "Tempus"
     .Delay = 1000
     .Start()
   End With
   tb.Text = "Stop"
 Else
   mp.Stop
   mp.Close
   tempus.Stop
   tb.Text = "Avvia"
 Endif
 
End


Public Sub Tempus_Timer()

 Dim img As Image

 img = mp.Video.Image
 Inc i

 img.Save("/tmp/immagini/foto_" & CStr(i) & ".png", 100)

 Me.Title = "Immagini catturate: " & CStr(i)

End


Uso della Classe MediaPipeline

Si potrà fare anche uso della Classe MediaPipeline per catturare singole immagini dalla ripresa video.

Semplice uso delle Classi MediaPipeline e MediaControl

Catturare un solo fotogramma

Mostriamo un esempio, nel quale si catturerà un singolo fotogramma e si creerà un file immagine di formato JPG:

Public Sub Button1_Click()

 Dim pl As MediaPipeline
 Dim src, enc, snk As MediaControl

 pl = New MediaPipeline 

 src = New MediaControl(pl, "v4l2src")
' Cattura un fotogramma dalla webcam e lo salva come immagine jpeg:
 src["num-buffers"] = 1
 enc = New MediaControl(pl, "jpegenc")
 snk = New MediaControl(pl, "filesink")
 snk["location"] = "/tmp/immagine.jpg"

' Collega fra loro i plugin di "GStreamer":
 src.LinkTo(enc)
 enc.LinkTo(snk)

' Effettua la ripresa dell'immagine:
 pl.Play()
 
' Con alcune webcam può essere necessario porre una breve pausa per consentire la ripresa dell'immagine:
 Wait 1

 pl.Stop()
 pl.Close()
 Print "Cattura immagine effettuata"

End

Catturare più fotogrammi

Mostriamo un esempio, questa volta a riga di comando, nel quale si cattureranno più fotogrammi della ripresa video mediante il plugin "multifilesink" di GStreamer:

Private bo As Boolean


Public Sub Main()

 Dim pl As MediaPipeline
 Dim src, dcb, vcn, enc, snk As MediaControl
 Dim tm As Date
 Dim i As Integer

 If Not Exist("/tmp/IMMAGINI") Then Mkdir "/tmp/IMMAGINI"

 pl = New MediaPipeline 

 src = New MediaControl(pl, "v4l2src")
 dcb = New MediaControl(pl, "decodebin")
 vcn = New MediaControl(pl, "videoconvert")
 enc = New MediaControl(pl, "pngenc")
 snk = New MediaControl(pl, "multifilesink")
' Per i nomi dei singoli file PNG si imposta un numero progressivo formato da 5 cifre decimali:
 snk["location"] = "/tmp/IMMAGINI/frame%05d.png"

' Collega fra loro i plugin di "GStreamer":
 src.LinkTo(dcb)
 dcb.LinkLaterTo(vcn)
 vcn.LinkTo(enc)
 enc.LinkTo(snk)

' Effettua la ripresa delle immagini:
 pl.Play()

 tm = Now 

 While Not bo
   i = DateDiff(tm, Now, gb.Millisecond)
' Il tempo trascorso dall'inizio della ripresa video viene mostrato in console/Terminale:
   Write "\rTempo: " & Str(Time(0, 0, 0, i))
   Flush 
   Wait 0.01
 Wend

 pl.Stop()
 pl.Close()
 Print "\nCattura immagini effettuata"

' Essendo stato utilizzato l'Evento "Application_Read()", è necessario usare l'istruzione "Quit" per terminare il programma e così per poter creare i singoli file immagine:
 Quit

End


Public Sub Application_Read() ' Premendo il tasto "Invio" della tastiera si arresta la ripresa video e si chiude il programma

 bo = True

End

Usare il Metodo ".GetLastImage()" della Classe MediaControl per catturare singole immagini dalla ripresa video, e utilizzare una DrawingArea per mostrarle

Quest'altra modalità prevede che:

  • sia utilizzata una DrawingArea, come superficie ove mostrare la ripresa video;
  • sia utilizzato il Metodo ".GetLastImage()" della Classe MediaControl per catturare singole immagini dal video.

Mostriamo di seguito un esempio pratico, nel quale la cattura delle immagini dalla ripresa video avviene ogni 500 millisecondi:

Private pl As MediaPipeline
Private snk As MediaControl


Public Sub Form_Open()
 
 Dim src, cnv As MediaControl
 Dim ftr As MediaFilter
 Dim dr As DrawingArea
 
 With dr = New DrawingArea(Me)
   .X = 10
   .Y = 10
   .W = 640
   .H = 480
 End With
  
 pl = New MediaPipeline
 
 src = New MediaControl(pl, "v4l2src")
 src["device"] = "/dev/video0"
' ...ma anche ad esempio così:
'    = "/dev/v4l/by-id/usb-Generic_Integrated_Camera_0001-video-index0"
  
 ftr = New MediaFilter(pl)
 ftr.Filter = "video/x-raw,width=640,height=480,framerate=30/1"
 cnv = New MediaControl(pl, "videoconvert")
 snk = New MediaControl(pl, "xvimagesink")
    
 src.LinkTo(ftr)
 ftr.LinkTo(cnv)
 cnv.LinkTo(snk)
  
' Imposta la DrawingArea come superficie ove mostrare la ripresa video:
 snk.SetWindow(dr)
  
End


Public Sub Button1_Click()
 
 Dim i As Integer
 Dim drc, s As String
  
 drc = "/tmp/immagini"
  
 If Not Exist(drc) Then
   Mkdir drc
 Else
   For Each s In Dir(drc, "immagine_*", gb.file)
     Kill drc &/ s
   Next
 Endif
  
 pl.Play()
  
 While pl.State = Media.Playing
   snk.GetLastImage().Save(drc &/ "immagine_" & CStr(I) & ".png")
   Print "Schermata video salvata nella cartella " & drc
' Attende mezzo secondo per catturare un'altra immagine dalla ripresa video:
   Wait 0.5
   Inc i
 Wend
  
End


Public Sub Button2_Click()

 pl.Stop()
 pl.Close()
 
End

Usare il Metodo ".GetScreenshot()" della Classe DesktopWindow e una DrawingArea

Con questa modalità si raccoglierà mediante il Metodo ".GetScreenshot()" della Classe DesktopWindow [nota 2] quanto appare sulla superficie video utilizzata. Per individuare utilmente tale superficie video, è necessario individuare il suo handle.
E' necessario attivare nell'applicazione Gambas i Componenti gb.desktop e gb.desktop.x11.

Mostriamo di seguito un esempio pratico, nel quale si salverà in un vettore di tipo "Picture[]" ogni 300 millesimi di secondo un'immagine del video, mostrato all'interno di una DrawingArea. Al termine della ripresa video si provvederà a salvare ciascuna immagine, salvata nel predetto vettore, in un file immagine di tipo png.

Private dr As DrawingArea
Private pl As MediaPipeline
Private pc As New Picture[]


Public Sub Form_Open()
 
 Dim src, tim, cnv, snk As MediaControl
 Dim ftr As MediaFilter
 
 With dr = New DrawingArea(Me)
   .X = 10
   .Y = 10
   .W = 640
   .H = 480
 End With
 
 pl = New MediaPipeline 
 
 src = New MediaControl(pl, "v4l2src")
 src["device"] = "/dev/video0"
' ...ma anche ad esempio così:
'    = "/dev/v4l/by-id/usb-Generic_Integrated_Camera_0001-video-index0"

 ftr = New MediaFilter(pl, "video/x-raw,width=640,height=480,framerate=30/1")
' Mostra nel video anche il tempo trascorso dall'avvio della ripresa:
 tim = New MediaControl(pl, "timeoverlay")
 cnv = New MediaControl(pl, "videoconvert")
 snk = New MediaControl(pl, "xvimagesink")
 
' Colleghiamo i quattro plug-in di "GStreamer":
 src.LinkTo(ftr)
 ftr.LinkTo(tim)
 tim.LinkTo(cnv)
 cnv.LinkTo(snk)
 snk.SetWindow(dr)
  
End


Public Sub Button1_Click()

 Dim dw As DesktopWindow
 
' Avvia la ripresa video della WebCam:
 pl.State = Media.Playing
 pl.Play()
 
' Resta in attesa che la WebCam avvi effettivamente la ripresa video:
 Wait 2
  
 dw = New DesktopWindow(dr.Handle)
 
 While pl.State = Media.Playing
' Cattura una schermata del contenuto video mostrato in quel momento dalla "DrawingArea":
   pc.Push(dw.GetScreenshot(True))
' La cattura della schermata avviene ogni 300 millisecondi:
   Wait 0.3
 Wend
     
End


Public Sub Button2_Click()    ' Questo evento arresta la ripresa video e salva ogni picture in un file .png

 Dim i As Integer
 Dim drc, s As String
  
 drc = "/tmp/immago"
  
 pl.Stop
 
 If Not Exist(drc) Then
   Mkdir drc
 Else
   For Each s In Dir(drc, "picture_*", gb.file)
     Kill drc &/ s
   Next
 Endif
 
 For i = 0 To pc.Max
   pc[i].Save(drc &/ "picture_" & CStr(i) & ".png", 100)
 Next
  
End

Usare il Metodo ".GetLastImage()" della Classe MediaControl, ma senza utilizzare una DrawingArea

Quest'altra modalità prevede che:

  • non sia utilizzata una DrawingArea, come superficie ove mostrare la ripresa video, bensì una superficie generata automaticamente da GStreamer;
  • sia utilizzato il Metodo ".GetLastImage()" della Classe MediaControl per catturare singole immagini dal video.

Mostriamo di seguito un esempio pratico:

Private pl As MediaPipeline
Private snk As MediaControl


Public Sub Form_Open()
 
 Dim src, cnv As MediaControl
 Dim ftr As MediaFilter
 
 pl = New MediaPipeline
 
 src = New MediaControl(pl, "v4l2src")
 src["device"] = "/dev/video0"
' ...ma anche ad esempio così:
'    = "/dev/v4l/by-id/usb-Generic_Integrated_Camera_0001-video-index0"

 ftr = New MediaFilter(pl)
 ftr.Filter = "video/x-raw,width=640,height=480,framerate=30/1"
 cnv = New MediaControl(pl, "videoconvert")
 snk = New MediaControl(pl, "xvimagesink")
    
 src.LinkTo(ftr)
 ftr.LinkTo(cnv)
 cnv.LinkTo(snk)
  
End


Public Sub Button1_Click()
 
 Dim i As Integer
 Dim drc, s As String
  
 drc = "/tmp/immagini"
  
 If Not Exist(drc) Then
   Mkdir drc
 Else
   For Each s In Dir(drc, "immagine_*", gb.file)
     Kill drc &/ s
   Next
 Endif
  
 pl.Play()
 
 While pl.State = Media.Playing
   snk.GetLastImage().Save(drc &/ "immagine_" & CStr(I) & ".png")
   Print "Schermata video salvata nella cartella " & drc
   Wait 0.5
   Inc i
 Wend
  
End


Public Sub Button2_Click()

 pl.Stop()
 pl.Close()

End


Note

[1] Riguardo all'Oggetto grafico da usare con il Metodo ".SetWindow()" della Classe MediaPlayer, B. Minisini ha chiarito che esso necessita di un controllo che abbia una vera finestra X11 (o Wayland), altrimenti si userà il primo controllo genitore con una finestra reale (che di solito è quella di primo livello).

[2] Vedi anche questa pagina della WIKI: Generare un file immagine da una DrawingArea