Vb.Net 2015 - проблема с хранением байтового массива и сравнениями с использованием lockbits/marshal.copy

Я новичок здесь, так что извините, если мой вопрос не в надлежащем формате, чтобы дать ответ. Пожалуйста, дайте мне знать, если мне нужно что-то добавить:

В настоящее время я работаю над проектом из дома для помощника в компании, которая использует действительно старую унаследованную систему, которая отображает вывод на экран. Система, которая у них есть, устарела и больше не поддерживается (компания, которая ее установила, больше не работает). Мне сказали, что им нужно хранить систему для ежемесячных отчетов, но они хотят отображать ее результаты более современным способом, чтобы, когда люди приходят, они могли видеть, что происходит без смущения. Трудно объяснить, но в основном меня просили захватывать информацию с экрана и выводить ее на другой.

Я проработал примерно 3/4 образца, написанного на VB.Net... и обнаружил, что сравнение изображений слишком медленное для изменений, происходящих с использованием getpixel для сравнения. Скорость также была проблемой при сохранении изображений в поток памяти для сравнения (проходя через x,y в поисках совпадения)... поэтому я переключился на копирование блокировок / маршалов в байтовые массивы для сравнения. В основном - данные, отображаемые в нескольких областях, всегда соответствуют одному из примерно 20 изображений, которые я сохранил. Я могу сравнивать изображения, используя снимки и сохраненные изображения (поместите diff поверх существующего сохраненного изображения, и результат будет затемнен на 100%). Я знаю, что мои сохраненные изображения соответствуют 100%, а предыдущие методы сравнения из g.fromimage полностью совпадают, но методы, которые я использовал, слишком медленные. Теперь, когда я использую байтовые массивы, я видел много несоответствий и обнаружил, что байтовые массивы изменяются случайным образом при извлечении из одних и тех же изображений (изображение загружается для сравнения и сохраняется в массиве... изображение на экране сохраняются в массиве, и сохраняются в текст, и больше ничего не делается снова и снова, что приводит к различиям.).

Открыв новый проект, я воспроизвел этот вопрос. Загрузка изображения в поле рисунка при запуске / без изменений на всем протяжении - g.copyfromscreen в растровое изображение, а затем сохраняется в байтовом массиве и экспортируется в текстовый файл, когда выполняется снова и снова. Я не могу понять, почему это происходит. Как будто я случайно обнаружил генератор случайных чисел, ха-ха. Области, которые я сравниваю, 5х72, поэтому не массивны. Прямо сейчас, чтобы упростить, я загружаю изображение в pixturebox и нажимаю кнопку, чтобы сохранить данные из этого изображения в байтовом массиве. Затем я сохраняю область изображения в.png и преобразовываю текст байтового массива из той же области в текстовый файл. Нажатие кнопки снова и снова приводит к разным байтовым массивам для вывода текста, но к файлам png, которые соответствуют 100%. Я не перемещаю изображение, я не перезагружаю изображение... Я не понимаю, почему байтовые массивы меняются.

Module Module1

Public baGB1Small((5 * 72 - 1) * 3) As Byte ' To be populated with small image.
Public baGB2Small((5 * 72 - 1) * 3) As Byte ' To be populated with small image.
Public baGB3Small((5 * 72 - 1) * 3) As Byte ' To be populated with small image.
Public baGB4Small((5 * 72 - 1) * 3) As Byte ' To be populated with small image.    

End Module

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

Dim filename As String = DateTime.Now.ToString("yyyy_MM_dd_HH_mm_ss_fff")    

'-- Below saves a chunk of the screen with the picturebox in it for comparison.

Dim BMPScrNew As New Bitmap(5, 420, Imaging.PixelFormat.Format24bppRgb)
Dim GrabRect As New Rectangle(478, 170, 5, 420)
Using g As Graphics = Graphics.FromImage(BMPScrNew)
    g.CopyFromScreen(GrabRect.Location, New Point(0, 0), GrabRect.Size)
End Using

BMPScrNew.Save("C:\TestSaveLoc\SCR1-" & filename & ".png", Imaging.ImageFormat.Png)

