PixelSearch в определенной области монитора

Итак, я пытаюсь найти определенный шаблон в середине экрана в данной области. Я использую библиотеку AutoItX и метод PixelSearch.

  • Прямоугольник X: 1980
  • Прямоугольник Y: 630
  • Размер прямоугольника X: 1240
  • Размер прямоугольника Y: 180

Он не возвращает, что шаблон найден, но если я отрегулирую шнуры прямоугольника на 0, 0, это покажет, что шаблон найден.

Следующий script используется:

  public void MonsterScan()
  {
    if(SixStarMax() == true)
    {
        Console.WriteLine("Pattern found");
    }
  }

  public bool SixStarMax()
  {
    Rectangle rect = new Rectangle(1980, 630, 1240, 180);
    autoSumPoint = AutoItX.PixelSearch(rect, 0xF8F0E0); // 0xF8F0E0
    autoSumPoint2 = AutoItX.PixelSearch(rect, 0xB7AD9F); // 0xB7AD9F
    autoSumPoint3 = AutoItX.PixelSearch(rect, 0xCDC6B8); // 0xCDC6B8
    autoSumPoint4 = AutoItX.PixelSearch(rect, 0x949084); // 0x949084

    if (rect.Contains(autoSumPoint2) == true && rect.Contains(autoSumPoint2) == true && rect.Contains(autoSumPoint3) == true && rect.Contains(autoSumPoint4) == true)
    {
      AutoItX.MouseMove(autoSumPoint.X, autoSumPoint.Y);
      return true;
    }
    else
    {
      return false;
    }
  }

Edit:

Попробовал отрегулировать шнуры на моем первом экране, и я получаю сообщение об ошибке.

System.AccessViolationException: 'An attempt was made to read or write to protected memory. This often indicates that other memory is damaged. '

Ответ 2

Вы можете закодировать его без какой-либо внешней библиотеки и быть очень быстрым, читая байты внутри. Не забудьте включить System.Drawing.Imaging и System.Linq в операторы using и скомпилировать его с опцией "Unsafe" в параметрах Project.

public bool SixStarMax()
{
    Rectangle rect = new Rectangle(1980, 630, 1240, 180);

    Bitmap bitmapToScan = GetScreenPart(rect);

    Point?[] autoSumPoints = new Point?[4];

    autoSumPoints[0] = SearchForColor(bitmapToScan, 0xF8F0E0);
    autoSumPoints[1] = SearchForColor(bitmapToScan, 0xB7AD9F);
    autoSumPoints[2] = SearchForColor(bitmapToScan, 0xCDC6B8);
    autoSumPoints[3] = SearchForColor(bitmapToScan, 0x949084);

    //return true if all points return a value
    bool containsAll = autoSumPoints.All(p => p.HasValue);

    if (containsAll) Cursor.Position = autoSumPoints[0].Value;
    return containsAll;
}

public Bitmap GetScreenPart(Rectangle rect)
{
    //initialize bitmap
    Bitmap bmp = new Bitmap(rect.Width, rect.Height, PixelFormat.Format32bppArgb);

    //fill bitmap
    using (Graphics g = Graphics.FromImage(bmp))
        g.CopyFromScreen(new Point(rect.Left, rect.Top), new Point(rect.Right, rect.Bottom), rect.Size);

    return bmp;
}

public Point? SearchForColor(Bitmap image, uint color)
{
    Rectangle rect = new Rectangle(0, 0, image.Width, image.Height);

    BitmapData data = image.LockBits(rect, ImageLockMode.ReadOnly, PixelFormat.Format32bppRgb);

    //works for 32-bit pixel format only
    int ymin = rect.Top, ymax = Math.Min(rect.Bottom, image.Height);
    int xmin = rect.Left, xmax = Math.Max(rect.Right, image.Width) - 1;

    int strideInPixels = data.Stride / 4; //4 bytes per pixel
    unsafe
    {
        uint* dataPointer = (uint*)data.Scan0;
        for (int y = ymin; y < ymax; y++)
            for (int x = xmin; x < xmax; x++)
            {
                //works independently of the data.Stride sign
                uint* pixelPointer = dataPointer + y * strideInPixels + x;
                uint pixel = *pixelPointer;
                bool found = pixel == color;
                if (found)
                {

                    image.UnlockBits(data);
                    return new Point(x, y);

                }
            }
    }
    image.UnlockBits(data);
    return null;
}