背景:
我原來的工程是使用opencv的,所以程序中的圖像都是表示為cv::Mat類型,為了能夠在imgui窗口中顯示我的cv::Mat的圖像,我找到了下面這個函數:
void ImGui::Image(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1,const ImVec4& tint_col, const ImVec4& border_col)
上面這個函數負責在imgui中的窗口中顯示圖像。但是需要先將我的cv::Mat類型的圖像轉換為這個的ImTextureID類型。可以通過下面這個函數來實現上述功能。
cv::Mat& image為待轉換的cv::Mat圖像,GLuint& imageTexture就是ImGui::Image()函數中需要的類型。
void Mat2Texture(cv::Mat& image, GLuint& imageTexture) {if (image.empty()) {std::cout << "image is empty! " << std::endl;return;}else {//generate texture using GL commandsglGenTextures(1, &imageTexture);glBindTexture(GL_TEXTURE_2D, imageTexture);glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);glTexImage2D(GL_TEXTURE_2D,0,GL_BGRA,image.cols,image.rows,0,GL_RGBA,GL_UNSIGNED_BYTE,image.data); }}
函數說明:
//用來產生你要操作的紋理對象的索引
//n:用來生成紋理的數量
//texture:用于存儲紋理索引
glGenTextures(GLsizei n, GLuint *textures);
//glBindTexture實際上改變了OpenGL的這個狀態,他告訴OpenGL下面對紋理的操作都是對他綁定的紋理對象的
//比如下面這里,就是在告訴opengl下面代碼中對2D紋理的任何操作都是針對索引imageTexture的紋理的。
glBindTexture(GL_TEXTURE_2D, imageTexture);
注意事項1:
函數glGenTextures(GLsizei n, GLuint *textures);只能放在循環外面使用,否則當程序循環次數多了以后,程序很吃內存,電腦會變得越來越卡,我剛開始沒有注意這個問題,將Mat2Texture函數放在了while循環里面,眼看著我的內存占用率直線上升。這是因為Mat2Texture函數中的glGenTextures函數被反復調用。而我需要將視頻流數據源源不斷的更新到imgui的窗口中,所以我需要循環調用Mat2Texture函數。那么我可以將函數換成下面的形式。
我只需要在窗口初始化的時候,反正就是在while循環的外面先執行一遍:
glGenTextures(1, &imageTexture);
然后把下面的函數放在while循環中就可以了。
void Mat2Texture(cv::Mat& image, GLuint& imageTexture) {if (image.empty()) {std::cout << "image is empty! " << std::endl;return;}else {//generate texture using GL commandsglBindTexture(GL_TEXTURE_2D, imageTexture);glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);glTexImage2D(GL_TEXTURE_2D,0,GL_BGRA,image.cols,image.rows,0,GL_RGBA,GL_UNSIGNED_BYTE,image.data); }}
注意事項2:
在函數Mat2Texture中的glTextImage2D()函數中我使用的是GL_BGRA和GL_RGBA參數,其實我在將調用Mat2Texture函數之前對image圖像進行如下操作:
cv::cvtColor(image, image, cv::COLOR_RGB2BGRA);
就是將RGB模式轉換為BGRA模式。明顯的區別是把之前的三通道圖像轉換成四通道圖像,如果不這樣做,有些圖像無法正常的呈現在imgui的窗口中,但是有些圖像也是可以的。我也試過BGR2BGRA和RGB2RGBA的形式,但是得到的圖像顏色不對,所以你在將cv::Mat轉換為Texture時,如果遇到這樣的問題可以試一下我上面的方法。