5

画像の一部が別の画像に存在するかどうかを確認しようとしました

説明:


完全な画像:
http://imageshack.us/photo/my-images/526/part1g.png/

彼が完全な画像に存在するかどうかを確認したい画像の2番目の部分:
http://imageshack.us/photo/my-images/706/part2p.png/

2番目の部分が存在する場合、関数
はtrueを返します存在するかどうかを確認できる機能はありますか?


(単一ピクセルのみの場合は非常に簡単でしたが、別の画像に画像の一部が存在するかどうかを確認したい)
動作するコードがありますが、画像に単一ピクセルが存在するかどうかを確認します

    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
4

2 に答える 2

3

この拡張機能を作成して、画像内の画像を見つけました。ただし、いくつかの制限があります。1) 画像は色空間なしで (またはとにかく同じもの) 保存する必要があり、2) 非可逆圧縮された画像 (つまり、jpeg、そのためには平均化と許容値が必要です) では機能しません。実装)。

ピクセル マッチング ルーチンを最適化しました。完全にはデバッグされていませんが、期待どおりに動作しているようです。アルファチャンネルを無視し(意図的に、必要に応じて拡張します)、呼び出し元をtry-catchする必要があります(つまり、メモリ不足の例外)。

使用法:

Dim p As Point = yourBitmap.Contains(bmpYouLookFor)
If p <> Nothing Then
'...
End If

コード: 拡張子 (.net 3.5 以降が必要) として使用したくない場合は、拡張子属性を削除し、代わりにソース ビットマップを引数として通常の関数として呼び出します。

以下をコピーしてモジュールに貼り付けます (ライセンス: 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
于 2012-09-26T16:26:28.680 に答える
0

2 番目の画像のすべての可能な左上隅のピクセルをループする関数を作成し、そのピクセルを別のビットマップ オブジェクトにコピーしてから、新しいビットマップ オブジェクトを 2 番目の画像ピクセルと比較するだけです。

したがって、最初にピクセルをループします

  • x < mainImageWidth - subImageWidth
  • y < mainImageHeight - subImageHeight

メイン画像の (x, y) のピクセルがサブ画像の (0, 0) のピクセルと同じカラー値を持つ場合は、(x, y) から始まる領域を同じ寸法でコピーします。このような関数を使用して、メイン イメージから新しい Bitmap オブジェクトへのサブイメージ - http://msdn.microsoft.com/en-us/library/aa457087.aspx

次に、新しいオブジェクトとサブイメージのピクセルをループして、同じ座標で色を比較します。違いが発生した場合は、ループを中断します。このループの最後に到達すると、一致があり、True を返すことができます。それ以外の場合は、サブイメージが収まりきらないポイントに到達するまでメイン イメージのピクセルをループし続け、False を返します。 .

于 2012-06-19T09:32:31.573 に答える