2017-04-01 6 views
0

OPENGLを使用して画像のヒストグラムを計算しようとしています。私はそれについていくつかの記事を読んだが、私はまだエラーが発生します。私のヒストグラムバッファは常にゼロを返します。私は読んだことがある いくつかのポスト:OPENGLでヒストグラムを計算する

Maknoll Histogram

Luminance histogram calculation in GPU-android opengl es 3.0

マイコード:

#include <stdio.h> 
#include <stdlib.h> 
#include <iostream> 
#include <vector> 

// Include GLEW 
#include <GL/glew.h> 

// Include GLFW 
#include <GLFW/glfw3.h> 
GLFWwindow* window; 

// Include GLM 
#include <glm/glm.hpp> 
using namespace glm; 
#include <SOIL.h> 

// Shader sources 
const GLchar* vertexSource = "\n" 
"#version 330 core\n" 
"attribute vec3 inPosition;\n" 
"void main()\n" 
"{\n" 
" float x = inPosition.x;\n" 
"\n" 
" gl_Position = vec4(\n" 
"  -1.0 + ((x) * 0.0078125),\n" 
"  -1,\n" 
"  0.0,\n" 
"  1.0\n" 
" );\n" 
"}\n"; 

const GLchar* fragmentSource = "\n" 
"#version 330 core\n" 
"out vec4 outputColor;\n" 
"void main()\n" 
"{\n" 
" outputColor = vec4(1.0, 1.0, 1.0, 1.0);\n" 
"}\n"; 

void CheckStatus(GLuint obj) 
{ 
    GLint status = GL_FALSE, len = 10; 
    if(glIsShader(obj)) glGetShaderiv(obj, GL_COMPILE_STATUS, &status); 
    if(glIsProgram(obj)) glGetProgramiv(obj, GL_LINK_STATUS, &status); 
    if(status == GL_TRUE) return; 
    if(glIsShader(obj)) glGetShaderiv(obj, GL_INFO_LOG_LENGTH, &len); 
    if(glIsProgram(obj)) glGetProgramiv(obj, GL_INFO_LOG_LENGTH, &len); 
    std::vector<char> log(len, 'X'); 
    if(glIsShader(obj)) glGetShaderInfoLog(obj, len, NULL, &log[0]); 
    if(glIsProgram(obj)) glGetProgramInfoLog(obj, len, NULL, &log[0]); 
    std::cerr << &log[0] << std::endl; 
    exit(-1); 
} 

GLfloat buffer[256]; 
GLuint hist[256]; 
float _image[512*512*3]; 

