You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

快速定位大图中样本图坐标:VB.NET代码容差与性能优化需求

大尺寸图像中样本坐标快速定位的VB.NET代码优化需求

需求背景

需实现大尺寸图像中样本图像坐标的快速定位,目前基于VB.NET编写了两类代码,存在性能、匹配逻辑缺陷等问题,具体如下:


第一版代码(整数RGB值,无容差匹配)

Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
        Dim intMain() As Integer = GetRgbValues(picMain.Image)
        Dim intTemp() As Integer = GetRgbValues(picTemp.Image)
        Dim ArrTemp = SplitArrayBySpecifiedStep(intTemp, picTemp.Image.Width)
        Dim FirstLine As Integer() = ArrTemp(0)
        Dim IndexOfFirstRow As Integer() = GetIndexsBySpecifiedOrder(intMain, FirstLine)
        '目前这部分运行正常,但后续逻辑需验证
        Dim ArrMain = SplitArrayBySpecifiedStep(intMain, picMain.Image.Width)
        Dim Coordinates_X_Y As New List(Of Rectangle)
        For Each StartFind In IndexOfFirstRow
            Dim i = StartFind Mod picMain.Image.Width
            Dim t = StartFind \ picMain.Image.Width
            Dim isY As Integer = t
            Dim IsX As Integer = i
            Dim thisIsIt As Integer = 0
            For startCheck = 1 To ArrTemp.Length - 1
                t += 1
                Dim gg = ArrMain(t).Skip(i).Take(ArrTemp(startCheck).Length).Select(Function(h) h).ToArray
                If ArraysSimilarity(gg, ArrTemp(startCheck)) Then
                    thisIsIt += 1
                End If
            Next
            If thisIsIt = ArrTemp.Length - 1 Then
                Dim rec As New Rectangle(IsX, isY, picTemp.Image.Width, picTemp.Image.Height)
                Coordinates_X_Y.Add(rec)
            End If
        Next
        For Each Rec In Coordinates_X_Y
            Dim bt As New Bitmap(picMain.Image)
            Dim g As Graphics = Graphics.FromImage(bt)
            g.DrawRectangle(New Pen(Color.Red, 3), New Rectangle(Rec.X, Rec.Y, Rec.Width, Rec.Height))
            picMain.Image = bt
            g.Dispose()
            ListBox1.Items.Add(Rec.X & "," & Rec.Y)
        Next

    End Sub
    Function ArraysSimilarity(InArray As Integer(), Simiilar As Integer(), Optional tolerance As Integer = 10) As Boolean
        ArraysSimilarity = InArray.SequenceEqual(Simiilar)
    End Function
    Function SplitArrayBySpecifiedStep(InArray As Integer(), ByStep As Integer) As Integer()()
        SplitArrayBySpecifiedStep = InArray.Select(Function(num, index) New With {.num = num, .index = index}) _
             .GroupBy(Function(x) x.index \ ByStep) _
             .Select(Function(g) g.Select(Function(x) x.num).ToArray).ToArray
    End Function
    Function GetIndexsBySpecifiedOrder(inArray As Integer(), SpecifiedOrder As Integer()) As Integer()
        GetIndexsBySpecifiedOrder = inArray.Select(Function(value, index) index) _
                    .Where(Function(index) inArray(index) = SpecifiedOrder(0) AndAlso
                                          If(index + SpecifiedOrder.Length <= inArray.Length,
                                             Enumerable.SequenceEqual(inArray.Skip(index).Take(SpecifiedOrder.Length), SpecifiedOrder),
                                             False)) _
                    .ToArray()
    End Function
    Private Function GetRgbValues(inBitmap As Bitmap) As Integer()
        Dim recBitmap As New Rectangle(0, 0, inBitmap.Width, inBitmap.Height)
        Dim DataMain As System.Drawing.Imaging.BitmapData = inBitmap.LockBits(recBitmap, Drawing.Imaging.ImageLockMode.ReadWrite, Imaging.PixelFormat.Format32bppArgb)
        Dim ptr As IntPtr = DataMain.Scan0
        Dim bytes As Integer = Math.Abs(DataMain.Stride) * recBitmap.Height

        Dim rgbValues(bytes / 4 - 1) As Integer
        System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, rgbValues.Length)
        inBitmap.UnlockBits(DataMain)
        Return rgbValues
    End Function

第一版代码问题

  • 通过整数类型获取RGB值,无法实现带容差的颜色匹配,ArraysSimilarity函数仅做严格相等判断
  • 运行性能较差,无法满足快速定位需求

