2013-05-29 24 views
8

OpenGV Texture ile OpenCV (jpg ve png) içeren bir resim yüklemek istiyorum. İşteOpenGL Texture için OpenCV resmi yükleme

Ben OpenGL'ye resim yüklemek nasıl: Her zaman döndürür "image.empty" olarak, görüntü yüklenir

glEnable(GL_TEXTURE_2D); 
    textureData = loadTextureData("textures/trashbin.png"); 
    cv::Mat image = cv::imread("textures/trashbin.png"); 
    if(image.empty()){ 
     std::cout << "image empty" << std::endl; 
    }else{ 
     glGenTextures(1, &textureTrash); 
     glBindTexture(GL_TEXTURE_2D, textureTrash); 
     glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); 
     glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); 
     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S , GL_REPEAT); 
     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 
     glTexImage2D(GL_TEXTURE_2D,0,3,image.cols, image.rows,0,GL_RGB,GL_UNSIGNED_BYTE, image.data); 
    } 

yanlış

İşte

benim yarattığım doku kullanarak sahne işlemek nasıl : Ben geometrisine doku uygulamak istediğiniz

glActiveTexture(GL_TEXTURE0); 
    glBindTexture(GL_TEXTURE_2D, textureTrash); 
    glm_ModelViewMatrix.top() = glm::translate(glm_ModelViewMatrix.top(),0.0f,-13.0f,-10.0f); 
    glUniformMatrix4fv(uniformLocations["modelview"], 1, false, glm::value_ptr(glm_ModelViewMatrix.top())); 

    std::cout << "textureShaderID: " << glGetUniformLocation(shaderProgram,"texture") << std::endl; 

    glUniform1i(glGetUniformLocation(shaderProgram,"texture"), 0); 
    objLoader->getMeshObj("trashbin")->render(); 

Ve nihayet fragmentShader

#version 330 
in vec2 tCoord; 

// texture // 
// TODO: set up a texture uniform // 
uniform sampler2D texture; 

// this defines the fragment output // 
out vec4 color; 

void main() { 
    // TODO: get the texel value from your texture at the position of the passed texture coordinate // 
    color = texture2D(texture, tCoord); 
} 

Doku koordinatları Vertex Arabellek Nesnesinden geliyor ve .obj dosyasından doğru şekilde ayarlanıyor. Ayrıca, rengi, örn. fragman gölgelendiricisinde kırmızı veya vec4'e (tCoord, 0,1); sonra nesne farklı renkte gölgelenir.

Doku uygulamak istediğimde ekran siyah renkte kalıyor ... Birisi bana yardım edebilir ve bana neden siyah kaldığını söyleyebilir mi?

cevap

16

Sadece doku yükleme kodunuza bakarak, OpenCV'nin bellekte görüntülerin nasıl yerleştirileceğiyle ilgili birçok noktayı göz ardı ediyorsunuz. Zaten izah ettik this answer içinde (OpenCV görüntü içine glGetTexImage) ters yönde için değil CV-GL yön için burada özetlemek olacak: neccessarily mağaza görüntü satırları sıkıca paketlenmiş gelmez tüm OpenCV ait

İlk ancak o bunları belirli bayt sınırlarına göre hizalayın (ne kadar, en az 4, fakat belki 8 veya daha fazla bir şey bilmiyor musunuz?). Şansınız varsa, 4 bayt hizalama kullanır ve GL, 4 baytlık hizalamanın varsayılan piksel depolama moduna da ayarlanır.

//use fast 4-byte alignment (default anyway) if possible 
glPixelStorei(GL_UNPACK_ALIGNMENT, (image.step & 3) ? 1 : 4); 

//set length of one complete row in data (doesn't need to equal image.cols) 
glPixelStorei(GL_UNPACK_ROW_LENGTH, image.step/image.elemSize()); 

