棋盘畸变矫正
一般棋盘的矫正是针对边缘地区的,不适用于鱼眼矫正,鱼眼中间部分完全很大,使用棋盘矫正来矫正鱼眼(半球),可能只矫正了边缘,中间的部分还是原样
#include<string> #include<fstream> #include<sstream> #include<iostream> #include<stdio.h> #include <glad/glad.h> #include <GLFW/glfw3.h> #include<Windows.h> const unsigned int SCR_WIDTH = 600; const unsigned int SCR_HEIGHT = 600; const int len = 364*366* 3 / 2; BYTE YUVdata[len]; unsigned int VBO = 0; unsigned int VAO = 0; unsigned int EBO = 0; unsigned int texturePIC = 0; int shaderProgram = 0; GLuint texIndexarray[3]; GLuint texUniformY = 99; GLuint texUniformU = 99; GLuint texUniformV = 99; void LoadPicture() { glGenTextures(3, texIndexarray);//生成三个纹理索引 glBindTexture(GL_TEXTURE_2D, texIndexarray[0]); //为bind的纹理设置环绕,过滤方式 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glBindTexture(GL_TEXTURE_2D, texIndexarray[1]); //为bind的纹理设置环绕,过滤方式 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glBindTexture(GL_TEXTURE_2D, texIndexarray[2]); //为bind的纹理设置环绕,过滤方式 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); //使用着色器程序,返回采样器的序号 glUseProgram(shaderProgram);//该语句必须要有;安装 指定着色器程序 texUniformY = glGetUniformLocation(shaderProgram, "ImgTex"); texUniformU = glGetUniformLocation(shaderProgram, "dataU"); texUniformV = glGetUniformLocation(shaderProgram, "dataV"); ////----------加载数据-------------------------------------------------------- FILE* fp = fopen("./wg1.yuv", "rb+");//I420 int returns = fread(YUVdata, 1, len, fp); int w = 364; int h = 366; int ysize = w*h; int uvsize = w * h / 4; void* uptr = &YUVdata[ysize]; void* vptr = &YUVdata[ysize * 5 / 4]; //--------------------------------------------------------------------------- glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, texIndexarray[0]);// texindexarray[0] =1 //使用GL_red表示单通道,glfw3里边没有YUV那个GL属性; glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, w, h, 0, GL_RED, GL_UNSIGNED_BYTE, YUVdata); glUniform1i(texUniformY, 0); //通过 glUniform1i 的设置,保证每个 uniform 采样器对应着正确的纹理单元;注意这里不能用tesindexarray[0]; glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, texIndexarray[1]); glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, w / 2, h / 2, 0, GL_RED, GL_UNSIGNED_BYTE, uptr); glUniform1i(texUniformU, 1); glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, texIndexarray[2]); glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, w / 2, h / 2, 0, GL_RED, GL_UNSIGNED_BYTE, vptr); glUniform1i(texUniformV, 2); glUseProgram(0); } void render() { glBindVertexArray(VAO); glUseProgram(shaderProgram); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); //glDrawArrays(GL_TRIANGLE_FAN,0,4);也可 glUseProgram(0); glBindVertexArray(0); } void initmodule() { //做个一模型;正方形;映射了顶点坐标和纹理坐标的对应关系 float vertexs[] = { //顶点坐标-------纹理坐标(屏幕坐标翻转) 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, -1.0f, 0.0f, 1.0f, 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f }; //一个正方形是由两个三角形得来的;记录顶点的索引顺序 unsigned int indexs[] = { 0,1,3, 1,2,3, }; //做VAO glGenVertexArrays(1, &VAO); glBindVertexArray(VAO); //做VBO glGenBuffers(1, &VBO); glBindBuffer(GL_ARRAY_BUFFER, VBO); //创建显存空间 glBufferData(GL_ARRAY_BUFFER, sizeof(vertexs), vertexs, GL_STATIC_DRAW); //设置索引缓冲 glGenBuffers(1, &EBO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indexs), indexs, GL_STATIC_DRAW); //加载纹理图片,生成纹理 LoadPicture(); //设置第0个锚点,3个点,不需要归一化,跨度5个float可以读下一个点 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0); //打开顶点 glEnableVertexAttribArray(0); //纹理属性设置,纹理在第一个锚点上(指定顶点数据) glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float))); //打开纹理 glEnableVertexAttribArray(1); //解除绑定VBO glBindBuffer(GL_ARRAY_BUFFER, 0); //解绑VAO glBindVertexArray(0); } void initshader(const char* verpath, const char* fragpath) { //编译shader,并记录shaderID std::string VerCode(""); std::string fregCode(""); //读文件 std::ifstream vShaderFile; std::ifstream fShaderFile; vShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit); fShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit); try { vShaderFile.open(verpath); fShaderFile.open(fragpath); std::stringstream vsstream, fsstream; vsstream << vShaderFile.rdbuf(); fsstream << fShaderFile.rdbuf(); VerCode = vsstream.str(); fregCode = fsstream.str(); } catch (const std::exception&) { std::cout << "read file error" << std::endl; } const char* vshader = VerCode.c_str(); const char* fshader = fregCode.c_str(); //shader 编译连接 unsigned int vertexID = 0, fragID = 0; char infoLog[512];//存储错误信息 int successflag = 0; vertexID = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vertexID, 1, &vshader, NULL); glCompileShader(vertexID); //获取编译是否成功 glGetShaderiv(vertexID, GL_COMPILE_STATUS, &successflag); if (!successflag) { glGetShaderInfoLog(vertexID, 512, NULL, infoLog); std::string errstr(infoLog); std::cout << "v shader err" << infoLog; } //frag fragID = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fragID, 1, &fshader, NULL); glCompileShader(fragID); //获取编译是否成功 glGetShaderiv(fragID, GL_COMPILE_STATUS, &successflag); if (!successflag) { glGetShaderInfoLog(fragID, 512, NULL, infoLog); std::string errstr(infoLog); std::cout << "f shader err" << infoLog; } //链接 shaderProgram = glCreateProgram(); glAttachShader(shaderProgram, vertexID); glAttachShader(shaderProgram, fragID); glBindAttribLocation(shaderProgram, 0, "position"); glBindAttribLocation(shaderProgram, 1, "inputTextureCoordinate"); glLinkProgram(shaderProgram); glGetProgramiv(shaderProgram, GL_LINK_STATUS, &successflag); if (!successflag) { glGetShaderInfoLog(shaderProgram, 512, NULL, infoLog); std::string errstr(infoLog); std::cout << "link error"; } //编译完成后,可以把中间的步骤程序删除 glDeleteShader(vertexID); glDeleteShader(fragID); } void processInput(GLFWwindow *window) { if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) { //将窗口设置为关闭,跳出循环 glfwSetWindowShouldClose(window, true); } } void framebuffer_size_callback(GLFWwindow* window, int width, int height) { glViewport(0, 0, width, height); } int main() { //glfw初始化 glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); //glfw创建窗口 GLFWwindow* window = glfwCreateWindow(500, 600, "LearnOpenGL", NULL, NULL); if (window == NULL) { printf("创建窗口失败"); //终止 glfwTerminate(); return -1; } //显示窗口 glfwMakeContextCurrent(window); //设置回调,当窗口大小调整后将调用该回调函数 glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); // glad初始化 if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) { printf("加载失败"); return -1; } initshader("vertexShader.glsl", "fragmentShader.glsl");//先编译着色器 initmodule(); // 使用循环达到循环渲染效果 while (!glfwWindowShouldClose(window)) { //自定义输入事件 processInput(window); glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); render(); //交互缓冲区,否则显示空白 glfwSwapBuffers(window); //输入输出事件,否则无法对窗口进行交互 glfwPollEvents(); } //终止渲染 关闭并清理glfw本地资源 glfwTerminate(); return 0; }
测试1:
原图:图一

