openGL版本:3.3
openGL库:glfw,glad,glm
openGL初始化环境和各个openGL库的配置可以在本人的另一篇博客中看到,地址为:
https://blog.csdn.net/xiechaoyi123/article/details/85138518
实现resize的流程如下:
1)初始化窗口和顶点着色器,片段着色器:
GLFWwindow*window = init(ScreenWidth, ScreenHeight);
float vertices[] = {
1.0f, 1.0f, 1.0f, 1.0f, // top right
1.0f, -1.0f, 1.0f, 0.0f, // bottom right
-1.0f, 1.0f, 0.0f, 1.0f, // top left
1.0f, -1.0f, 1.0f, 0.0f, // bottom right
-1.0f, -1.0f,0.0f, 0.0f, // bottom left
-1.0f, 1.0f,0.0f, 1.0f // top left
};
std::vector<int> params(2, 2);
unsigned int VAO1, VBO1;
initVAO(VAO1, VBO1, vertices, 6, params);
Shader resizeShader("resize.vs", "resize.fs");
其中第一个函数为初始化openGL窗口,具体函数如下:
GLFWwindow* init(int width,int height)
{
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);//主版本号
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);//次版本号
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);//使用核心模式
#ifdef __APPLE__
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // uncomment this statement to fix compilation on OS X
#endif
GLFWwindow*window = glfwCreateWindow(width, height, "LearnOpenGL", NULL, NULL);//创建窗口,设置窗口大小
if (window == NULL)
{
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return NULL;
}
glfwMakeContextCurrent(window);//将窗口的上下文设置为当前线程的主上下文
//视口回调函数,这样OpenGL才知道怎样根据窗口大小显示数据和坐标
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))//初始化GLAD
{
std::cout << "Failed to initialize GLAD" << std::endl;
return NULL;
}
return window;
}
第二个函数是初始化VAO,VBO:
void initVAO(unsigned int& VAO,unsigned int& VBO,float* vertextices,const int& num,std::vector<int>& vertexParams)
{
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
int numPart = vertexParams.size();
int numAll = 0;
for (int i = 0; i < numPart; ++i)
numAll += vertexParams[i];
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*numAll*num, vertextices, GL_STATIC_DRAW);
int offset = 0;
for (int i = 0; i < numPart; ++i)
{
if (i != 0)
offset += vertexParams[i-1];
glVertexAttribPointer(i, vertexParams[i], GL_FLOAT, GL_FALSE, numAll * sizeof(float), (void*)(offset * sizeof(float)));
glEnableVertexAttribArray(i);
}
}
接下来是初始化shader,具体实现可以参照这篇博客
2)上传本地图像到GPU中,即声明和初始化纹理,首先声明纹理id:
unsigned int texture;
glGenTextures(1, &texture);
然后通过opencv读取的图像img初始化该纹理:
void GenTextureByMat(unsigned int& texture,const cv::Mat& img)
{
glBindTexture(GL_TEXTURE_2D, texture);
// set the texture wrapping parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
// set texture filtering parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, img.cols, img.rows, 0, GL_RGB,GL_UNSIGNED_BYTE, img.data);
glGenerateMipmap(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);
}
3)创建渲染窗口:
resizeShader.use();
resizeShader.setInt("texture", 0);
{
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// bind textures on corresponding texture units
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
resizeShader.use();
// render container
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glfwSwapBuffers(window);//交换颜色缓冲
glfwPollEvents();//检查有没有出发什么事件(比如键盘输入、鼠标移动等)。
}
若是要使得得到的结果一直显示而不是一闪而过,需要在上面这段程序的中括号的上面加上这一句话:
while (!glfwWindowShouldClose(window))
{
//add samething
.......
}
4)实现shader,其中顶点着色器文件resize.vs如下:
#version 330 core
layout (location = 0) in vec2 aPos;
layout (location = 1) in vec2 aTexCoord;
out vec2 TexCoord;
void main()
{
gl_Position = vec4(aPos.x,aPos.y,0.0, 1.0f);
TexCoord = vec2(aTexCoord.x, aTexCoord.y);
}
aPos对应1)中vertices[]中的位置信息,是一个二维float型数组,aTexCoord对应纹理信息
片段着色器resize.fs的实现,由于opencv中的resize函数有多种插值方式,默认的是CV_INTER_LINER(双线性插值),
还有CV_INTER_NN(最近邻插值),CV_INTER_AREA(区域插值),还有其他的插值方式,最常用的是就是这三种。
由于openGL中的纹理坐标和纹理(uchar型纹理)像素值都是在[0,1)之间,所以需要对opencv的像素坐标进行归一化,下面实现opencv先最近邻方式resize到目标图像的4倍大小,再以区域插值的方式resize成目标图像:
#version 330 core
out vec4 fragColor;
in vec2 TexCoord;
uniform sampler2D img;
void main() {
int srcwidth = 1000,srcheight = 1000;
int scale = 4;
int width = 100,height=100,swidth = scale*width,sheight = scale*height;
int scale2 = scale*scale;
vec2 tmp;
vec3 tmp1;
tmp1.x=0,tmp1.y=0,tmp1.z=0;
for(int i=0;i<scale;++i)
{
for(int j=0;j<scale;++j)
{
tmp.x = TexCoord.x+(i)/float(swidth);
tmp.y = TexCoord.y+(j)/float(sheight);
tmp1 += texture(img,tmp).rgb;
}
}
tmp1 /= scale2;
fragColor = vec4(tmp1,1.0f);
}
OK,完成工作!
今天的文章openGL 实现opencv的resize函数分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/30667.html