int main() 
{ 
    // Initialise GLFW 
    if(!glfwInit()) 
    { 
     fprintf(stderr, "Failed to initialize GLFW\n"); 
     getchar(); 
     return -1; 
    } 

    glfwWindowHint(GLFW_SAMPLES, 4); 
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); 
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); 
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // To make MacOS happy; should not be needed 
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); 

    int width, height; 
    unsigned char* image = SOIL_load_image("sample_gray.bmp", &width, &height, 0, SOIL_LOAD_RGB); 
    unsigned char image_gray[width * height]; 
    printf("%d\t%d\n", width, height); 

    for (int i = 0; i < width * height; ++i) 
    { 
     image_gray[i] = image[i * 3]; 
     _image[i * 3] = image[i * 3]; 
     _image[i * 3 + 1] = image[i * 3 + 1]; 
     _image[i * 3 + 2] = image[i * 3 + 2]; 
    } 

    for (int i = 0; i < width * height; ++i) 
    { 
     hist[image_gray[i]]++; 
    } 

    // Open a window and create its OpenGL context 
    window = glfwCreateWindow(width, height, "Basic", NULL, NULL); 
    if(window == NULL){ 
     fprintf(stderr, "Failed to open GLFW window. If you have an Intel GPU, they are not 3.3 compatible. Try the 2.1 version of the tutorials.\n"); 
     getchar(); 
     glfwTerminate(); 
     return -1; 
    } 
    glfwMakeContextCurrent(window); 

    // Initialize GLEW 
    glewExperimental = true; // Needed for core profile 
    if (glewInit() != GLEW_OK) { 
     fprintf(stderr, "Failed to initialize GLEW\n"); 
     getchar(); 
     glfwTerminate(); 
     return -1; 
    } 

    // Ensure we can capture the escape key being pressed below 
    glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE); 

    // Dark blue background 
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 

    GLuint vbo; 
    glGenBuffers(1, &vbo); 
    glBindBuffer(GL_ARRAY_BUFFER, vbo); 

    GLuint num_input_data = width * height; 

    /* Upload data */ 
    glBufferData(GL_ARRAY_BUFFER, num_input_data * sizeof(float) * 3, _image, GL_STATIC_DRAW); 

    GLuint vertexShader, fragmentShader, shaderProgram; 
    // Create and compile the vertex shader 
    vertexShader = glCreateShader(GL_VERTEX_SHADER); 
    glShaderSource(vertexShader, 1, &vertexSource, NULL); 
    glCompileShader(vertexShader); 
    CheckStatus(vertexShader); 
    // Create and compile the fragment shader 
    fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); 
    glShaderSource(fragmentShader, 1, &fragmentSource, NULL); 
    glCompileShader(fragmentShader); 
    CheckStatus(fragmentShader); 
    // Link the vertex and fragment shader into a shader program 
    shaderProgram = glCreateProgram(); 
    glAttachShader(shaderProgram, vertexShader); 
    glAttachShader(shaderProgram, fragmentShader); 
    glBindFragDataLocation(shaderProgram, 0, "outputColor"); 
    glLinkProgram(shaderProgram); 


    CheckStatus(shaderProgram); 

    glUseProgram(shaderProgram); 


    // Specify the layout of the vertex data 
    GLint posAttrib = glGetAttribLocation(shaderProgram, "inPosition"); 
    glEnableVertexAttribArray(posAttrib); 
    glVertexAttribPointer(posAttrib, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), 0); 

    GLuint tex; 
    GLuint fbo; 
    glGenTextures(1, &tex); 
    glBindFramebuffer(GL_FRAMEBUFFER, fbo); 

    glGenFramebuffers(1, &fbo); 
    glActiveTexture(GL_TEXTURE0); 
    // glBindTexture(GL_TEXTURE_2D, tex); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 
    glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32F, 256, 1); 
    // glBindTexture(GL_TEXTURE_2D, 0); 

    glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0); 

    /* Clear buffer */ 
    glClearColor(1.0, 0.0, 0.0, 1.0); 
    glClear(GL_COLOR_BUFFER_BIT); 

    glBlendEquation(GL_FUNC_ADD); 
    glBlendFunc(GL_ONE, GL_ONE); 
    glEnable(GL_BLEND); 

    /* Init viewport */ 
    glViewport(0, 0, 256, 1); 
    glUseProgram(shaderProgram); 
    /* Draw */ 
    glDrawArrays(GL_POINTS, 0, num_input_data); 


    glReadPixels(0, 0, 256, 1, GL_RED, GL_FLOAT, buffer); 

    for (int i = 0; i < 256; ++i) 
    { 
     printf("%d\t%f\t%d\n", i, buffer[i], hist[i]); 
    } 

} 

は、誰が私を助けてもらえ、事前に感謝します。私は自分のコードを更新しました

、それは今働いている:あなたの熱意のために@VallentinするD

#include <stdio.h> 
#include <stdlib.h> 
#include <iostream> 
#include <vector> 
// Include GLEW 
#include <GL/glew.h> 

// Include GLFW 
#include <GLFW/glfw3.h> 
GLFWwindow* window; 

// Include GLM 
#include <glm/glm.hpp> 
using namespace glm; 
#include <SOIL.h> 

// Shader sources 
const GLchar* vertexSource = "\n" 
"#version 330 core\n" 
"in vec3 inPosition;\n" 
"void main()\n" 
"{\n" 
" float x = inPosition.x;\n" 
"\n" 
" gl_Position = vec4(\n" 
"  -1.0 + ((x + 1) * 0.0078125),\n" 
"  0.0,\n" 
"  0.0,\n" 
"  1.0\n" 
" );\n" 
"}\n"; 

const GLchar* fragmentSource = "\n" 
"#version 330 core\n" 
"out vec4 outputColor;\n" 
"void main()\n" 
"{\n" 
" outputColor = vec4(1.0, 1.0, 1.0, 1.0);\n" 
"}\n"; 

