问题
I Tried To Check If Part Of Image Existing In Another Image
Explanation:
full image:
http://imageshack.us/photo/my-images/526/part1g.png/
second part of image that i want to check if he existing in the full image:
http://imageshack.us/photo/my-images/706/part2p.png/
if the second part is Exist then the function return true
there is a function that can check if it exist?
(if it was only Single pixel then it was verey easy, but i want to check if Part Of Image Existing In Another Image)
there is a code that works , but it check if Single pixel exist in image:
Dim bmp As Bitmap = PictureBox1.Image
For x As Integer = 0 To bmp.Width - 1
For y As Integer = 0 To bmp.Height - 1
If bmp.GetPixel(x, y) = Color.FromArgb(48, 48, 48) Then
msgbox("Pixel Exist In Image!!!")
End If
Next
Next
回答1:
I wrote this extension to find an image within an image. It has a couple of limitations though: 1) The images must be saved without color-space (or the same ones anyways) and 2) It will not work with lossy-compressed images (ie. jpeg, for that you need averaging and tolerance implementation).
I have optimized the pixel matching routine. It's not fully debugged, but seem to work as expected. It ignores the alpha-channel (on purpose, extend as needed) and you need to try-catch on your caller (ie. out-of-memory exception).
Usage:
Dim p As Point = yourBitmap.Contains(bmpYouLookFor)
If p <> Nothing Then
'...
End If
The code: If you don't want to have it as an extension (which requires .net 3.5+) just remove the extension attribute and call it as an ordinary function with your source bitmap as an argument instead.
Copy and paste the following into a module (license: CC-attribution):
'*******************************************************************************
'*
'* Epistemex
'*
'* Bitmap extension: .Contains(bmp)
'* KF
'*
'* 2012-09-26 Initial version
'* 2012-09-26 Minor optimization, exit for's impl.
'*
'*******************************************************************************
Imports System.Drawing
Imports System.Runtime.CompilerServices
Imports System.Drawing.Imaging
Imports System.Runtime.InteropServices
Module BitmapExtension
<Extension()>
Public Function Contains(src As Bitmap, ByRef bmp As Bitmap) As Point
'
'-- Some logic pre-checks
'
If src Is Nothing OrElse bmp Is Nothing Then Return Nothing
If src.Width = bmp.Width AndAlso src.Height = bmp.Height Then
If src.GetPixel(0, 0) = bmp.GetPixel(0, 0) Then
Return New Point(0, 0)
Else
Return Nothing
End If
ElseIf src.Width < bmp.Width OrElse src.Height < bmp.Height Then
Return Nothing
End If
'
'-- Prepare optimizations
'
Dim sr As New Rectangle(0, 0, src.Width, src.Height)
Dim br As New Rectangle(0, 0, bmp.Width, bmp.Height)
Dim srcLock As BitmapData = src.LockBits(sr, Imaging.ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb)
Dim bmpLock As BitmapData = bmp.LockBits(br, Imaging.ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb)
Dim sStride As Integer = srcLock.Stride
Dim bStride As Integer = bmpLock.Stride
Dim srcSz As Integer = sStride * src.Height
Dim bmpSz As Integer = bStride * bmp.Height
Dim srcBuff(srcSz) As Byte
Dim bmpBuff(bmpSz) As Byte
Marshal.Copy(srcLock.Scan0, srcBuff, 0, srcSz)
Marshal.Copy(bmpLock.Scan0, bmpBuff, 0, bmpSz)
' we don't need to lock the image anymore as we have a local copy
bmp.UnlockBits(bmpLock)
src.UnlockBits(srcLock)
Dim x, y, x2, y2, sx, sy, bx, by, sw, sh, bw, bh As Integer
Dim r, g, b As Byte
Dim p As Point = Nothing
bw = bmp.Width
bh = bmp.Height
sw = src.Width - bw ' limit scan to only what we need. the extra corner
sh = src.Height - bh ' point we need is taken care of in the loop itself.
bx = 0 : by = 0
'
'-- Scan source for bitmap
'
For y = 0 To sh
sy = y * sStride
For x = 0 To sw
sx = sy + x * 3
'
'-- Find start point/pixel
'
r = srcBuff(sx + 2)
g = srcBuff(sx + 1)
b = srcBuff(sx)
If r = bmpBuff(2) AndAlso g = bmpBuff(1) AndAlso b = bmpBuff(0) Then
p = New Point(x, y)
'
'-- We have a pixel match, check the region
'
For y2 = 0 To bh - 1
by = y2 * bStride
For x2 = 0 To bw - 1
bx = by + x2 * 3
sy = (y + y2) * sStride
sx = sy + (x + x2) * 3
r = srcBuff(sx + 2)
g = srcBuff(sx + 1)
b = srcBuff(sx)
If Not (r = bmpBuff(bx + 2) AndAlso
g = bmpBuff(bx + 1) AndAlso
b = bmpBuff(bx)) Then
'
'-- Not matching, continue checking
'
p = Nothing
sy = y * sStride
Exit For
End If
Next
If p = Nothing Then Exit For
Next
End If 'end of region check
If p <> Nothing Then Exit For
Next
If p <> Nothing Then Exit For
Next
bmpBuff = Nothing
srcBuff = Nothing
Return p
End Function
End Module
回答2:
You could just write a function to loop through every possible upper-left corner pixel of the second image, then copy the pixels out to another bitmap object, then compare the new bitmap object to your second image pixel for pixel.
So first you would loop through pixels at
- x < mainImageWidth - subImageWidth
- y < mainImageHeight - subImageHeight
If the pixel at (x, y) in the main image has the same colour value as the pixel at (0, 0) in the sub-image, copy out the area starting from (x, y) with the same dimensions as your sub-image from your main image to a new Bitmap object using a function like this one - http://msdn.microsoft.com/en-us/library/aa457087.aspx
Then just loop through the pixels in the new object and your sub-image, comparing colours at the same coordinates as you go. Break the loop if you encounter a difference. If you get to the end of this loop, you have a match and can return True, otherwise continue looping through the pixels of the main image until you hit a point where it's impossible for the sub-image to fit any more, then return False.
来源:https://stackoverflow.com/questions/10899828/vb-net-check-if-image-existing-in-another-image