在更大的位图中查找位图(Pixel bot) -如何使它/for循环更快
本文关键字:位图 何使它 for 循环 Pixel 查找 bot | 更新日期: 2023-09-27 18:19:16
所以这个函数在更大的位图中找到一个位图。buuuut . .通过1920x1080的屏幕需要4-6秒。我不会问你我是否100%理解这些代码,我没有,我是一个编程新手,我的逻辑已经有点睡着了(凌晨4点)。(代码来自视频教程,我使用了很长时间,甚至没有研究它:D)
所以我真正想要的是让机器人在游戏中找到像素/图片,然后点击它,但4-6秒很长,不是吗?我对此非常好奇,因为用其他编程语言制作的一些游戏的像素机器人非常非常快!像1 s…所以我想,这是由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和不安全的代码为它写了一个小类。表演很棒。我决定使用单位值而不是颜色。要转换,可以使用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)中的点位置