void CheckStatus(GLuint obj) 
{ 
    GLint status = GL_FALSE, len = 10; 
    if(glIsShader(obj)) glGetShaderiv(obj, GL_COMPILE_STATUS, &status); 
    if(glIsProgram(obj)) glGetProgramiv(obj, GL_LINK_STATUS, &status); 
    if(status == GL_TRUE) return; 
    if(glIsShader(obj)) glGetShaderiv(obj, GL_INFO_LOG_LENGTH, &len); 
    if(glIsProgram(obj)) glGetProgramiv(obj, GL_INFO_LOG_LENGTH, &len); 
    std::vector<char> log(len, 'X'); 
    if(glIsShader(obj)) glGetShaderInfoLog(obj, len, NULL, &log[0]); 
    if(glIsProgram(obj)) glGetProgramInfoLog(obj, len, NULL, &log[0]); 
    std::cerr << &log[0] << std::endl; 
    exit(-1); 
} 

void _check_gl_error(int line) 
{ 
    GLenum err (glGetError()); 

    while(err!=GL_NO_ERROR) 
    { 
     std::string error; 

     switch(err) 
     { 
      case GL_INVALID_OPERATION:  error="INVALID_OPERATION";  break; 
      case GL_INVALID_ENUM:   error="INVALID_ENUM";   break; 
      case GL_INVALID_VALUE:   error="INVALID_VALUE";   break; 
      case GL_OUT_OF_MEMORY:   error="OUT_OF_MEMORY";   break; 
      case GL_INVALID_FRAMEBUFFER_OPERATION: error="INVALID_FRAMEBUFFER_OPERATION"; break; 
     } 

     std::cerr << "GL_" << error.c_str() <<":"<<line<<std::endl; 
     err=glGetError(); 
    } 
} 

GLfloat buffer[256]; 
GLuint hist[256]; 
float _image[512*512*3]; 

