openGL 实现opencv的resize函数

openGL 实现opencv的resize函数openGL版本:3.3openGL库:glfw,glad,glmopenGL初始化环境和各个openGL库的配置可以在本人的另一篇博客中看到,地址为:https://blog.csdn.net/xiechaoyi123/article/details/85138518实现resize的流程如下:1)初始化窗口和顶点着色器,片段着色器:GLFWwindow*window…

openGL

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

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注