1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
|
'ajoute
'-1 button
'-1 picturebox pour image "merge avec la sous-image".
'-1 picturebox pour la sous-image originale
'-un label pour afficher le rectangle et ses coordonnees
'-les 2 images sont en resources
Imports System.Drawing.Imaging
Imports System.Runtime.InteropServices
Public Class Form1
Public Sub New()
' Cet appel est requis par le Concepteur Windows Form.
InitializeComponent()
' Ajoutez une initialisation quelconque après l'appel InitializeComponent().
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Me.PictureBox1.Image = My.Resources.BigWithSmall
Me.PictureBox2.Image = My.Resources.Small
Dim bigImage As Bitmap = Me.PictureBox1.Image
Dim smallImage As Bitmap = Me.PictureBox2.Image
Dim tolerance As Double = 0.2
Dim rect As Rectangle = searchBitmap(smallImage, bigImage, tolerance)
Me.LabelRect.Text = "Location: " & rect.X.ToString & " , " & rect.Y.ToString & vbCrLf
Me.LabelRect.Text = Me.LabelRect.Text & "WxH :" & rect.Width.ToString & " , " & rect.Height.ToString
End Sub
Private Function searchBitmap(ByVal smallBmp As Bitmap, ByVal bigBmp As Bitmap, ByVal tolerance As Double) As Rectangle
Dim smallData As BitmapData = smallBmp.LockBits(New Rectangle(0, 0, smallBmp.Width, smallBmp.Height), ImageLockMode.[ReadOnly], PixelFormat.Format24bppRgb)
Dim bigData As BitmapData = bigBmp.LockBits(New Rectangle(0, 0, bigBmp.Width, bigBmp.Height), ImageLockMode.[ReadOnly], PixelFormat.Format24bppRgb)
Dim smallStride As Integer = smallData.Stride
Dim bigStride As Integer = bigData.Stride
Dim bigWidth As Integer = bigBmp.Width
Dim bigHeight As Integer = bigBmp.Height - smallBmp.Height + 1
Dim smallWidth As Integer = smallBmp.Width * 3
Dim smallHeight As Integer = smallBmp.Height
Dim location As Rectangle = Rectangle.Empty
Dim margin As Integer = Convert.ToInt32(255.0 * tolerance)
'Dim pSmall As Pointer(Of Byte) = CType(CType(smallData.Scan0, Pointer(Of System.Void)), Pointer(Of Byte))
'Dim pBig As Pointer(Of Byte) = CType(CType(bigData.Scan0, Pointer(Of System.Void)), Pointer(Of Byte))
' Get the address of the first line.
Dim pSmall As IntPtr = smallData.Scan0
Dim pBig As IntPtr = bigData.Scan0
Dim smallOffset As Integer = smallStride - smallBmp.Width * 3
Dim bigOffset As Integer = bigStride - bigBmp.Width * 3
Dim matchFound As Boolean = True
'POUR LISIBILITE DU CODE
Dim currentByte As Byte
'INCREMENTATION DU POINTEUR -P-
'NECESSAIRE DE LE CONVERTIR EN ENTIER 32 BIT(INTEGER)
Dim incrementPtrBig As Int32 = 0
Dim incrementPtrpSmall As Int32 = 0
matchFound = True
Try
For y As Integer = 0 To bigHeight - 1
For x As Integer = 0 To bigWidth - 1
'Dim pBigBackup As Pointer(Of Byte) = pBig
'Dim pSmallBackup As Pointer(Of Byte) = pSmall
Dim pBigBackup As IntPtr = pBig
Dim pSmallBackup As IntPtr = pSmall
'Look for the small picture.
For i As Integer = 0 To smallHeight - 1
matchFound = True
For j As Integer = 0 To smallWidth - 1
'With tolerance: pSmall value should be between margins.
'Dim inf As Integer = pBig(0) - margin
'Dim sup As Integer = pBig(0) + margin
currentByte = Marshal.ReadByte(pBig, 0)
Dim inf As Integer = currentByte - margin
Dim sup As Integer = currentByte + margin
'If sup < pSmall(0) OrElse inf > pSmall(0) Then
' matchFound = False
' Exit For
'End If
If sup < Marshal.ReadByte(pSmall, 0) OrElse inf > Marshal.ReadByte(pSmall, 0) Then
matchFound = False
Exit For
End If
'pBig += 1
'IntPtr est converti en integer avant d'etre incrementer de 1
'car IntPtr ne supporte les operations arithmetiques
'& Caste en IntPtr
incrementPtrBig = pBig.ToInt32
incrementPtrBig = incrementPtrBig + 1
pBig = CType(incrementPtrBig, IntPtr)
'pSmall += 1
'idem
incrementPtrpSmall = pSmall.ToInt32
incrementPtrpSmall = incrementPtrpSmall + 1
pSmall = CType(incrementPtrpSmall, IntPtr)
Next
If Not matchFound Then
Exit For
End If
'We restore the pointers.
pSmall = pSmallBackup
pBig = pBigBackup
'Next rows of the small and big pictures.
'increment est egal cette fois =>smallStride * (1 + i)
'pSmall += smallStride * (1 + i)
incrementPtrpSmall = pSmall.ToInt32
incrementPtrpSmall = incrementPtrpSmall + smallStride * (1 + i)
pSmall = CType(incrementPtrpSmall, IntPtr)
'pBig += bigStride * (1 + i)
incrementPtrBig = pBig.ToInt32
incrementPtrBig = incrementPtrBig + bigStride * (1 + i)
pBig = CType(incrementPtrBig, IntPtr)
Next
'If match found, we return.
If matchFound Then
location.X = x
location.Y = y
location.Width = smallBmp.Width
location.Height = smallBmp.Height
Exit For
Else
'If no match found, we restore the pointers and continue.
pBig = pBigBackup
pSmall = pSmallBackup
'pBig += 3
'increment est egal cette fois =>3
incrementPtrBig = pBig.ToInt32
incrementPtrBig = incrementPtrBig + 3
pBig = CType(incrementPtrBig, IntPtr)
End If
Next
If matchFound Then
Exit For
End If
'pBig += bigOffset
incrementPtrBig = pBig.ToInt32
incrementPtrBig = incrementPtrBig + bigOffset
pBig = CType(incrementPtrBig, IntPtr)
Next
Catch ex As AccessViolationException
MessageBox.Show(ex.Message & ex.Source & ex.StackTrace)
End Try
bigBmp.UnlockBits(bigData)
smallBmp.UnlockBits(smallData)
Return location
End Function
End Class |