原图图二:

使用的时候用ffmpeg 转成YUV420即可(大小可以自己截取)
片元着色器1:
#version 330 core precision mediump float; //纹理坐标 uniform float fx = -0.1;//控制 X 方向的畸变强度(横向拉伸补偿) uniform float fy = -0.1;//控制 y方向的畸变强度(横向拉伸补偿) varying vec4 vPosition; uniform sampler2D dataY; uniform sampler2D dataU; uniform sampler2D dataV; vec3 yuv; vec3 rgb; void main() { vec4 vPos = vPosition; vec2 vMapping = vPos.xy; vMapping.x += ((pow(vPos.y, 2.0)+pow(vPos.x, 2.0))*vPos.x)*-fx; vMapping.y += ((pow(vPos.y, 2.0)+pow(vPos.x, 2.0))*vPos.y)*-fy; vMapping = vMapping * vec2(1.0, -1.0)/ 2.0 + vec2(0.5, 0.5); yuv.x = texture2D(dataY, vMapping).r-0.065; yuv.y = texture2D(dataU, vMapping).r-0.5; yuv.z = texture2D(dataV, vMapping).r-0.5; rgb = mat3(1, 1, 1, 0, -0.18732, 1.8556, 1.57481, -0.46813, 0) * yuv; gl_FragColor = vec4(rgb.x, rgb.y,rgb.z,1); }
结果:图1运行后:

片元着色2 ,矫正图片二(突出的正方形):
#version 330 core precision mediump float; //纹理坐标 uniform float fx = 0.1;//控制 X 方向的畸变强度(横向拉伸补偿) uniform float fy =0.1;//控制 y方向的畸变强度(横向拉伸补偿) varying vec4 vPosition; uniform sampler2D dataY; uniform sampler2D dataU; uniform sampler2D dataV; vec3 yuv; vec3 rgb; void main() { vec4 vPos = vPosition; vec2 vMapping = vPos.xy; vMapping.x += (pow(vPos.y, 2.0)*vPos.x)*-fx; vMapping.y += (pow(vPos.x, 2.0)*vPos.y)*-fy; vMapping = vMapping * vec2(1.0, -1.0)/ 2.0 + vec2(0.5, 0.5); yuv.x = texture2D(dataY, vMapping).r-0.065; yuv.y = texture2D(dataU, vMapping).r-0.5; yuv.z = texture2D(dataV, vMapping).r-0.5; rgb = mat3(1, 1, 1, 0, -0.18732, 1.8556, 1.57481, -0.46813, 0) * yuv; gl_FragColor = vec4(rgb.x, rgb.y,rgb.z,1); }
看着边缘齐整很多,但是内部处理的还是不太好

浙公网安备 33010602011771号