int main() 
{ 
    // Initialise GLFW 
    if(!glfwInit()) 
    { 
     fprintf(stderr, "Failed to initialize GLFW\n"); 
     getchar(); 
     return -1; 
    } 

    glfwWindowHint(GLFW_SAMPLES, 4); 
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); 
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); 
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // To make MacOS happy; should not be needed 
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); 

    int width, height; 
    unsigned char* image = SOIL_load_image("sample_gray.bmp", &width, &height, 0, SOIL_LOAD_RGB); 
    unsigned char* image_gray = new unsigned char[width * height]; 

    printf("%d\t%d\n", width, height); 


    for (int i = 0; i < width * height; ++i) 
    { 
     image_gray[i] = image[i * 3]; 
     _image[i * 3] = image[i * 3]; 
     _image[i * 3 + 1] = image[i * 3 + 1]; 
     _image[i * 3 + 2] = image[i * 3 + 2]; 
    } 

    for (int i = 0; i < width * height; ++i) 
    { 
     hist[image_gray[i]]++; 
    } 

    // Open a window and create its OpenGL context 
    window = glfwCreateWindow(width, height, "Basic", NULL, NULL); 
    if(window == NULL){ 
     fprintf(stderr, "Failed to open GLFW window. If you have an Intel GPU, they are not 3.3 compatible. Try the 2.1 version of the tutorials.\n"); 
     getchar(); 
     glfwTerminate(); 
     return -1; 
    } 
    glfwMakeContextCurrent(window); 

    // Initialize GLEW 
    glewExperimental = true; // Needed for core profile 
    if (glewInit() != GLEW_OK) { 
     fprintf(stderr, "Failed to initialize GLEW\n"); 
     getchar(); 
     glfwTerminate(); 
     return -1; 
    } 
    _check_gl_error(__LINE__); 
    // Ensure we can capture the escape key being pressed below 
    glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE); 

    // Dark blue background 
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 


    GLuint vao; 
    glGenVertexArrays(1, &vao); 
    glBindVertexArray(vao); 

    GLuint vbo; 
    glGenBuffers(1, &vbo); 
    glBindBuffer(GL_ARRAY_BUFFER, vbo); 

    GLuint num_input_data = width * height; 

    /* Upload data */ 
    glBufferData(GL_ARRAY_BUFFER, num_input_data * sizeof(float) * 3, _image, GL_STATIC_DRAW); 

    GLuint vertexShader, fragmentShader, shaderProgram; 
    // Create and compile the vertex shader 
    vertexShader = glCreateShader(GL_VERTEX_SHADER); 
    glShaderSource(vertexShader, 1, &vertexSource, NULL); 
    glCompileShader(vertexShader); 
    CheckStatus(vertexShader); 
    // Create and compile the fragment shader 
    fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); 
    glShaderSource(fragmentShader, 1, &fragmentSource, NULL); 
    glCompileShader(fragmentShader); 
    CheckStatus(fragmentShader); 
    // Link the vertex and fragment shader into a shader program 
    shaderProgram = glCreateProgram(); 
    glAttachShader(shaderProgram, vertexShader); 
    glAttachShader(shaderProgram, fragmentShader); 
    glBindFragDataLocation(shaderProgram, 0, "outputColor"); 
    glLinkProgram(shaderProgram); 


    CheckStatus(shaderProgram); 

    glUseProgram(shaderProgram); 


    // Specify the layout of the vertex data 
    GLint posAttrib = glGetAttribLocation(shaderProgram, "inPosition"); 
    glEnableVertexAttribArray(posAttrib); 
    glVertexAttribPointer(posAttrib, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), 0); 

    GLuint tex; 
    GLuint fbo; 
    glGenFramebuffers(1, &fbo); 
    glBindFramebuffer(GL_FRAMEBUFFER, fbo); 

    glGenTextures(1, &tex); 
    glActiveTexture(GL_TEXTURE0); 
    glBindTexture(GL_TEXTURE_2D, tex); 
    glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, 256, 1, 0, GL_RED, GL_FLOAT, NULL); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 
    // glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32F, 256, 1); 

    glBindTexture(GL_TEXTURE_2D, 0); 

    glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0); 

    glBindFramebuffer(GL_FRAMEBUFFER, 0); 

    _check_gl_error(__LINE__); 

    glBindFramebuffer(GL_FRAMEBUFFER, fbo); 
    /* Clear buffer */ 
    glClearColor(0.0, 0.0, 0.0, 1.0); 
    glClear(GL_COLOR_BUFFER_BIT); 

    glBlendEquation(GL_FUNC_ADD); 
    glBlendFunc(GL_ONE, GL_ONE); 
    glEnable(GL_BLEND); 
    _check_gl_error(__LINE__); 


    /* Init viewport */ 
    glViewport(0, 0, 256, 1); 
    glUseProgram(shaderProgram); 
    /* Draw */ 
    glDrawArrays(GL_POINTS, 0, num_input_data); 


    glReadPixels(0, 0, 256, 1, GL_RED, GL_FLOAT, buffer); 
    _check_gl_error(__LINE__); 
    for (int i = 0; i < 256; ++i) 
    { 
     printf("%d\t%f\t%d\n", i, buffer[i], hist[i]); 
    } 
    free(image_gray); 
} 

特別感謝を!

+0

私が見る最初のことは、生成する前に 'fbo'をバインドすることです。 Second:あなたの 'CheckStatus'メソッドは、同じidを持つシェーダオブジェクトとシェーダプログラムがない場合にのみ動作します。すべてのハンドルは符号なしの整数であり、OpenGL実装がシェーダオブジェクト0とシェーダプログラムオブジェクト0を与えるのは完全に有効です。その場合、メソッドはリンクステータスとコンパイルステータスの両方を照会します。 – BDL

+0

@BDL、ありがとうございます。私は以下のコードを更新しました。もう一度それをチェックするのを助けてくれる? –

答えて

2

ヒストグラムバッファは常にゼロを返します。

興味深い。あなたがする必要があると思い

int width, height; 
unsigned char* image = SOIL_load_image("sample_gray.bmp", &width, &height, 0, SOIL_LOAD_RGB); 
unsigned char image_gray[width * height]; 

::私がすることで、このハエのようにしましょうコンパイラ何かを知らないので

unsigned char *image_gray = new unsigned char[width * height]; 

後でメモリdelete[] image_grayを解放することを忘れないでください。

あなたのシェーダもコンパイルされません。あるいは、あなたのドライバが私のものより少し傾いているかもしれません。 #version 330 coreのようにattributeを使用することはできず、inを使用する必要があります。

in vec3 inPosition; 

CheckStatus()であるとしてこれを伝えます:

0(3) : error C7555: 'attribute' is deprecated, use 'in/out' instead 