Sonra yukarıdan aşağıya doğru OpenCV saklar görüntüler, GL için dibe kullanırken gerçeği hesaba sahip: Ama elle güvenli tarafta olmak amacıyla piksel depolama modları ile keman en iyisi üst. Bu sadece koordinat uygun (belki doğrudan gölgelendiricideki) t-dokusunu yansıtma yoluyla halledilir olabilir, ama aynı zamanda sadece yüklemeden önce resmi çevirmek olabilir:

cv::flip(image, flipped, 0); 
image = flipped;    //maybe just cv::flip(image, image, 0)? 

Son olarak OpenCV saklar renkli görüntüler içinde BGR formatı bu yüzden RGB olarak yüklemek renkleri bozar.'da GL_BGR kullanın (OpenGL 1.2 gerektirir, ancak kimin sahip değil?).

Sorununuza tam bir çözüm bu olmayabilir (çünkü bu hataların siyah bir görüntü yerine çarpık bir sonuçla sonuçlanması gerektiğini düşünüyorum), ancak bunların üstesinden gelmek kesinlikle sorunlardır.

DÜZENLEME: Parça gölgelendiriciniz gerçekten (derlemeyi kullanarak tam sürümde) derliyor mu? Ben soruyorum çünkü GLSL 3.30 kullandığınız kelime texture da dahili bir fonksiyonun adıdır (aslında kullanılmayan texture2D işlevinin yerine kullanılmalıdır), belki de derleyici bazı ad çözümleme problemlerine sahiptir. basitleştirilmiş gölgelendiricilerinizde bu hata göz ardı edilir; ünkü tüm üniforma en iyi duruma getirilir ve birçok GLSL derleyicisinin katı standartlara uygunluktan başka bir şey olduğu bilinir). Yani bu örnekleyici üniformasını farklı bir isim vermeye çalışın.

8

İşte burada çalışma çözümüm - "Christan Rau" nun fikirlerine dayanıyor - Bunun için teşekkürler!

cv::Mat image = cv::imread("textures/trashbin.png"); 
    //cv::Mat flipped; 
    //cv::flip(image, flipped, 0); 
    //image = flipped; 
    if(image.empty()){ 
     std::cout << "image empty" << std::endl; 
    }else{ 
     cv::flip(image, image, 0); 
     glGenTextures(1, &textureTrash); 
     glBindTexture(GL_TEXTURE_2D, textureTrash); 

     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 

     // Set texture clamping method 
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); 
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); 


     glTexImage2D(GL_TEXTURE_2D,  // Type of texture 
        0,     // Pyramid level (for mip-mapping) - 0 is the top level 
        GL_RGB,   // Internal colour format to convert to 
        image.cols,   // Image width i.e. 640 for Kinect in standard mode 
        image.rows,   // Image height i.e. 480 for Kinect in standard mode 
        0,     // Border width in pixels (can either be 1 or 0) 
        GL_BGR, // Input image format (i.e. GL_RGB, GL_RGBA, GL_BGR etc.) 
        GL_UNSIGNED_BYTE, // Image data type 
        image.ptr());  // The actual image data itself 

     glGenerateMipmap(GL_TEXTURE_2D); 
    } 
+1

Bu şekilde mi çalışıyor? Bu arada, filtre ve sıkma modlarını neden değiştirdiniz? Ve bir mipmapping filtresi kullanmıyorken neden mipmap oluşturuyorsunuz? –

+0

Evet, bu şekilde çalışıyor - Kesinlikle en iyi çözüm değil ve geliştirmek için çok fazla potansiyele sahip - Ama çalışıyor - Ve mipmap'ler bir sonraki özellik olarak uygulanacak, ben sadece kullanıyorum satır – glethien

+0

kaldırmak unuttum Görüntünüzü gösterme yönteminiz, ancak image.ptr() işlevini kullanmak için okuma erişimi ihlali yapıyorum. Lütfen gönderimi buradan görebilirsiniz: https://stackoverflow.com/questions/45013214/qt-signal-slot-cvmat-unable-to-read-memory-access-violation#45014271 – Pete