在Python中读取屏幕像素的方法比PIL更快吗? [英] Faster method of reading screen pixel in Python than PIL?

查看:394
本文介绍了在Python中读取屏幕像素的方法比PIL更快吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

目前,我正在通过AutoItv3使用像素读取器来在运行直接X的程序中执行某些操作;一个游戏.现在程序可以正常工作,但是作为练习,我一直在用python重写它.现在我可以做:

Currently I'm using a pixel reader via AutoItv3 to perform some actions in a program that is running direct X; A game. Right now the program works fine but as an exercise I've been rewriting it in python. Right now I can do:

import ImageGrab  # Part of PIL
    image = ImageGrab.grab() #Define an area to capture.
    rgb = image.getpixel((1, 90)) #What pixel do we want?

这可以捕捉我想要的像素信息,但是我做得很快(需要每秒完成3倍或更快),但是结果是,它主要影响了这款基于DirectX的游戏的帧速率

And that grabs the pixel info I want just fine, but I'm doing this quite rapidly (needs to be done 3x a second or faster), but the result is that it majorly affects the framerate of this DirectX-based game.

Python中是否有更快的方法来读取特定的屏幕像素?即使将其限制为每0.3秒运行一次,也会造成比实际更多的压力(我实际上认为python会比AutoIt更快 ,从而达到特定目的,因此我尝试这样做的原因)

Is there a faster way in Python to read a specific screen pixel? Even limiting this one to running every 0.3 seconds is causing more strain than it really should (I actually figured python would be faster than AutoIt for this particular purpose, hence the reason I'm trying it)

推荐答案

这是PIL的抓取屏幕源,它不接受任何参数,并且抓取整个屏幕并将其转换为位图.

This is the PIL's grabscreen source, Its does not accept any parameters, and Its grab the whole screen and convert it to bitmap.

PyImaging_GrabScreenWin32(PyObject* self, PyObject* args)
{
    int width, height;
    HBITMAP bitmap;
    BITMAPCOREHEADER core;
    HDC screen, screen_copy;
    PyObject* buffer;

    /* step 1: create a memory DC large enough to hold the
       entire screen */

    screen = CreateDC(";DISPLAY", NULL, NULL, NULL); 
    screen_copy = CreateCompatibleDC(screen); 

    width = GetDeviceCaps(screen, HORZRES);
    height = GetDeviceCaps(screen, VERTRES);

    bitmap = CreateCompatibleBitmap(screen, width, height);
    if (!bitmap)
        goto error;

    if (!SelectObject(screen_copy, bitmap))
        goto error;

    /* step 2: copy bits into memory DC bitmap */

    if (!BitBlt(screen_copy, 0, 0, width, height, screen, 0, 0, SRCCOPY))
        goto error;

    /* step 3: extract bits from bitmap */

    buffer = PyString_FromStringAndSize(NULL, height * ((width*3 + 3) & -4));
    if (!buffer)
        return NULL;

    core.bcSize = sizeof(core);
    core.bcWidth = width;
    core.bcHeight = height;
    core.bcPlanes = 1;
    core.bcBitCount = 24;
    if (!GetDIBits(screen_copy, bitmap, 0, height, PyString_AS_STRING(buffer),
                   (BITMAPINFO*) &core, DIB_RGB_COLORS))
        goto error;

    DeleteObject(bitmap);
    DeleteDC(screen_copy);
    DeleteDC(screen);

    return Py_BuildValue("(ii)N", width, height, buffer);

error:
    PyErr_SetString(PyExc_IOError, "screen grab failed");

    DeleteDC(screen_copy);
    DeleteDC(screen);

    return NULL;
}

所以,当我稍微深入一点时,发现C方法是很好的

So, when I just go a little deep, found C approach is good

http://msdn.microsoft.com/zh-cn/library/dd144909(VS.85).aspx

Python具有ctypes,因此这是我使用ctypes的方法(在Windows 10中,winnt已替换为Windows):

And Python has ctypes, so here is my approach using ctypes (in Windows 10, winnt has been replaced with Windows):

>>> from ctypes import *
>>> user= windll.LoadLibrary("c:\\winnt\\system32\\user32.dll") #I am in windows 2000, may be yours will be windows
>>> h = user.GetDC(0)
>>> gdi= windll.LoadLibrary("c:\\winnt\\system32\\gdi32.dll")
>>> gdi.GetPixel(h,1023,767)
16777215 #I believe its white color of RGB or BGR value, #FFFFFF (according to msdn it should be RGB)
>>> gdi.GetPixel(h,1024,767)
-1 #because my screen is only 1024x768

您可以像这样为函数GetPixel编写包装器

You could write a wrapper for function GetPixel like this

from ctypes import windll
dc= windll.user32.GetDC(0)

def getpixel(x,y):
    return windll.gdi32.GetPixel(dc,x,y)

然后您可以使用getpixel(0,0)getpixel(100,0)等...

Then you can use like getpixel(0,0), getpixel(100,0), etc...

PS:我的操作系统是Windows 2000,因此我将winnt放在路径中,您可能需要将其更改为windows,否则您应该完全删除路径,只需使用user32.dllgdi32.dll也可以.

PS: Mine is Windows 2000, so I put winnt in the path, you may need to change it to windows or you chould completely remove path, just using user32.dll and gdi32.dll should work too.

这篇关于在Python中读取屏幕像素的方法比PIL更快吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