Differenze tra le versioni di "Estrarre e salvare singole immagini da una ripresa video mediante WebCam effettuata con il Componente gb.media"
(19 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''. | + | 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 | + | 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 | + | 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 | + | 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" | ||
+ | .SetWindow(PictureBox1) ' <SUP>[[[#Note|nota 1]]]</sup> | ||
+ | .Play() | ||
+ | End With | ||
+ | |||
+ | Mkdir "/tmp/immagini_WebCam" | ||
+ | |||
+ | End | ||
+ | |||
+ | |||
+ | Public Sub Button1_Click() <FONT Color=gray>' ''Cliccando sul tasto, si catturerà un'immagine dal video''</font> | ||
+ | |||
+ | Dim im As Image | ||
+ | |||
+ | <FONT Color=gray>' ''Cattura un fotogramma dalla webcam e lo salva come immagine di formato PNG:''</font> | ||
+ | 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) | ||
+ | <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 | ||
+ | |||
+ | ===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 im As MediaControl | ||
+ | Private drar As DrawingArea | ||
Private tb As ToggleButton | Private tb As ToggleButton | ||
Private tempus As Timer | Private tempus As Timer | ||
Riga 16: | Riga 83: | ||
− | + | Public Sub Form_Open() | |
− | + | ||
− | |||
Dim flt As MediaFilter | 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" | ||
+ | |||
+ | im.SetWindow(drar) | ||
If tb.Value Then | If tb.Value Then | ||
− | + | 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 | ||
− | + | mp.Stop | |
− | + | mp.Close | |
tempus.Stop | tempus.Stop | ||
+ | tb.Text = "Avvia" | ||
Endif | Endif | ||
− | + | End | |
+ | |||
+ | Public Sub Tempus_Timer() | ||
− | |||
− | |||
Dim img As Image | Dim img As Image | ||
− | Dim | + | |
+ | 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() | ||
− | + | <FONT Color=gray>' ''Con alcune webcam può essere necessario porre una breve pausa per consentire la ripresa dell'immagine:''</font> | |
− | + | 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") | ||
+ | <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 | ||
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 | + | * 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 96: | Riga 258: | ||
− | + | Public Sub Form_Open() | |
Dim src, cnv As MediaControl | Dim src, cnv As MediaControl | ||
Riga 102: | Riga 264: | ||
Dim dr As DrawingArea | 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" | |
− | + | 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) | |
<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) | |
− | + | End | |
− | + | 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" | |
− | + | 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 | |
<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 | |
− | + | Inc i | |
− | + | Wend | |
− | + | End | |
− | + | Public Sub Button2_Click() | |
− | + | ||
− | + | pl.Stop() | |
− | + | pl.Close() | |
− | + | ||
− | + | End | |
− | |||
− | |||
− | ===Usare il | + | ===Usare il Metodo ".GetScreenshot()" della Classe ''DesktopWindow'' e una ''DrawingArea''=== |
− | Con questa modalità si raccoglierà mediante il | + | Con questa modalità si raccoglierà mediante il Metodo ".GetScreenshot()" della Classe ''DesktopWindow'' <SUP>[[[#Note|nota 2]]]</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 | + | <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 | + | 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 178: | Riga 336: | ||
− | + | Public Sub Form_Open() | |
− | + | Dim src, tim, cnv, snk As MediaControl | |
− | + | Dim ftr As MediaFilter | |
With dr = New DrawingArea(Me) | With dr = New DrawingArea(Me) | ||
Riga 188: | Riga 346: | ||
.W = 640 | .W = 640 | ||
.H = 480 | .H = 480 | ||
− | |||
− | |||
End With | End With | ||
Riga 209: | Riga 365: | ||
snk.SetWindow(dr) | snk.SetWindow(dr) | ||
− | + | End | |
− | + | 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.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 | |
− | + | dw = New DesktopWindow(dr.Handle) | |
− | + | 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)) | |
<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 | |
− | + | Wend | |
− | + | End | |
+ | |||
+ | 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/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''=== | |
− | ===Usare il | ||
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 | + | * 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 269: | Riga 424: | ||
− | + | 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 | |
− | + | src = New MediaControl(pl, "v4l2src") | |
− | + | src["device"] = "/dev/video0" | |
− | + | 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 i As Integer | ||
Dim drc, s As String | 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= | =Note= | ||
− | [1 | + | [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]] |
Versione attuale delle 18:04, 15 lug 2024
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.
Indice
- 1 Usare la Classe MediaPlayer
- 2 Uso della Classe MediaPipeline
- 2.1 Semplice uso delle Classi MediaPipeline e MediaControl
- 2.2 Usare il Metodo ".GetLastImage()" della Classe MediaControl per catturare singole immagini dalla ripresa video, e utilizzare una DrawingArea per mostrarle
- 2.3 Usare il Metodo ".GetScreenshot()" della Classe DesktopWindow e una DrawingArea
- 2.4 Usare il Metodo ".GetLastImage()" della Classe MediaControl, ma senza utilizzare una DrawingArea
- 3 Note
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" .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" 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" 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" 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" 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