棋盘畸变矫正

一般棋盘的矫正是针对边缘地区的,不适用于鱼眼矫正,鱼眼中间部分完全很大,使用棋盘矫正来矫正鱼眼(半球),可能只矫正了边缘,中间的部分还是原样

#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);

 }

看着边缘齐整很多,但是内部处理的还是不太好

 

posted on 2025-05-14 16:58  邗影  阅读(15)  评论(0)    收藏  举报

导航