Мне нужно обрабатывать изображения, отправленные на видеодисплей моего ноутбука, и мне нужно отправить ввод с клавиатуры в мою систему Linux, используя C ++ или программу оболочки.

Моя цель - обрабатывать изображения, которые являются частью игры FPS, а затем выполнять действия внутри этой игры (следовательно, ввод с клавиатуры) на основе этих изображений. Вместо того, чтобы пытаться понять (если это вообще возможно), как взаимодействовать с игрой X или Y, используя некоторый API, я решил, что это самый быстрый способ взаимодействия с любой игрой, каким-то образом перехватывая ввод и вывод Linux.

Есть ли способ сделать это без взлома ядра или драйверов устройств? Раньше я использовал recordmydesktop для записи своего рабочего стола в виде видео, думаю, я мог бы взломать его код и попытаться что-то из него перепроектировать. Есть другие идеи? Я использую Ubuntu 11.

Связанный вопрос

2
BBSysDyn 28 Авг 2011 в 18:34

3 ответа

Лучший ответ

Наконец-то у меня есть решение. Я считаю, что UrT сам по себе загружает OpenGL, поэтому такие вещи, как wallhacks и т. Д., Невозможны. Тогда лучший оставшийся вариант - это сделать X-скриншоты. Это работало довольно быстро, даже с таким языком сценариев, как Python. Следующий код делает последовательные снимки экрана и отображает их в виде анимации через OpenCV. УрТ, конечно, нужно запускать в свернутом режиме. Остальные детали в моем проекте.

import gtk.gdk
import PIL
from opencv.cv import *
from opencv.highgui import *
from opencv.adaptors import PIL2Ipl

w = gtk.gdk.get_default_root_window()
sz = w.get_size()
print "The size of the window is %d x %d" % sz

size_x = 600
size_y = 400
start_x = 0
start_y = 100
end_x = start_x+size_x
end_y = start_y+size_y
box = (start_x, start_y, start_x+size_x, start_y+size_y)

while True:
    pb = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB,False,8,sz[0],sz[1])
    pb = pb.get_from_drawable(w,w.get_colormap(),0,0,0,0,sz[0],sz[1])
    width,height = pb.get_width(),pb.get_height()
    im = PIL.Image.fromstring("RGB",(width,height),pb.get_pixels())
    im = im.crop(box)
    cv_img = PIL2Ipl(im)
    cvNamedWindow("fps")
    cvShowImage("fps", cv_img)
    cvWaitKey(30) 

Также для отправки ключей в игру описанный выше способ не работал, пришлось использовать xdotool чтобы отправить ключ прямого перехода в УрТ,

xdotool search --name ioUrbanTerror  windowactivate keydown W
0
Nightfirecat 15 Ноя 2011 в 19:18

Для этого вам не нужно делать ничего более низкого уровня, чем ядро ​​или драйверы устройств.

Вы можете использовать расширение XTest X11, чтобы программно имитировать события ввода, например (из это сообщение, есть < a href = "http://bharathisubramanian.wordpress.com/2010/03/14/x11-fake-key-event-generation-using-xtest-ext" rel = "nofollow"> другой пример клавиатуры ).

#include <X11/extensions/XTest.h>  
#include <unistd.h>  

int main ()  
{  
  Display *dpy = NULL;  
  XEvent event;  

  dpy = XOpenDisplay (NULL);  

  /* Get the current pointer position */  
  XQueryPointer (dpy, RootWindow (dpy, 0),  
        &event.xbutton.root, &event.xbutton.window,  
        &event.xbutton.x_root, &event.xbutton.y_root,  
        &event.xbutton.x, &event.xbutton.y,  
        &event.xbutton.state);  

  /* Fake the pointer movement to new relative position */  
  XTestFakeMotionEvent (dpy, 0, event.xbutton.x + 100,  
        event.xbutton.y + 50, CurrentTime);  
  XSync(dpy, 0);  
  XCloseDisplay (dpy);  
  return 0;  
}   

Самый простой способ сделать снимки - использовать функцию вставки (через LD_PRELOAD) для «перехвата» вызовов glXSwapBuffers , который будет вызываться после отрисовки каждого кадра. Оттуда вы можете скопировать содержимое фреймбуфера, используя glReadPixels и делайте с ним, что хотите.

Например. непроверенная схема для перехвата фреймов OpenGL:

// Function pointer to the *real* glXSwapBuffers
static void (*glx_fptr)(Display*, GLXDrawable) = NULL;

// Make sure init gets called when the shared object is loaded. GCC specific.
static void init(void)  __attribute__((constructor));

static void init(void) {
    dlerror();
    // find the real glXSwapBuffers
    glx_fptr = dlsym(RTLD_NEXT, "glXSwapBuffers");
    if (NULL == glx_fptr)
        fprintf(stderr, "[glvidcap] %s\n", dlerror());
}

void glXSwapBuffers(Display *dpy, GLXDrawable drawable) {
    unsigned int w = 0;
    unsigned int h = 0;
    static int x,y;
    static Window win;
    static unsigned int border,depth;
    // Find the window size. (You could skip this and make it all static if you
    // Trust the window not to change size
    XGetGeometry(dpy, drawable, &win, &x, &y, &w, &h, &border, &depth);

    // Assuming frame is some memory you want the frame dumped to:
    glReadPixels(0,0,w,h,GL_BGR,GL_UNSIGNED_BYTE, frame);

    // Call the real function:
    assert(glx_fptr);
    glx_fptr(dpy, drawable);
}

Затем вы хотите скомпилировать его как общий объект и LD_PRELOAD этот общий объект перед запуском любой игры, которую вы просматриваете.

Если это приложение SDL, вы можете перехватить вызовы к SDL_Flip или SDL_UpdateRect в зависимости от ситуации.

5
Lekensteyn 3 Янв 2014 в 23:34

Благодаря ответу @ awoodland я поискал связанные ресурсы и нашел это

http://bzr.sesse.net/glcapture/glcapture.c

Я компилирую этот код как

gcc -shared -fPIC -o glcapture.so glcapture.c -ldl

И загрузите его для FPS-игры Urban Terror в скрипте как

LD_PRELOAD=`pwd`/glcapture.so [DIR]/UrbanTerror/ioUrbanTerror.i386

В момент запуска этого скрипта игра загружается. По какой-то причине игровая графика не отображается, но я могу это исправить позже. Когда я выхожу из игры, я вижу сообщения gettimeofday, напечатанные на консоли, которые говорят мне, что ловушка сработала. Я предоставлю более подробную информацию по мере продолжения работы над этим кодом.

Для отправки нажатий клавиш я перешел по ссылке

http://bharathisubramanian.wordpress.com/2010/03/14/x11-fake-key-event-generation-using-xtest-ext/

После того, как я установил необходимый пакет на Ubuntu с помощью

sudo apt-get install libxtst-dev

Затем fakeKey.c компилировался и работал без проблем.

Примечание. Я начал проект на Github для этого, любой желающий может разветвляться, помогать и т. Д.

1
Lekensteyn 3 Янв 2014 в 23:35