質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.36%

openCVで画像を読み込んでopenGLで表示させると色が違う原因と対処方法が知りたい。

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 1,252
退会済みユーザー

退会済みユーザー

提示画像ですが左がopenglで右が画像を表示させているのですがなぜoepngCVで読み込んでopenGLで描画させると画像の色が違うのでしょうか?
一番怪しいのは画像の読み込みLoadTexture();関数ですが何をしてしまったのでしょうか?検討が付きません。色空間でしょうか?
色のチャンネル数は3でした。

イメージ説明

byte* LoadTexture(const char* str, float* width, float* height)
{
    cv::Mat image;
    image = cv::imread(str);

    if (image.empty() == true)
    {
        printf("image.empty()\n");
        return nullptr;
    }
    else {
        printf("load \n");
        //cv::cvtColor(image, image, cv::COLOR_RGB2BGR); //色空間を変更

        printf("channels: %d\n",image.channels());
        int size = image.rows * image.cols * image.channels();


        printf("size: %d\n", size);
        byte* bytes = new byte[size]{ 0 }; 
        std::memcpy(bytes, (void*)image.data, (size_t)size);

        // 画像サイズを取得
        *width = image.cols;    //  横
        *height = image.rows;   //  縦


        return bytes;   //  unsigned char*を返す
    }
}



#include "../Header/Sprite.hpp"
#include "../Header/Shader.hpp"
#include "../Header/Game.hpp"
#include "../Header/Texture.hpp"

//数学ライブラリ
#include "glm/ext.hpp"
#include "glm/glm.hpp"


#include <opencv2/core.hpp>

class Game;
/*################################################################################################################
* 画像 描画クラス
################################################################################################################*/

//コンストラクタ
/*
* Game クラス
* テクスチャ パス
* 描画する画像の寸法
*/
Sprite::Sprite(Game* g, const char* FileName) : Transform_2D(g)
{
    shader = new Shader(g,"Shader/2D/Sprite.vert", "Shader/2D/Sprite.frag");
    Owner = g;//Gameクラス

    Transform_2D::setTransfrom(glm::vec2(1,1),0,glm::vec2(0,0));    //トランスフォームを初期化

    //テクスチャを設定     

    glGenTextures(1, &TextureID);
    glBindTexture(GL_TEXTURE_2D, TextureID);

    float width, height;    //画像の寸法

    byte* data = LoadTexture(FileName,&width,&height);    //テクスチャを取得

    printf("widht: %f\n", width);
    printf("height: %f\n", height);

    if (data != NULL) 
    {
        if (getTextureChannel(FileName) == 3)
        {
            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, (GLsizei)width, (GLsizei)height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
        }
        else if (getTextureChannel(FileName) == 4)
        {
            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)width, (GLsizei)height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
        }
    }
    else {
        std::cerr << "Unable to load texture: " << FileName << std::endl;
    }

    //1ドットのUV数値
    float uvWidth = 1.0f / width;    //U
    float uvHeight = 1.0f / height;    //V    

    vertex[0] = attribute{ -width / 2.0f,height / 2.0f,     0,0 };
    vertex[1] = attribute{ -width / 2.0f,-height / 2.0f, 0,1 };
    vertex[2] = attribute{ width / 2.0f,-height / 2.0f,  1,1 };

    vertex[3] = attribute{ -width / 2.0f,height / 2.0f, 0,0 }; 
    vertex[4] = attribute{ width / 2.0f,-height / 2.0f, 1,1 };
    vertex[5] = attribute{ width / 2.0f,height /  2.0f, 1,0 };

    //VAO
    glGenVertexArrays(1, &VAO);
    glBindVertexArray(VAO);

    //VBO
    glGenBuffers(1, &VBO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, (sizeof(vertex) / sizeof(vertex[0])) * sizeof(attribute), vertex, GL_STATIC_DRAW);

    //頂点座標
    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(attribute), NULL);
    glEnableVertexAttribArray(0);

    //UV座標
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(attribute), (void*)(sizeof(float) * 2));
    glEnableVertexAttribArray(1);

    //ミニマップを設定
    glGenerateMipmap(GL_TEXTURE_2D);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    //異方性フィルタリングを設定
    GLfloat largest;
    glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &largest);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, largest);

    delete data;
    data = nullptr;
}

//描画
void Sprite::DrawGraph(int x, int y)
{
    shader->Enable();    //シェーダーを有効にする
    shader->SetFloatUniform_3m("uViewMatrix", getViewMatrix());
    shader->SetFloatUniform_3m("uWorldMatrix", getWorldMatrix());
    Transform_2D::UpdateTransform();


    Transform_2D::setTransform_Move(glm::vec2(x, y));

    glBindVertexArray(VAO);
    glBindTexture(GL_TEXTURE_2D, TextureID);
    glDrawArrays(GL_TRIANGLES, 0, (GLsizei)std::size(vertex));

}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • jbpb0

    2021/01/20 16:51

    https://note.nkmk.me/python-opencv-bgr-rgb-cvtcolor/
    から引用
    OpenCVの関数imread()で画像ファイルを読み込むと色の順番がBGR(青、緑、赤)になる。

    キャンセル

回答 1

checkベストアンサー

+1

glTexImage2DでデータフォーマットにGL_RGBを指定しているが,OpenCVで読み込んだデータのフォーマットはBGRなので食い違っている.
そのため,BとRが反転した結果となっている.

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2021/01/20 17:21

    cv::cvtColor(image,image, cv::COLOR_BGR2RGB);
    として解決しました。

    キャンセル

  • 2021/01/20 17:40

    わざわざ画像データを変換するんですか.
    glTexImage2D の引数の側を1個変えるだけで済む話なんじゃないかと思うんだけど.

    キャンセル

  • 2021/01/20 17:43

    (まぁ,どっち側をいじくるべき話なのかは,関数 LoadTexture の戻り値の仕様次第だろうから,画像側をいじくるのが正解なのかもしれません.)

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.36%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る