Как отобразить изображения (GpuMats), которые были обработаны на графическом процессоре с помощью CUDA, в QGLWidget? - PullRequest
0 голосов
/ 19 сентября 2019

Немного предыстории:

Я работаю над проектом, который читает два изображения 4k, использует opencv, чтобы начать процесс сшивания изображений для создания панорамы (я использую это для получения значений, которые будут использоваться позже),затем я передаю данные, полученные из opencv, в ядро ​​CUDA и выполняю вычисления (сложение и умножение) для окончательного сшивания изображений.

Там, где начинается проблема:

Первоначально япередавал скачанный cv::Mat в класс с именем video_widget, который наследует QGLWidget, и отображал изображение там без проблем.Поскольку очень важно ускорить этот процесс, мне было интересно, есть ли способ сократить время загрузки данных из GPU в CPU и вместо этого просто отображать данные прямо из GPU.

У меня естьисследовал, и, возможно, я недостаточно знаю о своей проблеме, чтобы задавать правильные вопросы, но из того, что я вижу, это кажется возможным.Кто-нибудь может помочь, пожалуйста?

Когда я только начал, я изменил методы с передачи загруженного cv::Mat на пропуск cv::cuda::GpuMat, с которого загружались данные.Я понимаю, что теперь это неправильно, поскольку я пишу это, зная о том, как обрабатываются данные в графическом процессоре ... но в любом случае.После обработки изображения я пропускаю его через сигнальный слот, который вызывает метод update_frame для созданного QGLWidget, затем обновляется глобальный cv::cuda::GpuMat, затем вызывается updateGL(), который, как я знаю, вызывает paintGL().Итак, внутри paintGL() я попробовал пару вещей, которые все потерпели неудачу:

  1. Просто изменил строку с принятия в cv::Mat на cv::cuda::GpuMat
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, current_frame_gpu.cols, current_frame_gpu.rows, 0.0f, GL_BGR, GL_UNSIGNED_BYTE, current_frame_gpu.data);

это мгновенно закончилось неудачей, поэтому я начал (догадываться) менять разные форматы, чтобы посмотреть, не в этом ли проблема ... Без кубиков.

Создал QOpenGLTexture и скопировал данные из cv::cuda::GpuMat к этому и попытался связать его, вызвав this->bindTexture(), но каждый раз в этой строке или около нее не получалось.

Пробовал

cv::ogl::Texture2D tex;

tex.copyFrom(current_frame_gpu);

tex.bind();

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

Правильный код при пропуске cv::Mat:

void video_widget::paintGL(){
    //Clear the buffer
    glClear(GL_COLOR_BUFFER_BIT);
    //Update the texture
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, current_frame.cols, 
    current_frame.rows, 0.0f, GL_BGR, GL_UNSIGNED_BYTE, current_frame.data);
    //Maps each texture coordinate to the vertices in object space
    float x_offset = 60.0;
    float y_offset = -10.0;
    glBegin(GL_QUADS);
    glTexCoord2f(0, 1); 
    glVertex2i(left + dx + x_offset, bottom + dy - y_offset);
    glTexCoord2f(0, 0); 
    glVertex2i(left + dx + x_offset, top + dy - y_offset);
    glTexCoord2f(1, 0); 
    glVertex2i(right + dx + x_offset, bottom + dy - y_offset);
    glTexCoord2f(1, 1); 
    glVertex2i(right + dx + x_offset, top + dy - y_offset);
    glEnd();

    //Some settings checks...
    ...
    ...

    glFlush();
}
...