Vb.Net Check If Image Existing In Another Image

空扰寡人 提交于 2019-12-18 06:49:39

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!