'-- Below breaks the main saved image into chunks for comparison.
'-- Chunk 1:
Dim BMPSN As New Bitmap(5, 72)
Dim GRNew As New Rectangle(0, 7, 5, 72)
BMPSN = BMPScrNew.Clone(GRNew, Imaging.PixelFormat.Format24bppRgb)
BMPSN.Save("C:\TestSaveLoc\B1-" & filename & ".png", Imaging.ImageFormat.Png)
Dim BMD As Imaging.BitmapData = BMPSN.LockBits(New Rectangle(0, 0, BMPSN.Width, BMPSN.Height), Imaging.ImageLockMode.ReadOnly, Imaging.PixelFormat.Format24bppRgb)
Runtime.InteropServices.Marshal.Copy(BMD.Scan0, baGB1Small, 0, baGB1Small.Length)
BMPSN.UnlockBits(BMD)

'-- Chunk 2:
BMPSN = New Bitmap(5, 72)
GRNew = New Rectangle(0, 89, 5, 72)
BMPSN = BMPScrNew.Clone(GRNew, Imaging.PixelFormat.Format24bppRgb)
BMPSN.Save("C:\TestSaveLoc\B2-" & filename & ".png", Imaging.ImageFormat.Png)
BMD = BMPSN.LockBits(New Rectangle(0, 0, BMPSN.Width, BMPSN.Height), Imaging.ImageLockMode.ReadOnly, Imaging.PixelFormat.Format24bppRgb)
Runtime.InteropServices.Marshal.Copy(BMD.Scan0, baGB2Small, 0, baGB2Small.Length)
BMPSN.UnlockBits(BMD)

'-- Chunk 3:
BMPSN = New Bitmap(5, 72)
GRNew = New Rectangle(0, 171, 5, 72)
BMPSN = BMPScrNew.Clone(GRNew, Imaging.PixelFormat.Format24bppRgb)
BMPSN.Save("C:\TestSaveLoc\B3-" & filename & ".png", Imaging.ImageFormat.Png)
BMD = BMPSN.LockBits(New Rectangle(0, 0, BMPSN.Width, BMPSN.Height), Imaging.ImageLockMode.ReadOnly, Imaging.PixelFormat.Format24bppRgb)
Runtime.InteropServices.Marshal.Copy(BMD.Scan0, baGB3Small, 0, baGB3Small.Length)
BMPSN.UnlockBits(BMD)

'-- Chunk 4:
BMPSN = New Bitmap(5, 72)
GRNew = New Rectangle(0, 253, 5, 72)
BMPSN = BMPScrNew.Clone(GRNew, Imaging.PixelFormat.Format24bppRgb)
BMPSN.Save("C:\SWAutoer\TestSaveLoc\B4-" & filename & ".png", Imaging.ImageFormat.Png)
BMD = BMPSN.LockBits(New Rectangle(0, 0, BMPSN.Width, BMPSN.Height), Imaging.ImageLockMode.ReadOnly, Imaging.PixelFormat.Format24bppRgb)
Runtime.InteropServices.Marshal.Copy(BMD.Scan0, baGB4Small, 0, baGB4Small.Length)
BMPSN.UnlockBits(BMD)

BMPSN.Dispose()
BMPScrNew.Dispose()

'-- Writes output to a textbox on the screen (for testing only)
Output1.AppendText(Environment.NewLine & DateTime.Now)
Output1.AppendText(Environment.NewLine & "FirstCheck:" & CDWB3(filename))

filename = Nothing

End Sub

Public Function CDWB3(vfpath As String) As String

Dim BMPScrNew As New Bitmap(5, 420, Imaging.PixelFormat.Format24bppRgb)
Dim GrabRect As New Rectangle(478, 170, 5, 420)
Using g As Graphics = Graphics.FromImage(BMPScrNew)
    g.CopyFromScreen(GrabRect.Location, New Point(0, 0), GrabRect.Size)
End Using
BMPScrNew.Save("C:\TestSaveLoc\SCR2-" & vfpath & ".png", Imaging.ImageFormat.Png)

