Visualizzazione dei risultati da 1 a 8 su 8
  1. #1
    Utente di HTML.it
    Registrato dal
    Sep 2011
    Messaggi
    8

    VB: analisi dell'immagine

    Salve a tutti,
    sto cercando di realizzare un sistema di analisi dell'immagine proveniente da una telecamera. L'analisi in se non è troppo difficile, si tratta di selezionare una area rettangolare (fissa) e controllare quanti pixel di questa area differiscono (con un certo margine) da un colore campione settato.
    Per adesso, per fare una prova, ho solo calcolato il colore medio dell'area selezionata (tanto per far fare qualcosa al programma). Per quanto riguarda l'analisi dei pixel dell'area non ho problemi, almeno fino a quando lo posso fare con le normali istruzioni in VB, cicli, calcoli, ecc... Premetto che conosco VB abbastanza superficialmente, e tendo comunque per formazione a utilizzare istruzioni semplici anche per fare cose complesse...
    Come telecamera sto usando una webcam (settata a 640x480). Per l'accesso alle immagini della webcam ho fatto un po' di copia e incolla su alcuni sorgenti trovati in rete, e grossomodo funziona. Purtroppo non ho capito come funzionano di preciso le istruzioni che mi creano l'immagine, quindi il programma sicuramente non è ottimizzato.

    Il principale problema che ho adesso (e che mi aspettavo, ma almeno ho tentato di fare qualcosa da solo) è che il programma è troppo lento. In generale non riesco a caricare più di 10 immagini al secondo (sebbene tenti di caricarne 20, con un timer ciclico di 50 ms)... Se poi l'area di pixel da anlizzare cresce un pochino (al momento sto analizzando 6300 pixel) le immagini al secondo analizzate diminuiscono ancora (bene che vada ne analizzo 5 o 6). Poichè vorrei poter analizzare aree più vaste (in previsione di utilizzare immagini a risoluzione superiore, almeno 1024x768) e con maggiore velocità (20-25 frame al secondo), vorrei capire come poter ottimizzare il codice, o se magari conviene cambiare linguaggio di programmazione.

    Questo è il codice del programma:

    Form principale:
    codice:
    Option Explicit
    Dim Frame_Per_Sec As Integer    'contatore frame per secondo elaborati
    Dim Xcoord_start As Integer     'coordinate inizio area analizzata
    Dim Ycoord_start As Integer     'coordinate inizio area analizzata
    Dim Xcoord_end As Integer       'coordinate fine area analizzata
    Dim Ycoord_end As Integer       'coordinate fine area analizzata
    Dim hCap As Long
     
     
    Private Sub cmdImpostazioniVideo_Click()
    'Visualizza la finestra di dialogo per la modifica delle impostazioni video.
    Call SendMessage(hCap, WM_CAP_DLG_VIDEOFORMAT, 0&, 0&)
    End Sub
     
     
    Private Sub Timer1_Timer()
    'base tempi 50 ms, poi gira a quanto ce la fa...
    'acquisisco una immagine
    SendMessage hCap, WM_CAP_EDIT_COPY, 0&, 0&
    picCam2.Picture = Clipboard.GetData
     
    Dim pixelColor As Long          'variabile prelievo colore pixel
    'variabili singoli colori
    Dim red As Long                 'le dichiaro long perchè sennò non funziona, chissà perchè...
    Dim green As Long
    Dim blue As Long
     
    'variabili analisi colore per calcolo colore medio
    Dim red_medium As Long
    Dim green_medium As Long
    Dim blue_medium As Long
    Dim pixel_number As Long
     
    'puntatori cicli
    Dim i As Integer
    Dim j As Integer
     
    'inizializzazione variabili
    pixel_number = 0
    red_medium = 0
    green_medium = 0
    blue_medium = 0
    Xcoord_start = 5
    Xcoord_end = 634
    Ycoord_start = 100
    Ycoord_end = 109
     
    'ciclo lettura pixel e calcolo media
    For i = Xcoord_start To Xcoord_end
        For j = Ycoord_start To Ycoord_end
            pixelColor = GetPixel(picCam2.hdc, i, j)        'lettura colore pixel
            blue = pixelColor \ 65536                       'estrazione informazione blu
            green = (pixelColor - blue * 65536) \ 256       'estrazione informazione verde
            red = pixelColor - blue * 65536 - green * 256   'estrazione informazione rosso
            
            red_medium = red_medium + red                   'media colore rosso
            green_medium = green_medium + green             'media colore verde
            blue_medium = blue_medium + blue                'media colore blu
            pixel_number = pixel_number + 1                 'conteggio pixel analizzati
        Next
    Next
     
    'visualizzazione numero pixel analizzati
    Text1.Text = pixel_number
     
    'calcolo e visualizzazione media colore area
    Rout.Text = red_medium / pixel_number
    Gout.Text = green_medium / pixel_number
    Bout.Text = blue_medium / pixel_number
     
    'disegno un rettangolo rosso intorno all'area analizzata
    'riga superiore
    For i = Xcoord_start To Xcoord_end
        SetPixel picCam2.hdc, i, Ycoord_start, 255
    Next
    'riga inferiore
    For i = Xcoord_start To Xcoord_end
        SetPixel picCam2.hdc, i, Ycoord_end, 255
    Next
    'riga sinistra
    For j = Ycoord_start To Ycoord_end
        SetPixel picCam2.hdc, Xcoord_start, j, 255
    Next
    'riga destra
    For j = Ycoord_start To Ycoord_end
        SetPixel picCam2.hdc, Xcoord_end, j, 255
    Next
     
    'contatore frame per secondo analizzati
    Frame_Per_Sec = Frame_Per_Sec + 1
    End Sub
     
     
    Private Sub Timer2_Timer()
    'base tempi 1 secondo
    'visualizzo il numero di frame per secondo analizzati e resetto il contatore
    Text2.Text = Frame_Per_Sec
    Frame_Per_Sec = 0
    End Sub
     
     
    Private Sub Form_Load()
    hCap = capCreateCaptureWindow("Cattura immagini", WS_CHILD Or WS_VISIBLE, 0, 0, picCam.Width, picCam.Height, picCam.hWnd, 0)
    
    If hCap <> 0 Then
    Call SendMessage(hCap, WM_CAP_DRIVER_CONNECT, 0, 0)
    Call SendMessage(hCap, WM_CAP_SET_PREVIEWRATE, 66, 0&)
    Call SendMessage(hCap, WM_CAP_SET_PREVIEW, CLng(True), 0&)
    End If
    End Sub
     
    
    Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
    On Error Resume Next
    Call SendMessage(hCap, WM_CAP_DRIVER_DISCONNECT, 0, 0)
    If hCap <> 0 Then DestroyWindow (hCap)
    Kill App.Path & "\Temp.bmp"
    End Sub


    Modulo:
    codice:
    Option Explicit
    Public Const WS_CHILD As Long = &H40000000
    Public Const WS_VISIBLE As Long = &H10000000
     
    Public Declare Function capCreateCaptureWindow Lib "avicap32.dll" Alias "capCreateCaptureWindowA" (ByVal lpszWindowName As String, ByVal dwStyle As Long, ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hwndParent As Long, ByVal nID As Long) As Long
     
    Public Const WM_USER As Long = &H400
    Public Const WM_CAP_START As Long = WM_USER
    Public Const WM_CAP_EDIT_COPY As Long = WM_USER + 30
    Public Const WM_CAP_DRIVER_CONNECT As Long = WM_CAP_START + 10
    Public Const WM_CAP_DRIVER_DISCONNECT As Long = WM_CAP_START + 11
    Public Const WM_CAP_SET_PREVIEW As Long = WM_CAP_START + 50
    Public Const WM_CAP_SET_PREVIEWRATE As Long = WM_CAP_START + 52
    Public Const WM_CAP_DLG_VIDEOFORMAT As Long = WM_CAP_START + 41
    Public Const WM_CAP_FILE_SAVEDIB As Long = WM_CAP_START + 25
     
    Public Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByRef lParam As Any) As Long
     
    Public Declare Function DestroyWindow Lib "user32" (ByVal hWnd As Long) As Long
    Public Declare Function GetPixel Lib "gdi32" (ByVal hdc As Long, ByVal x As Long, ByVal y As Long) As Long
    
    Public Declare Function SetPixel Lib "gdi32" (ByVal hdc As Long, ByVal x As Long, ByVal y As Long, ByVal crColor As Long) As Long
    Nel form principale ho due picturebox (picCam e picCam2). Nella prima visualizzo direttamente quello che ricevo dalla webcam (non mi serve a nulla, ma il sorgente che ho copiato faceva così, e non so come toglierla), mentre nella seconda acquisisco una immagine ogni volta che devo fare l'analisi. Ho provato a fare l'analisi della prima immagine (stoppando la ricezione delle immagini dala webcam per avere un frame fisso) ma non riesco a prelevare il colore dei pixel, mentre dalla seconda immagine funziona.

    Ho inoltre le seguenti textbox di output:
    Rout: valore medio colore rosso
    Gout: valore medio colore verde
    Bout: valore medio colore blu

    Text1: numero pixel analizzati
    Text2: numero frame al secondo analizzati

    Ho postato il codice del progetto, se può essere utile posso allegare in qualche modo anche tutto il progetto in VB.

    Spero di non essermi dimenticato nulla di utile...

    Grazie a tutti!

  2. #2
    GetPixel e SetPixel sono funzioni estremamente lente, dovresti ottenere la tua immagine in una bitmap e lavorare direttamente sui pixel in memoria; per fare ciò in maniera efficiente, però, probabilmente dovresti lavorare in C o in C++ (sia perché in VB non ci sono i puntatori e quindi diventa difficile lavorare in questa maniera, sia perché sono linguaggi molto più veloci e con compilatori decisamente migliori).
    Amaro C++, il gusto pieno dell'undefined behavior.

  3. #3
    Utente di HTML.it
    Registrato dal
    Sep 2011
    Messaggi
    8
    Sospettavo una cosa del genere...
    Un chiarimento: ottenere l'immagine in bitmap significa che la camera deve inviarmela già in formato bitmap? O basta solo salvarla in bmp? In pratica dopo vado a leggere direttamente il file con un puntatore, giusto?

  4. #4
    Non parlo dello specifico formato .BMP (ovvero delle DIB), parlo semplicemente di una rappresentazione in cui hai un blocco di memoria che contiene i pixel in forma di array accessibile in maniera semplice (ogni accesso ad un pixel si riduce ad una somma di un numero ad un puntatore e alla sua dereferenziazione); ovviamente non vorrai passare per dei file, dato che l'IO su disco ucciderebbe le performance.

    Comunque per l'analisi di immagini ci sono ottime librerie già pronte (come la OpenCV) che sicuramente hanno algoritmi con prestazioni migliori.
    Amaro C++, il gusto pieno dell'undefined behavior.

  5. #5
    Utente di HTML.it
    Registrato dal
    Sep 2011
    Messaggi
    8
    Mmm... intanto sto danto una occhiata alla programmazione in C.
    Si, il discorso mi torna perfettamente, grossomodo è quello che farei, se sapessi come farlo... sono abituato alla programmazione a basso livello (microcontrollori, al massimo plc) dove ho tutto in mano, e con linguaggi ad alto livello mi trovo più in difficoltà, non tanto per la programmazione stessa (quella è facile) quanto per l'accesso a risorse esterne e l'utilizzo di librerie pronte...

    Per l'algoritmo di analisi preferirei scrivermelo da me, lo ritengo più facile e più facilmente personalizzabile. Ovviamente so che è bene scriverlo in un linguaggio snello e veloce, purtroppo non so le differenze tra le varie istruzioni in termini di impiego della CPU. Non è come i microprocessori, dove nell'istruction set è specificato anche il tempo di esecuzione...

    Tornando al modo di leggere l'immagine, in pratica potrei trasferire l'immagine in un array, o qualcosa di simile... o no?

  6. #6
    Originariamente inviato da Bit79
    Tornando al modo di leggere l'immagine, in pratica potrei trasferire l'immagine in un array, o qualcosa di simile... o no?
    Sì, solo che non avendo mai lavorato con le API di cattura di Windows non ti so dare suggerimenti precisi.
    Amaro C++, il gusto pieno dell'undefined behavior.

  7. #7
    Utente di HTML.it
    Registrato dal
    Sep 2011
    Messaggi
    8
    Grazie... proseguirò la ricerca!

  8. #8
    Utente di HTML.it
    Registrato dal
    Sep 2011
    Messaggi
    8
    Salve a tutti... sono andato avanti con il lavoro.

    Poichè ho deciso di passare alla programmazione in C per questo progetto, riapro la discussione nell'apposita sezione...

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.