openGL 实现opencv的resize函数

本文详细介绍了使用OpenGL和其相关库(如glfw, glad和glm)进行图像缩放的方法。从初始化OpenGL环境到实现图像的最近邻插值和区域插值缩放,包括顶点着色器和片段着色器的编写,以及如何利用OpenCV处理图像数据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

openGL版本:3.3

openGL库:glfw,glad,glm

openGL初始化环境和各个openGL库的配置可以在本人的另一篇博客中看到,地址为:

https://blog.youkuaiyun.com/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,完成工作!

<think>我们正在讨论的是不同编程环境中的resize函数,根据引用内容,resize函数在多个库和语言中都有出现。用户的问题是关于如何使用resize函数,并希望得到语法和示例。根据引用,我们可以从以下几个方面回答:1.OpenCV-Python中的resize函数(用于图像处理)2.C++STL中vector容器的resize函数(用于调整容器大小)3.其他可能相关的resize函数(如MATLAB中的print函数涉及调整图形大小,但用户主要关注的是resize函数,所以重点在前两者)此外,用户上一次的问题是关于EasyX库修改窗口大小,但当前问题转向了resize函数的使用,因此我们应专注于当前问题。下面将分别介绍OpenCV和C++STL中resize函数的用法。###OpenCV-Python中的resize函数引用[1]提到,在OpenCV-Python中,`cv2.resize()`函数用于调整图像大小。**语法:**```pythonresized_image=cv2.resize(src,dsize[,dst[,fx[,fy[,interpolation]]]])```**参数说明:**-`src`:输入图像-`dsize`:输出图像的大小,格式为`(width,height)`-`fx`:水平缩放因子(可选)-`fy`:垂直缩放因子(可选)-`interpolation`:插值方法(可选),默认为`cv2.INTER_LINEAR`**注意:**可以通过直接指定`dsize`或者通过`fx`和`fy`缩放因子来调整图像大小。如果指定了`dsize`,则忽略`fx`和`fy`。**示例:**```pythonimportcv2#读取图像image=cv2.imread('image.jpg')#方法1:直接指定目标尺寸resized1=cv2.resize(image,(800,600))#方法2:使用缩放因子(宽度和高度都缩小到原来的一半)resized2=cv2.resize(image,None,fx=0.5,fy=0.5)#显示结果cv2.imshow('Resizedbydsize',resized1)cv2.imshow('Resizedbyfxandfy',resized2)cv2.waitKey(0)cv2.destroyAllWindows()```###C++STL中vector的resize函数引用[2][3]提到,C++STL中`std::vector`的`resize()`函数用于调整容器的大小。**语法:**```cppvoidresize(size_typecount);voidresize(size_typecount,constvalue_type&value);```**参数说明:**-`count`:新的容器大小(元素个数)-`value`:当需要增加元素时,用此值初始化新元素(可选,默认为值初始化)**注意:**-如果当前大小大于`count`,则减小容器到`count`,多余的元素被销毁。-如果当前大小小于`count`,则增加元素到`count`,新增元素用`value`初始化(如果提供了`value`)或进行值初始化(默认)。**示例:**```cpp#include<iostream>#include<vector>intmain(){std::vector<int>nums={1,2,3,4,5};//将大小调整为3(删除末尾两个元素)nums.resize(3);//输出:123for(intnum:nums){std::cout<<num<<"";}std::cout<<std::endl;//将大小调整为5,新增元素为0nums.resize(5,0);//输出:12300for(intnum:nums){std::cout<<num<<"";}std::cout<<std::endl;return0;}```###其他环境中的resize函数-**MATLAB**:引用[4]提到了MATLAB中print函数可以调整图形大小,但这不是一个名为resize函数。MATLAB中调整图像大小通常使用`imresize`函数,但不在本次引用范围内,所以不展开。###总结1.**OpenCVresize**:主要用于图像缩放,可以通过目标尺寸或缩放因子来控制。2.**C++vector的resize**:用于调整容器大小,可以指定新的大小和新增元素的初始值。根据用户上一次的问题(EasyX库修改窗口大小)和当前问题(resize函数),我们提供了上述两种常见用法。如果用户有特定环境的需求,可以进一步说明。---###📚相关问题1.OpenCV中图像缩放的插值方法有哪些?2.C++vector的resize和reserve有什么区别?3.如何在Python中调整列表的大小?4.在OpenGL中如何实现窗口大小调整时的图像缩放?[^1]:OpenCV-Python中的resize函数[^2]:C++STLvector的resize函数[^3]:vector::resize()函数说明[^4]:MATLAB中图形调整大小的方法</think>### Resize 函数使用方法详解 在不同编程环境中,`resize()` 函数的功能和用法有所不同。以下是主要应用场景的详细说明: #### 🖼️ 1. OpenCV-Python 图像缩放 在 OpenCV 中,`resize()` 用于调整图像尺寸: ```python import cv2 # 读取图像 image = cv2.imread('input.jpg') # 方式1:直接指定目标尺寸 (宽,高) resized_direct = cv2.resize(image, (800, 600)) # 方式2:使用缩放因子 (fx: 宽度比例, fy: 高度比例) resized_scale = cv2.resize(image, None, fx=0.5, fy=0.5) # 缩小50% # 方式3:指定尺寸+插值算法 resized_highq = cv2.resize(image, (1200,900), interpolation=cv2.INTER_CUBIC) ``` **参数说明**: - `dsize`: 目标尺寸元组 `(width, height)` - `fx/fy`: 宽/高缩放比例(当 `dsize=None` 时生效) - `interpolation`: 插值算法(默认 `cv2.INTER_LINEAR`)[^1] #### 📦 2. C++ STL vector 容器调整 C++ 中 `std::vector` 的 `resize()` 用于改变元素数量: ```cpp #include <vector> using namespace std; int main() { vector<int> nums = {1, 2, 3}; // 扩容到5个元素,新增元素默认0 nums.resize(5); // 结果: {1,2,3,0,0} // 扩容到7个元素,新增元素初始化为10 nums.resize(7, 10); // 结果: {1,2,3,0,0,10,10} // 缩容到2个元素 nums.resize(2); // 结果: {1,2} return 0; } ``` **语法**: ```cpp void resize(size_t new_size); // 默认初始化新增元素 void resize(size_t new_size, T value); // 指定新增元素值[^2][^3] ``` #### 📊 3. MATLAB 图形调整 在 MATLAB 中,`resize()` 用于调整图形尺寸: ```matlab % 创建图形 fig = figure; plot(1:10, rand(1,10)); % 设置图形尺寸 (单位:像素) set(fig, 'Position', [100 100 800 600]); % 导出时指定尺寸 print('output.pdf', '-dpdf', '-r300', '-bestfit'); % 自动适应尺寸[^4] ``` ### ⚠️ 使用注意事项 1. **OpenCV 图像缩放**: - 缩放因子大于 1 时图像放大,小于 1 时缩小 - 高质量缩放推荐 `INTER_CUBIC` 插值,实时处理可用 `INTER_LINEAR` - 通道数不变(RGB 图像缩放后仍为 3 通道) 2. **C++ vector 调整**: - 扩容时:新增元素会调用默认构造函数 - 缩容时:多余元素会被销毁(触发析构函数) - 与 `reserve()` 区别:`reserve()` 只预分配内存不改变元素数量 3. **MATLAB 图形处理**: - 优先在图形界面手动调整 - 向量格式(PDF/EPS)缩放效果最佳 - 位图格式(JPEG/PNG)缩放可能导致锯齿 --- ### 📚 相关问题 1. OpenCV 中不同插值算法的性能差异如何? 2. C++ vector 的 `resize()` 和 `reserve()` 有何本质区别? 3. MATLAB 如何保持图形缩放后的清晰度? 4. 在 Python Pillow 库中如何实现图像缩放? [^1]: OpenCV 图像缩放语法 [^2]: C++ vector resize 基础用法 [^3]: STL resize 函数说明 [^4]: MATLAB 图形尺寸调整
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值