Dim WasFound As Integer = 0
Dim FoundAtY As Integer = 0

Dim Checkst As Stopwatch = Stopwatch.StartNew
Dim StoppedAt As Integer = 169

For vNewY = 0 To 348 ' Goes down one pixel through the main scraped image to compare a chunk that is 5x72 to the saved arrays of smaller chunks.

    Dim BMPSN As New Bitmap(5, 72)
    Dim GRNew As New Rectangle(0, vNewY, 5, 72)
    BMPSN = BMPScrNew.Clone(GRNew, Imaging.PixelFormat.Format24bppRgb)
    BMPSN.Save("C:\TestSaveLoc\B1Loc-" & vfpath & ".png", Imaging.ImageFormat.Png)

    Dim BMD As Imaging.BitmapData = BMPSN.LockBits(New Rectangle(0, 0, BMPSN.Width, BMPSN.Height), Imaging.ImageLockMode.ReadOnly, Imaging.PixelFormat.Format24bppRgb)
    Dim vmBuffer((BMPSN.Width * BMPSN.Height - 1) * 3) As Byte
    Marshal.Copy(BMD.Scan0, vmBuffer, 0, vmBuffer.Length)
    BMPSN.UnlockBits(BMD)

    If vNewY = 7 Then '-- THIS IS WHERE bagb1small should always match.

        Dim writer1 As New IO.StreamWriter("C:\TestSaveLoc\MainBuff-" & vfpath & ".txt")
        writer1.WriteLine(Convert.ToBase64String(vmBuffer))
        writer1.Flush()
        writer1.Close()
        writer1.Dispose()

        Dim writer2 As New IO.StreamWriter("C:\TestSaveLoc\bagb1small-" & vfpath & ".txt")
        writer2.WriteLine(Convert.ToBase64String(bagb1small))
        writer2.Flush()
        writer2.Close()
        writer2.Dispose()

    End If

    StoppedAt = StoppedAt + 1
    Dim B1Found As Boolean = True
    Dim B2Found As Boolean = True
    Dim B3Found As Boolean = True
    Dim B4Found As Boolean = True

    For i = 0 To vmBuffer.Length - 1 Step 3
        Dim BadCount As Integer = 0

        If vmBuffer(i) <> baGB1Small(i) Then
            B1Found = False
            BadCount += 1
        End If
        If vmBuffer(i) <> baGB2Small(i) Then
            B2Found = False
            BadCount += 1
        End If
        If vmBuffer(i) <> baGB3Small(i) Then
            B3Found = False
            BadCount += 1
        End If
        If vmBuffer(i) <> baGB4Small(i) Then
            B4Found = False
            BadCount += 1
        End If

        If BadCount > 3 Then Exit For
    Next

    BMD = Nothing
    vmBuffer = Nothing

    If B1Found = True Then
        WasFound = 1
        Exit For
    End If
    If B2Found = True Then
        WasFound = 2
        Exit For
    End If
    If B3Found = True Then
        WasFound = 3
        Exit For
    End If
    If B4Found = True Then
        WasFound = 4
        Exit For
    End If

    BMPSN.Dispose()

Next

BMPScrNew.Dispose()

Checkst.Stop()
CDWB3 = WasFound.ToString & "," & StoppedAt

End Function

С помощью приведенного выше кода изображение загружается в поле для картинок в заданной позиции на экране в событии загрузки формы. Я ожидаю, что нажатие кнопки будет выдавать один и тот же вывод каждый раз (байтовый массив соответствует байтовому массиву последнего клика), поскольку изображение на экране вообще не меняется. Это не вариант.

Выводы моего изображения (файл сохраняется в png) совпадают каждый раз, когда я нажимаю кнопку. Вывод байтового массива в текст не совпадает. Блок 1 иногда обнаруживается, блок 2-4 - другой (блок 1 не виден на экране), а иногда его вообще нет... Это статическое изображение на экране, с которого я копирую и сравниваю - это должно не будет дела. Блок 1 должен всегда находиться в одной и той же позиции каждый раз, а массивы байтов должны быть одинаковыми каждый раз.

0 ответов

Другие вопросы по тегам