如何快速获取并处理实时屏幕输出
我正在尝试编写一个程序来玩全屏电脑游戏(作为计算机视觉和人工智能的实验)。
对于这个实验,我假设游戏没有供 AI 玩家使用的底层 API(也没有可用的源),因此我打算处理游戏在屏幕上呈现的视觉信息。
游戏在 win32 系统上以全屏模式运行(我假设是 direct-X)。
目前我正在使用 win32 函数
#include <windows.h>
#include <cvaux.h>
class Screen {
public:
HWND windowHandle;
HDC windowContext;
HBITMAP buffer;
HDC bufferContext;
CvSize size;
uchar* bytes;
int channels;
Screen () {
windowHandle = GetDesktopWindow();
windowContext = GetWindowDC (windowHandle);
size = cvSize (GetDeviceCaps (windowContext, HORZRES), GetDeviceCaps (windowContext, VERTRES));
buffer = CreateCompatibleBitmap (windowContext, size.width, size.height);
bufferContext = CreateCompatibleDC (windowContext);
SelectObject (bufferContext, buffer);
channels = 4;
bytes = new uchar[size.width * size.height * channels];
}
~Screen () {
ReleaseDC(windowHandle, windowContext);
DeleteDC(bufferContext);
DeleteObject(buffer);
delete[] bytes;
}
void CaptureScreen (IplImage* img) {
BitBlt(bufferContext, 0, 0, size.width, size.height, windowContext, 0, 0, SRCCOPY);
int n = size.width * size.height;
int imgChannels = img->nChannels;
GetBitmapBits (buffer, n * channels, bytes);
uchar* src = bytes;
uchar* dest = (uchar*) img->imageData;
uchar* end = dest + n * imgChannels;
while (dest < end) {
dest[0] = src[0];
dest[1] = src[1];
dest[2] = src[2];
dest += imgChannels;
src += channels;
}
}
使用这种方法处理帧的速度太慢了。有没有更好的方法来获取屏幕帧?
I am trying to write a program to play a full screen PC game for fun (as an experiment in Computer Vision and Artificial Intelligence).
For this experiment I am assuming the game has no underlying API for AI players (nor is the source available) so I intend to process the visual information rendered by the game on the screen.
The game runs in full screen mode on a win32 system (direct-X I assume).
Currently I am using the win32 functions
#include <windows.h>
#include <cvaux.h>
class Screen {
public:
HWND windowHandle;
HDC windowContext;
HBITMAP buffer;
HDC bufferContext;
CvSize size;
uchar* bytes;
int channels;
Screen () {
windowHandle = GetDesktopWindow();
windowContext = GetWindowDC (windowHandle);
size = cvSize (GetDeviceCaps (windowContext, HORZRES), GetDeviceCaps (windowContext, VERTRES));
buffer = CreateCompatibleBitmap (windowContext, size.width, size.height);
bufferContext = CreateCompatibleDC (windowContext);
SelectObject (bufferContext, buffer);
channels = 4;
bytes = new uchar[size.width * size.height * channels];
}
~Screen () {
ReleaseDC(windowHandle, windowContext);
DeleteDC(bufferContext);
DeleteObject(buffer);
delete[] bytes;
}
void CaptureScreen (IplImage* img) {
BitBlt(bufferContext, 0, 0, size.width, size.height, windowContext, 0, 0, SRCCOPY);
int n = size.width * size.height;
int imgChannels = img->nChannels;
GetBitmapBits (buffer, n * channels, bytes);
uchar* src = bytes;
uchar* dest = (uchar*) img->imageData;
uchar* end = dest + n * imgChannels;
while (dest < end) {
dest[0] = src[0];
dest[1] = src[1];
dest[2] = src[2];
dest += imgChannels;
src += channels;
}
}
The rate at which I can process frames using this approach is much too slow. Is there a better way to acquire screen frames?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
作为一般方法,我会挂接缓冲区翻转函数调用,以便可以捕获每个帧上的帧缓冲区。
http://easyhook.codeplex.com/
As a general method, I would hook the buffer-flipping function calls so I can capture the framebuffer on every frame.
http://easyhook.codeplex.com/