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 è: