Visualizzazione dei risultati da 1 a 6 su 6
  1. #1
    Utente di HTML.it
    Registrato dal
    Apr 2009
    Messaggi
    970

    [VB.NET] Velocità elaborazione Pixel a Pixel da Webcam

    Dunque, ricollegandomi alla discussione di acquisizione di immagini da Webcam, ho creato un'applicazione che, confrontanto i fotogrammi delle cam e impostando ovviamente delle soglie sia di luminosità che di numero di pixel in cui è avvenuto un cambiamento di luminosità, mi dice se c'è stato un cambiamento tra un fotogramma e l'altro e quindi del movimento.
    Ora parte del codice che gestisce tutto questo é

    codice:
     Private Function ControlImage(ByVal immagine_or As Image, ByVal immagine_new As Image) As Boolean
            Try
                Dim esito As Boolean
                Dim bm_or As Bitmap
                Dim bm_new As Bitmap
                Dim bmpData_or As System.Drawing.Imaging.BitmapData
                Dim bmpData_new As System.Drawing.Imaging.BitmapData
                Dim rect_or As Rectangle
                Dim rect_new As Rectangle
                Dim ptr_or As IntPtr
                Dim ptr_new As IntPtr
                Dim bytes As Integer
    
                bm_or = New Bitmap(immagine_or)
                bm_new = New Bitmap(immagine_new)
    
                'Estrazione dei colori nell'immagine del primo fotogramma
                 rect_or = New Rectangle(0, 0, bm_or.Width, bm_or.Height)
                bmpData_or = bm_or.LockBits(rect_or, Drawing.Imaging.ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb)
    
                ' Get the address of the first line.
                ptr_or = bmpData_or.Scan0
    
                bytes = bm_or.Width * bm_or.Height * 3
                Dim rgbValues_or(bytes - 1) As Byte
    
                ' Copy the RGB values into the array.
                System.Runtime.InteropServices.Marshal.Copy(ptr_or, rgbValues_or, 0, bytes)
    
               'Estrazione dei colori nell'immagine del secondo fotogramma
               rect_new = New Rectangle(0, 0, bm_new.Width, bm_new.Height)
                bmpData_new = bm_new.LockBits(rect_new, Drawing.Imaging.ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb)
    
                 ptr_new = bmpData_new.Scan0
    
                Dim rgbValues_new(bytes - 1) As Byte
    
                Dim pixelBytes As Integer = 3
                ' Copy the RGB values into the array.
                System.Runtime.InteropServices.Marshal.Copy(ptr_new, rgbValues_new, 0, bytes)
    
                ' Unlock the bits.
                bm_new.UnlockBits(bmpData_new)
    
                '*************************************************************
                Dim diffPix As Integer
                Dim lumaPixel As Double
                Dim Max As Double
                Dim Min As Double
                Dim temp As Double
                Dim temp2 As Double
                Dim pos As Integer
                Dim scanPixel As Integer
                Dim listaPointX As New List(Of Integer)
                Dim listaPointY As New List(Of Integer)
    
                PixelChanged = 0
                scanPixel = 0
    
                '*********************************************************
    
                    For Y As Integer = 0 To bm_or.Height - 1 Step scanPixSixeY
                        For X As Integer = 0 To bm_or.Width - 1 Step scanPixSixeX
                            pos = (Y * bmpData_new.Stride) + (X * pixelBytes)
                            diffPix = CInt(rgbValues_new(pos)) - CInt(rgbValues_or(pos))
                            scanPixel += 1
    
                            'Calcolo luminosità
                            lumaPixel = rgbValues_or(pos) / 255
                            Max = 0
                            Min = 1
                            If lumaPixel > Max Then Max = lumaPixel
                            If lumaPixel < Min Then Min = lumaPixel
                            temp = System.Math.Min(((Max + Min) / 2 * 255), 255)
                            temp2 += temp
                            '******************
    
                            If (rgbValues_new(pos) >= SensibiltàColoriView.B AndAlso System.Math.Abs(diffPix) > (rgbValues_or(pos) * SensibilitaColore)) Then
    
                                PixelChanged += 1
    
                                listaPointX.Add(X)
                                listaPointY.Add(Y)
    
                                rgbValues_or(pos + 2) = PixelChangedColor.R    'Red
                                rgbValues_or(pos + 1) = PixelChangedColor.G    'Green
                                rgbValues_or(pos) = PixelChangedColor.B        'Blue
    
                                If esito = False AndAlso PixelChanged > SensilitàPixel Then
                                    esito = True
                                End If
                            End If
                        Next
                    Next
    
                    luminosity = temp2 / scanPixel
                    listaPointX.Sort()
                    listaPointY.Sort()
    
            
                '*************************************************************
               
     System.Runtime.InteropServices.Marshal.Copy(rgbValues_or, 0, ptr_or, bytes)
                bm_or.UnlockBits(bmpData_or)
    
                Dim myPoint(1) As Point
                If listaPointX.Count > 0 Then myPoint(0).X = listaPointX(0)
                If listaPointY.Count > 0 Then myPoint(0).Y = listaPointY(0)
                If listaPointX.Count > 0 Then myPoint(1).X = listaPointX(listaPointX.Count - 1)
                If listaPointY.Count > 0 Then myPoint(1).Y = listaPointY(listaPointY.Count - 1)
    
                RaiseEvent PixelChangedView(bm_or, bm_new, esito, PixelChanged, luminosity, myPoint)
    
                bm_or.Dispose()
                bm_or = Nothing
                bm_new.Dispose()
                bm_new = Nothing
                rect_or = Nothing
                rect_new = Nothing
    
                img1 = img2.Clone
                img2.Dispose()
                img2 = Nothing
                listaPointX = Nothing
                listaPointY = Nothing
                TimeElapsed = System.Environment.TickCount - count
                Return esito
            Catch ex As Exception
                'MsgBox(ex.Message)
            End Try
        End Function
    La sequenza è abbastanza semplice e intuitiva:
    -prendo il primo e il secondo fotogramma
    -li converto in due matrici distinte, dove ogni matrice è composta dai valori RBG del singoli pixel nel formato R,G,B quindi se rgbValue è la mia matrice avrò:
    rgbValue(0) = valore Blu pixel 1
    rgbValue(1) = valore verde pixel 1
    rgbValue(2) = valore rosso pixel 1

    rgbValue(3) = valore Blu pixel 2
    rgbValue(4) = valore verde pixel 2
    rgbValue(5) = valore rosso pixel 2
    - Confronto le due matrici e traggo le mie conclusioni.

    Ora le mie domando sono:
    1-E' meglio confrontare le due matrici così come sono composte, ovvero:
    codice:
     For pos As Integer = 0 To rgbValue.Length - 1 Step 3
          pixB = rgbValue(pos )           'Valore pixel blu
          pixG = rgbValue(pos + 1)      'Valore pixel verde
          pixR = rgbValue(pos + 2)      'Valore pixel rosso
     Next
    oppure in questo modo:
    codice:
     For Y As Integer = 0 To bm_or.Height - 1 
           For X As Integer = 0 To bm_or.Width - 1 
                      pos = (Y * bmpData_new.Stride) + (X * pixelBytes)
                       pixB = rgbValue(pos)
                       pixG = rgbValue(pos +1)
                       pixR = rgbValue(pos +2)
          Next
    Next
    2-Cosa posso fare per velocizzare l'esecuzione? (per un fotogramma da 640x480 sul mio PC l'elaborazione avviene in circa 50 ms)

    L'ouput a video dell'applizazione è:

    Sbagliare è umano, perseverare è diabolico.

  2. #2
    Utente di HTML.it L'avatar di gibra
    Registrato dal
    Apr 2008
    residenza
    Italy
    Messaggi
    4,244
    Se confronti tutti i pixel l'elaborazione è lenta, questo è ovvio.
    Io ti suggerisco di prendere dei 'campioni' di pixel, piuttosto che elaborare tutti i pixel.

    Anni fa ho seguito questo metodo quando dovevo 'catturare' dal web i fotogrammi da uno streaming video. Avendo una connessione telefonica dial-up da pochi kb non potevo né temporizzare la cattura, né stare davanti al monitor per catturarli una alla volta.

    In questo modo catturavo il fotogramma solo quando cambiava e lo salvavo 'al volo' in bmp, poi alla fine mi ricrevo il filmato AVI grazie alle immagini salvate.

    La scelta di quanti e quali campioni utilizzare dipende dal risultato che si cerca, ovvero che livello di precisione mi occorre.

    Ad esempio, suddividendo 'logicamente' i fotogrammi in 9 rettangoli 3x3 (o più... scegli tu) puoi selezionare ad esempio 3 pixel da 5 rettangoli (vedi schema sotto) per un totale di 18 pixel che confronterai tra i due fotogrammi.
    E' abbastanza improbabile che cambi un fotogramma senza che almeno uno di questi pixel cambi anch'esso.

    codice:
    -------------------
    |  *  |     |  *  |
    -------------------
    |     |  *  |     |
    -------------------
    |  *  |     |  *  |
    -------------------
    Naturalmente dopo qualche prova potrai verificare se devi aumentare i rettangoli anzichè i 5 indicati nell'asterisco, e se per ogni rettangolo aumentari il numero di pixel da catturare.

    Sicuramente è assai più veloce che non leggere tutti i pixels.


  3. #3
    Utente di HTML.it
    Registrato dal
    Apr 2009
    Messaggi
    970
    Mi metto subto al lavoro e provo, grazie.

    Già mettendo uno step di 3 pixel la velocità di elaborazione dimezza.
    codice:
     For Y As Integer = 0 To bm_or.Height - 1 Step 3
               For X As Integer = 0 To bm_or.Width - 1  step 3
               'Codice
               Next
      Next
    Come si vede dall'immagine elaborata (i pixel rossi sono quelli cambiati dal fotogramma precedente)
    Sbagliare è umano, perseverare è diabolico.

  4. #4
    Utente di HTML.it
    Registrato dal
    Apr 2009
    Messaggi
    970
    Originariamente inviato da gibra
    Se confronti tutti i pixel l'elaborazione è lenta, questo è ovvio.
    Io ti suggerisco di prendere dei 'campioni' di pixel, piuttosto che elaborare tutti i pixel.

    Anni fa ho seguito questo metodo quando dovevo 'catturare' dal web i fotogrammi da uno streaming video. Avendo una connessione telefonica dial-up da pochi kb non potevo né temporizzare la cattura, né stare davanti al monitor per catturarli una alla volta.

    In questo modo catturavo il fotogramma solo quando cambiava e lo salvavo 'al volo' in bmp, poi alla fine mi ricrevo il filmato AVI grazie alle immagini salvate.

    La scelta di quanti e quali campioni utilizzare dipende dal risultato che si cerca, ovvero che livello di precisione mi occorre.

    Ad esempio, suddividendo 'logicamente' i fotogrammi in 9 rettangoli 3x3 (o più... scegli tu) puoi selezionare ad esempio 3 pixel da 5 rettangoli (vedi schema sotto) per un totale di 18 pixel che confronterai tra i due fotogrammi.
    E' abbastanza improbabile che cambi un fotogramma senza che almeno uno di questi pixel cambi anch'esso.

    codice:
    -------------------
    |  *  |     |  *  |
    -------------------
    |     |  *  |     |
    -------------------
    |  *  |     |  *  |
    -------------------
    Naturalmente dopo qualche prova potrai verificare se devi aumentare i rettangoli anzichè i 5 indicati nell'asterisco, e se per ogni rettangolo aumentari il numero di pixel da catturare.

    Sicuramente è assai più veloce che non leggere tutti i pixels.

    Ma tipo qualcosa del genere ??
    Immagini allegate Immagini allegate
    Sbagliare è umano, perseverare è diabolico.

  5. #5
    Utente di HTML.it L'avatar di gibra
    Registrato dal
    Apr 2008
    residenza
    Italy
    Messaggi
    4,244
    Scusa, ma se non spieghi cosa rappresenta quell'immagine... non so cosa risponderti.
    Mi sembra di essere stato abbastanza chiaro, o no?

  6. #6
    Utente di HTML.it
    Registrato dal
    Apr 2009
    Messaggi
    970
    Lascia pedere quell'immagine, è puramente dimostrativa. La Webcam riprenderà in realtà un magazzino.
    Sbagliare è umano, perseverare è diabolico.

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.