Черный квадрат отображает вместо изображения OpenCV

Я пытаюсь отобразить два изображения размером 256x256 с типом данных ushort. Один должен быть в оттенках серого, а другой в RGB. Однако оба отображаются как черные квадраты. Я считаю, что ошибка кроется где-то в моем определении текстуры openGL, но я не уверен.

Вот моя минимальная версия кода.

#include "imgui.h"
#include "imgui_impl_glfw.h"
#include "imgui_impl_opengl3.h"
#include <glad/glad.h>    
#include <GLFW/glfw3.h>
#include <opencv2/opencv.hpp>

using namespace cv;


int main()
{
    //init glfw, window, glad, imgui
    glfwInit();
    const char* glsl_version = "#version 330 core";
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    GLFWwindow* window = glfwCreateWindow(600, 400, "test", NULL, NULL);
    glfwMakeContextCurrent(window);
    gladLoadGL();
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    ImGui::CreateContext();
    ImGui::StyleColorsDark();
    ImGui_ImplGlfw_InitForOpenGL(window, true);
    ImGui_ImplOpenGL3_Init(glsl_version);


    //define image data
    ushort value;
    Mat_<ushort> grey = Mat_<ushort>(256, 256);
    Mat_<Vec3w> rgb = Mat_<Vec3w>(256, 256);


    for (int i = 0; i < grey.rows; i++)
        for (int j = 0; j < grey.cols; j++)
        {
            value = (i + j) / 256.0 * USHRT_MAX;
            grey.at<ushort>(i, j) = value;
            rgb.at<Vec3w>(i, j) = Vec3w(value, value, value);
        }

    
    //create textures
    GLuint greyID;
    GLuint rgbID;

    glGenTextures(1, &greyID);
    glBindTexture(GL_TEXTURE_2D, greyID);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_R16, 256, 256, 0, GL_RED, GL_UNSIGNED_SHORT, grey.data);

    glGenTextures(1, &rgbID);
    glBindTexture(GL_TEXTURE_2D, rgbID);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16UI, 256, 256, 0, GL_RGB, GL_UNSIGNED_SHORT, rgb.data);


    while (!(glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS))
    {
        glfwPollEvents();

        ImGui_ImplOpenGL3_NewFrame();
        ImGui_ImplGlfw_NewFrame();
        ImGui::NewFrame();

        ImGui::Begin("Images");
        ImGui::Image((void*)(intptr_t)greyID, ImVec2(256, 256));
        ImGui::SameLine();
        ImGui::Image((void*)(intptr_t)rgbID, ImVec2(256, 256));
        ImGui::End();

        ImGui::Render();

        glClearColor(0.2f, 0.2f, 0.2f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

        ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
        glfwSwapBuffers(window);
    }

    ImGui::DestroyContext();
    glfwDestroyWindow(window);
    glfwTerminate();
    return 1;
}

Вот результат:

Я не вижу явных проблем. Попробуйте проверить наличие ошибок с помощью glGetError после glTexImage2D. Вы также можете попробовать использовать инструмент отладки, такой как RenderDoc или APITrace. С другой стороны, есть ли причина, по которой вы все еще используете OpenCV 2?

LHLaurini 12.01.2023 16:08

@LHLaurini Что именно вы подразумеваете под «вы все еще используете OpenCV 2»?

Dan Mašek 12.01.2023 16:19

@DanMašek Я имею в виду, что OpenCV 2.x к этому моменту уже ~ 5 лет. Усложняет компиляцию на некоторых системах.

LHLaurini 12.01.2023 16:22

Я использовал glGetError() после каждого вызова создания текстур и не получил никаких проблем, за исключением второго glTexImage2D. Возвращает ошибку 1282.

Lilmothiit 12.01.2023 16:31

@LHLaurini Я понимаю, но как вы пришли к выводу, что эту версию использует OP? Я не вижу никаких указаний на это нигде в посте (но, может быть, я что-то пропустил?). Если вы делаете это предположение на основе директивы include, то это неверно — даже месячная версия 4.7.0 по-прежнему использует opencv2 для заголовков...

Dan Mašek 12.01.2023 16:33

@DanMašek Ты прав.

LHLaurini 12.01.2023 16:34

@Lilmothiit Хм, это странно. 1282 есть GL_INVALID_OPERATION, и ни одна из проблем в документах не кажется актуальной.

LHLaurini 12.01.2023 16:43

@LHLaurini В других дискуссиях по подобным вопросам, похоже, упоминается, что документация Khronos может быть устаревшей или неполной. Я не уверен.

Lilmothiit 12.01.2023 16:49

Я обнаружил одну несвязанную проблему с моим кодом: установка значений (i + j) / 256.0 * USHRT_MAX превышает предел USHRT_MAX для половины изображения. Хотел написать (i + j) / 512.0 * USHRT_MAX. Однако его изменение не решает проблему.

Lilmothiit 12.01.2023 16:59

Разве GL_RGB во втором вызове glTexImage2D не должен быть вместо GL_RGB_INTEGER? В документации сказано, что «GL_INVALID_OPERATION генерируется, если комбинация internalFormat, формата и типа не является одной из приведенных выше таблиц». и эта комбинация, которую вы используете, отсутствует в вышеупомянутой таблице, насколько я вижу... Хотя, возможно, я смотрю на неправильную версию документов:/

Dan Mašek 12.01.2023 17:00

@DanMašek Вы частично правы. GL_RGB_INTEGER приводит к полному исчезновению моего блока Image, так как мой тип данных короткий. Я думаю, GL_RGB16 или GL_RGB16UI было бы правильно вместо этого? Однако установка любого из них по-прежнему не решает исходную проблему, но, по крайней мере, черный квадрат отображается.

Lilmothiit 12.01.2023 17:08

@Lilmothiit вам нужно GL_RGB16 для внутреннего формата и GL_RGB для формата данных.

Yakov Galka 12.01.2023 17:08

@YakovGalka извините, я пробовал, но все равно не работает :(

Lilmothiit 12.01.2023 17:10
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
13
73
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

В вашем коде две проблемы.

Во-первых, как обсуждалось в комментариях, в вашем случае вы, вероятно, захотите использовать GL_RGB16 вместо GL_RGB16UI. Это позаботится об ошибке текстуры.

Вторая проблема заключается в том, что вам нужно добавить

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

после glBindTexture.

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

После исправления обеих этих проблем ваша программа работает:

Вы также можете рассчитать свой цвет как

value = min((i + j) / 256.0), 1.0) * USHRT_MAX;

Большое спасибо!! Что касается расчета value, я уже прокомментировал, что хотел написать value = (i + j) / 512.0 * USHRT_MAX;.

Lilmothiit 12.01.2023 18:00

@Lilmothiit Ах, да, я пропустил это. Разделение на 510.0 было бы немного лучше, так как это максимальное значение (255+255).

LHLaurini 12.01.2023 18:04

Чтобы добавить к ответу LHLaurini, я также допустил ошибку во втором звонке glTexImage2d. Здесь внутренний формат GL_RGB16UI неверен, так как мой тип данных short. Этот формат должен быть GL_RGB16:

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16, 256, 256, 0, GL_RGB, GL_UNSIGNED_SHORT, rgb.data);

Другие вопросы по теме