3

我为在线游戏“征服在线”制作了一个 OCR 机器人。

它工作得很好,但是,它工作得非常慢。

我认为 i7 扫描 250、000 像素应该没有问题,尤其是当每个像素执行的指令少于 100 条时。

令人不安的是,机器人每次扫描屏幕大约需要 5 秒,而它应该只需要几毫秒。

我在整个代码中插入了大量的调试语句,包括这个:

        public bool searchScreenCoord(Point screenCoord, Bitmap printscreen, List<Point> blacklistedPixels, List<LootableItem> lootableItems,
            List<AttackableMonster> attackableMonsters, ClickTracker ct, bool chkGreens, bool chkBlacks, bool chkLoot)
        {
            Color pixel = printscreen.GetPixel(screenCoord.X, screenCoord.Y);

#if DEBUG_Time
            DateTime pixelStartTime = DateTime.Now;
#endif

            if (chkGreens)
            {
#if DEBUG_Time
                if ((DateTime.Now.Subtract(pixelStartTime).Ticks > 500))
                {
                    File.AppendAllText("C:\\ocr\\stats\\pixelStats.csv", 
                        "green.Checked:" + DateTime.Now.Subtract(pixelStartTime).Ticks.ToString() + "\r\n");
                    pixelStartTime = DateTime.Now;

                }                
#endif

从定义中可以看出,chkGreens 是从 doMonsters 方法/线程传入的布尔值,而不是对 chkGreenMonsters.Checked 的调用,这可能由于访问 GUI 线程而出现问题。我消除了重复的跨线程调用以试图解决我的问题。

我的调试文件包含以下内容:

black.Checked   10000
green.Checked   10001
green.Checked   10000
black.Checked   10000
get black word  30001
black.Checked   10001
black.Checked   10001
get black word  10001

出于我想不到的原因,线程在声明日期时间和检查传入的 bool 之间休眠了 10, 000 个滴答声。

但并不是每次调用 searchScreenCoord 时都会发生这种情况。也许每 25 或 50 个电话一次。

我想这可能是一个行为不端的过程,每隔一段时间就需要 10,000 个滴答声来进行时间切片,但这种解释似乎很牵强。

有谁知道为什么这会发生在我身上?

我很感激任何可以消除应用程序正在采取的可怕的 10,000 次小睡的建议。

谢谢。

4

2 回答 2

3

DateTime 返回的值来自系统时钟。它仅在线程第一次放在 cpu 上时更新,因此您会看到它一次跳过 10 毫秒或 15 毫秒的时间,即使您可能会对其进行两次相隔 5 微秒的调用。

相反,使用高性能计数器来测量物理时间的流逝。

    [DllImport("kernel32.dll", SetLastError = true)]
    public static extern bool QueryPerformanceCounter(out long lpPerformanceCount);

    [DllImport("kernel32.dll", SetLastError = true)]
    public static extern bool QueryPerformanceFrequency(out long frequency);

调用一次 QPF 以计算 QPC 每秒变化的速度。

time1 = QPC
-stuff-
time2 = QPC
passedTimeSeconds = (time2 - time1) / QPF
于 2013-03-30T04:23:55.497 回答
1

GetPixel 是一种访问像素数据的非常慢的方法。

有关如何处理大块像素数据的信息,请参阅此 SO 条目:

在 C# 中快速使用位图

于 2013-03-30T03:43:31.033 回答