我一直在研究一个基本上运行位图截图图像的小应用程序。然后位图检测到我加载的Resources.GrabPixel .bmp中的某个像素。当涉及许多类似的像素时,这种方法在某些方面似乎不可靠。
如果我要在BlueStacks或Andy Emulator中使用它,那么返回可能是错误的。我曾经有过这样的实例,它会检测到一个游戏图标,但由于一些奇怪的原因,几天后它会随机停止检测到同一个图标。
那么我应该学习更多的方法和方法吗?我不是C#的专家,我可以尝试和构建的任何示例都很棒。如果有人认为可以通过任何方式改进,我会在下面列出我的代码。
目标:检测某些像素,同时丢弃不匹配的像素。更准确的像素阅读器。
下面列出的代码包含bitmap和mouse_events。
public partial class frmMain : Form
{
private const UInt32 MOUSEEVENTF_LEFTDOWN = 0x0002;
private const UInt32 MOUSEEVENTF_LEFTUP = 0x0004;
[DllImport("user32.dll", EntryPoint = "SetCursorPos")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetCursorPos([In] int X, [In] int Y);
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint dwData,
int dwExtraInfo);
public enum MouseEventFlags : uint
{
LEFTDOWN = 0x00000002,
LEFTUP = 0x00000004,
MIDDLEDOWN = 0x00000020,
MIDDLEUP = 0x00000040,
MOVE = 0x00000001,
ABSOLUTE = 0x00008000,
RIGHTDOWN = 0x00000008,
RIGHTUP = 0x00000010,
WHEEL = 0x00000800,
XDOWN = 0x00000080,
XUP = 0x00000100
}
public enum MouseEvents
{
MOUSEEVENTF_LEFTDOWN = 0x02,
MOUSEEVENTF_LEFTUP = 0x04,
MOUSEEVENTF_RIGHTDOWN = 0x08,
MOUSEEVENTF_RIGHTUP = 0x10,
MOUSEEVENTF_WHEEL = 0x0800,
}
public frmMain()
{
InitializeComponent();
}
// Loads the exe program
private void btLogin_Click(object sender, EventArgs e)
{
// takes a snapshot of the screen
Bitmap bmpScreenshot = Screenshot();
// makes the background of the form a screenshot of the screen
////this.BackgroundImage = bmpScreenshot;
// find the Icon and check if it exists
Point location;
bool success = FindBitmap(Properties.Resources.Programloader, bmpScreenshot, out location);
// check if it found the bitmap
if (success == false)
{
MessageBox.Show("Couldn't locate Andy.exe!");
return;
}
// move the mouse to Icon
Cursor.Position = location;
// click
MouseClick();
MouseClick();
if (success == true)
{
System.Threading.Thread.Sleep(5000);
}
}
/// <summary>
/// Simulates a mouse click
/// </summary>
private void MouseClick()
{
mouse_event((uint)MouseEventFlags.LEFTDOWN, 0, 0, 0, 0);
Thread.Sleep((new Random()).Next(20, 30));
mouse_event((uint)MouseEventFlags.LEFTUP, 0, 0, 0, 0);
}
/// <summary>
/// Takes a snapshot of the screen
/// </summary>
/// <returns> A snapshot of the screen</return>
private Bitmap Screenshot()
{
// this is where we will store a snapshot of the screen
Bitmap bmpScreenshot = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
// creates a graphics object so we can draw the screen in the bitmap (bmpScreenshot)
Graphics g = Graphics.FromImage(bmpScreenshot);
// copy from screen into the bitmap we created
g.CopyFromScreen(0, 0, 0, 0, Screen.PrimaryScreen.Bounds.Size);
// return the screenshot
return bmpScreenshot;
}
/// <summary>
/// Finds the location of a bit map within another bitmap and returns if it was successfully found
/// </summary>
/// <param name="bmpNeedle"> The image we want to find</param>
/// <param name="bmpHaystack"> Where we want to search for the image</param>
/// <param name="location"> Where we found the image</param>
/// <returns> If the bmpNeedle was found successfully </returns>
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;
}
private void frmMain_Load(object sender, EventArgs e)
{
timer1.Start();
timer1.Interval = 1;
}
private void timer1_Tick(object sender, EventArgs e)
{
label1.Text = Cursor.Position.X.ToString() + ":" + Cursor.Position.Y.ToString();
}
private void button1_Click_3(object sender, EventArgs e)
{
// takes a snapshot of the screen
Bitmap bmpScreenshot = Screenshot();
// makes the background of the form a screenshot of the screen
//this.BackgroundImage = bmpScreenshot;
// find the login button and check if it exists
Point location;
bool success = FindBitmap(Properties.Resources.Map, bmpScreenshot, out location);
// check if it found the bitmap
if (success == false)
{
MessageBox.Show("Test Failed Badly.");
return;
}
// move the mouse to login button
Cursor.Position = location;
// click
MouseClick();
MouseClick();
}
// Uses a Mouse_event to scroll (Right)
private void button2_Click_2(object sender, EventArgs e)
{
uint X = (775);//set x position
uint Y = (340);//set y position
// Thread.Sleep(10000);
mouse_event((uint)MouseEvents.MOUSEEVENTF_LEFTDOWN, X, Y, 0, 0);
// Thread.Sleep(2000);
SetCursorPos((int)X + 10, (int)Y + 10);
// Thread.Sleep(2000);
mouse_event((uint)MouseEvents.MOUSEEVENTF_LEFTUP, X + 15, Y + 15, 0, 0);
uint A = (775);//set x position
uint B = (340);//set y position
mouse_event((uint)MouseEvents.MOUSEEVENTF_LEFTDOWN, A, B, 50, 50);
SetCursorPos((int)A + 50, (int)B + 50);
mouse_event((uint)MouseEvents.MOUSEEVENTF_LEFTDOWN, A, B, 50, 50);
Cursor.Position = new Point(715, 218);
Thread.Sleep(2000);
Cursor.Position = new Point(400, 218);
Thread.Sleep(1000);
mouse_event((uint)MouseEvents.MOUSEEVENTF_LEFTUP, X + 15, Y + 15, 0, 0);
}
// Scans the sceen for a particular build(Farm,Sawmill,ect.)
private void button6_Click_1(object sender, EventArgs e)
{
// takes a snapshot of the screen
Bitmap bmpScreenshot = Screenshot();
// makes the background of the form a screenshot of the screen
//this.BackgroundImage = bmpScreenshot;
// find the login button and check if it exists
Point location;
bool success = FindBitmap(Properties.Resources.HallofWar, bmpScreenshot, out location);
// check if it found the bitmap
if (success == false)
{
// MessageBox.Show("Test Failed Badly.");
return;
}
// move the mouse to login button
Cursor.Position = location;
// click
MouseClick();
}
}
答案 0 :(得分:1)
如果我理解正确,你试图找出一个大位图是否包含一个较小的位图。首先,让我说Bitmap.GetPixel
非常慢,所以如果你想走这条路,如果你先将位图复制到数组中,你会好得多。您可以通过调用Bitmap.LockBits
然后使用Marshal.Copy
将原始数据复制到数组中来实现。 This MSDN page有一个例子。
如果您不想重新发明轮子,我建议使用一个库,例如OpenCV(及其.NET端口,Emgu CV)。您可以查看this question,这与您正在做的事情非常相似。
最后,提醒一句:如果我找不到它,你就试图在截图中找到一个程序图标。但是,根据您的DPI设置,分辨率,图标的透明度及其大小,您拥有的图标可能不会与屏幕上呈现的图标完全相同。