また、あなたはしても、まだ持っていないフレームバッファをバインドしようとしています。

GLuint fbo; 
glBindFramebuffer(GL_FRAMEBUFFER, fbo); 
[...] 
glGenFramebuffers(1, &fbo); 

あなたはその周りに反転させる必要があるだろう:それはまた私を困惑

GLuint fbo; 
glGenFramebuffers(1, &fbo); 
glBindFramebuffer(GL_FRAMEBUFFER, fbo); 

MSVCは私を叫ぶよう、あなたのコンパイラは、そのスライドを聞かせする理由。

Error C4700 uninitialized local variable 'fbo' 

また、それに変更を適用する前にテクスチャを結合していません。

// glBindTexture(GL_TEXTURE_2D, tex); 

glBindTexture()のコメントを外してください。

また、頂点配列も作成していません。どちらのチェックglGetError()が言ったでしょうか。

GLuint vao; 
glGenVertexArrays(1, &vao); 
glBindVertexArray(vao); 

glEnableVertexAttribArray()に電話する前に行ってください。

また、あなたのクリアカラーは赤です。だからこそ、それほど助けにならないでしょう。今のところglReadPixels()への電話は1.0にしかなりません。

glClearColor(0.0, 0.0, 0.0, 1.0) 

ここで、glReadPixels()は依然としてゼロのみを返す。ただし、フレームバッファをアンバインドしたり作成したりしないでください。そして、それは私が望む結果が得られるものを与えます。フレームバッファを使用してはいけないので、私はそこに何か問題があると思っています。私はあなたのコードを見渡すことでそれを指摘することはできません。しかし、コードには既に問題が詰まっているので、これは公正な出発点です。

追加:glTexStorage2D()は4.2の中核である一方、

  • あなたは、OpenGL 3.3をターゲットにしています。ポイントは、glTexStorage2D()がサポートされていることを確認したい場合は、ターゲットを4.2にします。
  • glActiveTexture()への呼び出しは冗長です。
  • テクスチャの高さが1であるため、1Dテクスチャの使用を検討してください。
  • あなたは、ウィンドウ(およびコンテキスト)を作成した前_check_gl_error()を呼び出すことはできませんまず第一に、まだ編集Debug Output

を利用

glGetError()以上をチェックすることを忘れないでくださいとglewInit()と呼ばれます。

手動で行番号を追加する代わりに、__LINE__を使用できます。従って_check_gl_error(__LINE__)

もう一度赤いクリアカラーを使用しないでください。黒のクリアカラーglClearColor(0.0, 0.0, 0.0, 1.0)を使用してください。 をブレンドすると、0.1の結果は1.1になり、1.0に戻ってクランプされます。従って、赤色チャネルは、get-goから0.0になるはずです。

私はこの問題を認識しました。頂点シェーダーで手動でy-1.0に設定しています。これは、GL_POINTSを描いているので、スクリーンから落ちることになります。 y-0.9999に設定すると、今すぐ望ましい結果が得られているようです。しかし、これに頼るのは火事で遊ぶようなものです。

今アプリケーションを実行すると、0.01.0の混合が表示されます。 1.0を得る理由は、フラグメントシェーダーで1.0という赤いチャンネルの場合はoutputColorに設定されているためです。すべてのものを合計すると、いくらか狂った価値があるかもしれませんが、最後には1.0にクランプされます。

代わりにしてみてください:今、あなたの代わりに0.0または1.0のいずれかであることの、出力が増減見るべき

outputColor = vec4(0.005, 1.0, 1.0, 1.0); 

。ただし、hist[i]が200より大きい場合は、1.0となります。 1/0.005 = 200です。

すべては少なくともの作業です。

+0

@Vallentinさんへの返信ありがとうございます。私は推奨するポイントで自分のコードを更新しました。エラーをチェックするために 'glGeterror()'を使って '_check_gl_error'関数を追加します。しかし、私のバッファーはまだ0を返す(あなたが言ったように私は色を赤色にクリアすれば1.0)。私のコードをもう一度チェックできますか?ありがとうございました。もう一つ、他の関数に関数 'glTexStorage1D'を置き換えることができますか? –

+0

@ tiena2cva私の編集をチェックしてください。もちろん@BDLは – Vallentin

+1

です。 Typo and fixed;) – Vallentin

関連する問題