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:
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.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
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!

Rispondi quotando