新版代码(字符串拼接匹配,仍有缺陷)

Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
    Dim pictureBoxMain As PictureBox = picMain
    Dim PictureBoxTemp As PictureBox = picTemp
    Dim intMain As String = GetRgbOfString(pictureBoxMain.Image)
    Dim intTemp() As String = GetArrRgbOfString(PictureBoxTemp.Image, PictureBoxTemp.Image.Width)
    Dim firstRowsRgb As New List(Of Integer)
    Dim Coordinates_X_Y As New List(Of Rectangle)
    Dim i As Integer = 0
    Dim FirstLine As String = intTemp(0)
    Do
        i = InStr(i + 1, intMain, FirstLine)
        If i = 0 Then
            Exit Do
        Else
            Dim XY() As Integer = FindOtherRows(i, intMain, pictureBoxMain.Image.Width, intTemp)
            If XY IsNot Nothing Then
                Dim rec As New Rectangle(XY(0), XY(1), PictureBoxTemp.Image.Width, PictureBoxTemp.Image.Height)
                Coordinates_X_Y.Add(rec)
            End If
        End If
    Loop
    For Each Rec In Coordinates_X_Y
        Dim bt As New Bitmap(pictureBoxMain.Image)
        Dim g As Graphics = Graphics.FromImage(bt)
        g.DrawRectangle(New Pen(Color.Red, 3), New Rectangle(Rec.X, Rec.Y, Rec.Width, Rec.Height))
        pictureBoxMain.Image = bt
        g.Dispose()
        ListBox1.Items.Add(Rec.X & "," & Rec.Y)
    Next
End Sub
Function FindOtherRows(start As Integer, InMain As String, WidthMain As Integer, RowsFind As String()) As Integer()
    '此处的核心匹配逻辑无法识别超过2行的内容
    '容差设置至关重要,烦请检查该部分
    Dim thisIsIt As Integer = 0
    Dim GetSeparator As Integer = InMain.Take(start).Count(Function(c) c = "|")
    For Row = 1 To RowsFind.Length - 1
        Dim Result3 As String = String.Join("|", InMain.Split("|").Skip(GetSeparator + WidthMain).Take(Split(RowsFind(Row), "|").Length))
        Dim stt6 As String = Result3 & vbNewLine & RowsFind(Row)
        If Result3 = RowsFind(Row) Then thisIsIt += 1 ' 此处需要添加容差逻辑
    Next
    If thisIsIt > 0 Then
        Return {(GetSeparator Mod WidthMain), (GetSeparator \ WidthMain)}
    Else
        Return Nothing
    End If
End Function
Private Function GetRgbOfString(inBitmap As Bitmap) As String
    Dim recBitmap As New Rectangle(0, 0, inBitmap.Width, inBitmap.Height)
    Dim DataMain As System.Drawing.Imaging.BitmapData = inBitmap.LockBits(recBitmap, Drawing.Imaging.ImageLockMode.ReadWrite, Imaging.PixelFormat.Format32bppArgb)
    Dim ptr As IntPtr = DataMain.Scan0
    Dim bytes As Integer = Math.Abs(DataMain.Stride) * recBitmap.Height
    Dim rgbValues(bytes / 4 - 1) As Integer
    System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, rgbValues.Length)
    inBitmap.UnlockBits(DataMain)
    '  Dim Resul As String = System.Text.Encoding.Default.GetString(rgbValues)
    GetRgbOfString = String.Join("|", rgbValues)
End Function
Private Function GetArrRgbOfString(inBitmap As Bitmap, SplitBy As Integer) As String()
    Dim recBitmap As New Rectangle(0, 0, inBitmap.Width, inBitmap.Height)
    Dim DataMain As System.Drawing.Imaging.BitmapData = inBitmap.LockBits(recBitmap, Drawing.Imaging.ImageLockMode.ReadWrite, Imaging.PixelFormat.Format32bppArgb)
    Dim ptr As IntPtr = DataMain.Scan0
    Dim bytes As Integer = Math.Abs(DataMain.Stride) * recBitmap.Height
    Dim rgbValues(bytes / 4 - 1) As Integer
    System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, rgbValues.Length)
    inBitmap.UnlockBits(DataMain)
    Return SplitArrayBySpecifiedStep(rgbValues, SplitBy)
End Function
Function SplitArrayBySpecifiedStep(InArray As Integer(), ByStep As Integer) As String()
    Dim Result = InArray.Select(Function(s, i) New With {s, i}).GroupBy(Function(x) x.i \ ByStep).Select(Function(g) String.Join("|", g.Select(Function(x) x.s))).ToArray
    Return Result
End Function

新版代码问题

  • 速度有所提升,可在10秒内定位1366×768像素大图中的4个目标,但仍需优化以达到最佳速度
  • FindOtherRows函数无法识别超过2行的样本图像,核心匹配逻辑存在缺陷
  • 未实现容差匹配,仅做字符串严格相等判断,需补充容差逻辑

内容的提问来源于stack exchange,提问作者Mansour Dalir

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 13:44:59