C#BitMap无法找到像素

时间:2015-06-30 01:10:18

标签: c# bitmap

我一直在研究一个基本上运行位图截图图像的小应用程序。然后位图检测到我加载的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();
    }
}

1 个答案:

答案 0 :(得分:1)

如果我理解正确,你试图找出一个大位图是否包含一个较小的位图。首先,让我说Bitmap.GetPixel非常慢,所以如果你想走这条路,如果你先将位图复制到数组中,你会好得多。您可以通过调用Bitmap.LockBits然后使用Marshal.Copy将原始数据复制到数组中来实现。 This MSDN page有一个例子。

如果您不想重新发明轮子,我建议使用一个库,例如OpenCV(及其.NET端口,Emgu CV)。您可以查看this question,这与您正在做的事情非常相似。

最后,提醒一句:如果我找不到它,你就试图在截图中找到一个程序图标。但是,根据您的DPI设置,分辨率,图标的透明度及其大小,您拥有的图标可能不会与屏幕上呈现的图标完全相同。