c# - 在更大的位图中查找位图(Pixel bot)-如何使其/for循环更快?

标签 c# bitmap pixel bots

所以这个函数是在更大的位图中找到一个位图..buuuut..它需要 4-6 秒才能通过 1920x1080 屏幕.. 我不会问你我是否 100% 理解该代码,我不知道,我是编程的新手,我的逻辑已经有点睡着了(凌晨 4:00)..(代码来自视频教程,我是甚至没有研究它就使用了很长时间 :D)

所以我真正想要的是让机器人在游戏中寻找像素/图片然后点击它,但是 4-6 秒太长了,不是吗?我对此很好奇,因为用其他编程语言制作的几款游戏的像素机器人非常非常快!比如1s... 所以我想,它是由 c# 引起的吗?它可能不是由 c# 引起的 .. 但这段代码很有效,但也许不需要那么长? 我考虑过“获得更快的循环”.. 但那可能不会发生。

尝试发明一些解决方案,我将不胜感激!而且我仍然认为这个问题对于其他许多人来说可能很重要。

private bool FindBitmap(Bitmap bmpNeedle, Bitmap bmpHaystack, out Point location)
{
    for (int outerX = 0; outerX < bmpHaystack.Width - bmpNeedle.Width; outerX++)
    {
        for (int outerY = 0; outerY < bmpHaystack.Height - bmpNeedle.Height; outerY++)
        {
            for (int innerX = 0; innerX < bmpNeedle.Width; innerX++)
            {
                for (int innerY = 0; innerY < bmpNeedle.Height; innerY++)
                {
                    Color cNeedle = bmpNeedle.GetPixel(innerX, innerY);
                    Color cHaystack = bmpHaystack.GetPixel(innerX + outerX, innerY + outerY);

                    if (cNeedle.R != cHaystack.R || cNeedle.G != cHaystack.G || cNeedle.B != cHaystack.B)
                    {
                        goto notFound;
                    }
                }
            }
            location = new Point(outerX, outerY);
            return true;

        notFound:
            continue;
        }
    }
    location = Point.Empty;
    return false;
}    

最佳答案

我使用LockBits不安全 代码为其编写了一个小类。 表现很棒。 我决定使用 uint 值而不是颜色。 对于转换,您可以使用 http://www.vcskicks.com/color-uint.php

/// <summary>
///     Represents a bitmap with bit functions.
/// </summary>
public class LockedBitmap
{
private Rectangle _bounds;

/// <summary>
///     Gets or sets the bitmap.
/// </summary>
public Bitmap Bitmap { get; set; }

/// <summary>
///     Gets or sets the values of the bitmap.
/// </summary>
/// <remarks>Watch at the static length!</remarks>
public uint[] Buffer { get; set; }

/// <summary>
///     Gets or sets the bitmap data.
/// </summary>
public BitmapData BitmapData { get; set; }

/// <summary>
///     Initializes a new instance of <see cref="LockedBitmap" />.
/// </summary>
/// <param name="bitmap">The processed bitmap.</param>
public LockedBitmap(Bitmap bitmap)
{
    this.Bitmap = bitmap;
}

/// <summary>
///     Locks a Bitmap into system memory.
/// </summary>
public unsafe void LockBits()
{
    var width = this.Bitmap.Width;
    var height = this.Bitmap.Height;

    var imageLockMode = ImageLockMode.UserInputBuffer;

    // Setting imageLockMode
    imageLockMode = imageLockMode | ImageLockMode.ReadOnly;
    imageLockMode = imageLockMode | ImageLockMode.WriteOnly;

    // Save the bouunds
    this._bounds = new Rectangle(0, 0, width, height);

    // Create Pointer
    var someBuffer = new uint[width*height];
    // Pin someBuffer
    fixed (uint* buffer = someBuffer) //pin
    {
        // Create new bitmap data.
        var temporaryData = new BitmapData
        {
            Width = width,
            Height = height,
            PixelFormat = PixelFormat.Format32bppArgb,
            Stride = width*4,
            Scan0 = (IntPtr) buffer
        };

        // Get the data
        this.BitmapData = this.Bitmap.LockBits(this._bounds, imageLockMode, PixelFormat.Format32bppArgb,
            temporaryData);
        // Set values
        this.Buffer = someBuffer;
    }
}

/// <summary>
///     Unlocks this Bitmap from system memory.
/// </summary>
public void UnlockBits()
{
    this.Bitmap.UnlockBits(this.BitmapData);
}

/// <summary>
///     Iterate through all pixel values.
/// </summary>
public unsafe void Iterate()
{
    // Dimension
    var width = this.Bitmap.Width;
    var height = this.Bitmap.Height;
    // Actual uint position
    int cp = 0;
    // Pointer at the fist uint
    var scp = (uint*)this.BitmapData.Scan0;
    // Stick the array
    fixed (uint* cb = this.Buffer)

        // Step through each pixel
        for (uint* cbp = cb, cbdest = cb + this.Buffer.Length; cbp < cbdest; cbp++)
        {
            // Get x and y from position
            var x = cp % width;
            var y = cp / width;

            var color = *cbp;

            cp++;  // Increment cp
        }
}
}

示例用法:

using (OpenFileDialog ofd = new OpenFileDialog())
{
    if (ofd.ShowDialog() == DialogResult.OK)
    {
        Image image = Image.FromFile(ofd.FileName);
        LockedBitmap locked = new LockedBitmap((Bitmap) image);
        locked.LockBits();
        locked.Iterate();
        locked.UnlockBits();
    }
}

color 现在具有像素颜色的值。 cp 是绝对位置 (1D) 和 (x|y) 点在位图中的位置 (2D)

关于c# - 在更大的位图中查找位图(Pixel bot)-如何使其/for循环更快?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25467926/

相关文章:

android - 如何使用 Libgdx 获取整个屏幕的位图?

c++ - 从图像中获取不正确的读数

c# - 如何在 C# (mono) 中使用 Gdk# 库?

c# - 在 C# .NET 中加载第一个连接的时间很长

java - 我如何在android中将位图转换为PDF格式

image - MATLAB 如何将轴坐标转换为像素坐标?

css - 在其父项内自由移动文本

c# - SyndicationFeed 将 namespace 前缀从 a10 更改为 atom

c# - 知道某个条目位于数据库中

wpf - 有没有办法在存储在内存中的 WPF 中显示图像?