Vb.Net Check If Image Existing In Another Image

后端 未结 2 701
后悔当初
后悔当初 2020-12-19 10:58

I Tried To Check If Part Of Image Existing In Another Image

Explanation:


full image:
http://imageshack.us/photo/my-images/526/part

相关标签:
2条回答
  • 2020-12-19 11:30

    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.

    0 讨论(0)
  • 2020-12-19 11:38

    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
    
    0 讨论(0)
提交回复
热议问题