本篇主要是講使用Opencv導入一副圖片,然后講該副圖片當成紋理顯示在opengl當中。
-
首先說如何配置Opencv
我的硬件環境是: Windows10+Visual Studio 2015+opencv3.0
先在此網站下載opencv,下載之后,它是長這樣的,點擊它,會自動解壓縮成名字為“opencv”的文件夾
接下來進行環境配置:從控制面板開始,按着這個路徑 Control Panel\System and Security\System 來到高級系統設置(advanced system settings)就進入了如下界面:
在系統變量里面找到Path,然后在Value中添加OpenCV的目錄:我的是:C:\Users\Dell\Downloads\opencv\build\x86\vc12\bin。(我的opencv直接保存在了downloads里面)
然后你新建一個VS2015的項目(新建項目方法我就不說了),然后點擊:項目--->屬性--->配置屬性--->VC++目錄----->包含目錄
把下面這些目錄添加進去:
C:\Users\Dell\Downloads\opencv\build\include
C:\Users\Dell\Downloads\opencv\build\include\opencv
C:\Users\Dell\Downloads\opencv\build\include\opencv2
最后大概長這樣:
再在庫目錄中添加這些目錄:
C:\Users\Dell\Downloads\opencv\build\x86\vc12\lib
C:\Users\Dell\Downloads\opencv\build\x86\vc12\staticlib
注意:你可以發現我這里面用的是x86架構,其實opencv里面還給了x64架構。這主要取決於你的項目用的是什么架構,可以看這里來判斷
最后一步:
點擊鏈接器---> 輸入---->附加依賴項中加入:
opencv_ts300.lib; opencv_world300.lib
至此 opencv就配置好了。你當然也要配置opengl,但是這里我就不說了。
2. 圖片作為紋理在opengl中顯示
先把要用的資源圖片放在你VS項目中的目錄中,與cpp文件一個目錄下面。
請復制一下代碼:
#include<gl/glut.h> #include <opencv.hpp> using namespace cv; //OpenCV讀取圖像 Mat I = imread("ntulogo.bmp"); //設置長寬 int width = I.cols; int height = I.rows; //設置圖像指針 GLubyte* pixels; GLuint load_texture() { //OpenGL紋理用整型數表示 GLuint texture_ID; //獲取圖像指針 int pixellength = width*height * 3; pixels = new GLubyte[pixellength]; memcpy(pixels, I.data, pixellength * sizeof(char)); imshow("OpenCV", I); //將texture_ID設置為2D紋理信息 glGenTextures(1, &texture_ID); glBindTexture(GL_TEXTURE_2D, texture_ID); //紋理放大縮小使用線性插值 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); //紋理水平豎直方向外擴使用重復貼圖 //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); //紋理水平豎直方向外擴使用邊緣像素貼圖(與重復貼圖二選一) //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); //將圖像內存用作紋理信息 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_BGR_EXT, GL_UNSIGNED_BYTE, pixels); free(pixels); return texture_ID; } void display() { // 清除屏幕 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //獲取紋理對象 GLuint image = load_texture(); //重新設置OpenGL窗口:原點位置為左上角,x軸從左到右,y軸從上到下,坐標值與像素坐標值相同 glViewport(0, 0, (GLsizei)width, (GLsizei)height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0, width, height, 0); //顯示紋理 glEnable(GL_TEXTURE_2D); //允許使用紋理 glBindTexture(GL_TEXTURE_2D, image); //選擇紋理對象 //原始完全填充四邊形 glBegin(GL_POLYGON); //設置為多邊形紋理貼圖方式並開始貼圖 glTexCoord2f(0.0f, 0.0f); glVertex2f(0, 0); //紋理左上角對應窗口左上角 glTexCoord2f(0.0f, 1.0f); glVertex2f(0, height); //紋理左下角對應窗口左下角 glTexCoord2f(1.0f, 1.0f); glVertex2f(width, height); //紋理右下角對應窗口右下角 glTexCoord2f(1.0f, 0.0f); glVertex2f(width, 0); //紋理右上角對應窗口右上角 glEnd(); //結束貼圖*/ /*//三角形 glBegin(GL_POLYGON); glTexCoord2f(0.0f, 0.0f); glVertex2f(0, 0); glTexCoord2f(0.0f, 1.0f); glVertex2f(0, height); glTexCoord2f(1.0f, 1.0f); glVertex2f(width, height); glEnd();*/ /* //多邊形 glBegin(GL_POLYGON); glTexCoord2f(0, 0); glVertex2f(0, 0); glTexCoord2f(0, 1); glVertex2f(0, height/3); glTexCoord2f(1, 1); glVertex2f(width/4, height/3); glTexCoord2f(1, 0); glVertex2f(width/4, 0); glTexCoord2f(0.0f, 0.5f); glVertex2f(0, height/2); glEnd();*/ /*//任意變換 glBegin(GL_POLYGON); glTexCoord2f(0.0f, 0.0f); glVertex2f(width/4, height/4); glTexCoord2f(0.0f, 1.0f); glVertex2f(0, height); glTexCoord2f(1.0f, 1.0f); glVertex2f(width, height*2/3); glTexCoord2f(1.0f, 0.0f); glVertex2f(width*4/5, 50); glEnd();*/ //邊緣貼圖效果 /*glBegin(GL_POLYGON); glTexCoord2f(0.0f, 0.0f); glVertex2f(0, 0); glTexCoord2f(0.0f, 2.0f); glVertex2f(0, height); glTexCoord2f(2.0f, 2.0f); glVertex2f(width, height); glTexCoord2f(2.0f, 0.0f); glVertex2f(width, 0); glEnd();*/ glDisable(GL_TEXTURE_2D); //禁止使用紋理 //雙緩存交換緩存以顯示圖像 glutSwapBuffers(); } void main(int argc, char** argv) { //初始化GL glutInit(&argc, argv); //設置顯示參數(雙緩存,RGB格式) glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB); //設置窗口尺寸:width*height glutInitWindowSize(width, height); //設置窗口位置:在屏幕左上角像素值(100,100)處 glutInitWindowPosition(100, 100); //設置窗口名稱 glutCreateWindow("OpenGL"); //顯示函數,display事件需要自行編寫 glutDisplayFunc(display); //重復循環GLUT事件 glutMainLoop(); }
最后你會看到這個結果:
3. 再說幾個小問題
如果在opengl中,你在使用貼紋理之前,有使用過glColor函數,就會影響到接下來的貼圖,例如:我前面使用過了glColor3f(1,0,0).那么我的紋理圖就會變成這樣:
所以,需要在紋理貼圖之前,寫一句glColor3f(1,1,1)
其次如果你的項目中用到了光照,那這個光照可能會影響到紋理的顯示,就會變暗。
解決方法是在畫紋理的前后加上,關閉光照和打開光照這兩句話,即:
glDisable(GL_LIGHTING);
glEnable(GL_LIGHTING);
還有不懂之處,請參考一下參考網站
reference:
1. https://zhuanlan.zhihu.com/p/24714986?refer=ry000
2. http://blog.csdn.net/lanergaming/article/details/48689841
3. https://learnopengl-cn.readthedocs.io/zh/latest/01%20Getting%20started/06%20Textures/