使用OpenGL实现OpenCV鱼眼相机模型对图像去畸变时遇到的问题

我在尝试使用OpenGL着色器来实现鱼眼相机去畸变和透视转换,但在去畸变这里遇到了问题。
下面是我分别得到的去畸变图和投影图,可以看出去畸变图中仍然存在部分畸变,在投影变换后畸变会更加明显。

img


img

下面是我片段着色器的代码:

#version 330 core

in vec2 textureCoords;

uniform sampler2D inputTexture;
uniform float windowWidth;
uniform float windowHeight;
uniform float textureWidth;
uniform float textureHeight;
uniform float scaleTest;

mat3 inverseMatrix = mat3(
    4.2612641166,    13.003206285,    -2228.5388394338,
    0.0517394913,    10.0787253178,    -262.8409400879,
    -0.0010467339,    0.0241003739,    1.0
);

mat3 cameraMatrix = mat3(
    302.4530598322,    0.0,            496.64001463163,
    0.0,            320.7461859439,    331.19980984361,
    0.0,            0.0,            1.0
);

mat3 inverseCamMat = mat3(
    0.00330629817,    0.0,            -1.6420399744,
    0.0,            0.003117729980,    -1.0325915766,
    0.0,            0.0,            1.0
);

vec4 distortVector = vec4(-4.3735601598704078e-02, 2.1692522970939803e-02, -2.6388839028513571e-02, 8.4123126605702321e-03);

void main() {
    //投影图坐标到去畸变图坐标
    vec3 frameCoords = vec3(textureCoords.x * windowWidth, textureCoords.y * windowHeight, 1.0);
    vec3 m = inverseMatrix[2] * frameCoords;
    float zed = 1.0 / (m.x + m.y + m.z);
    frameCoords = frameCoords * zed;
    float xTrans = inverseMatrix[0][0]*frameCoords.x + inverseMatrix[0][1]*frameCoords.y + inverseMatrix[0][2]*frameCoords.z;
    float yTrans = inverseMatrix[1][0]*frameCoords.x + inverseMatrix[1][1]*frameCoords.y + inverseMatrix[1][2]*frameCoords.z;
    vec2 coords = vec2(xTrans/windowWidth, yTrans/windowHeight);
    //gl_FragColor = texture(inputTexture, coords);

    //去畸变图坐标到畸变原图坐标
    float i = coords.x * windowWidth * 1.5 - 300;
    float j = coords.y * windowHeight * 1.5 - 250;
    float xc = inverseCamMat[0][0]*i + inverseCamMat[0][2];
    float yc = inverseCamMat[1][1]*j + inverseCamMat[1][2];
    float r = sqrt(xc*xc + yc*yc);
    float degree = atan(r);
    float rd = degree + distortVector[0]*pow(degree,3) + distortVector[1]*pow(degree,5) + distortVector[2]*pow(degree,7) + distortVector[3]*pow(degree,9);
    rd *= scaleTest;
    float scale = rd / r;
    float x = xc * scale;
    float y = yc * scale;
    float u = cameraMatrix[0][0]*x + cameraMatrix[0][2];
    float v = cameraMatrix[1][1]*y + cameraMatrix[1][2];
    vec2 finalCoords = vec2(u/textureWidth, v/textureHeight);

    if (finalCoords.x>=0.0 && finalCoords.x<=1.0 && finalCoords.y>=0.0 && finalCoords.y<=1.0) {
        gl_FragColor = texture(inputTexture, finalCoords);
    } else {
        gl_FragColor = vec4(0.0,0.0,0.0,0.0);
    }
}

其中投影转换部分我参考了这里
去畸变部分我参考了这里
另外scaleTest是我引入的一个出射角因子,上面的结果图是在该因子等于1.02左右时得到的,如果等于1的话畸变会更加明显。
我使用OpenCV得到的去畸变图测试了着色器中投影转换部分的代码,可以得出正常的结果,所以猜测问题应该出在畸变模型部分,请问有什么建议吗?非常感谢

不知道你这个问题是否已经解决, 如果还没有解决的话:
  • 帮你找了个相似的问题, 你可以看下: https://ask.csdn.net/questions/1056424
  • 这篇博客也不错, 你可以看下【我的OpenGL学习进阶之旅】关于OpenGL ES 绘制纹理,因为加载纹理坐标设置错误,导致纹理无法渲染的问题
  • 除此之外, 这篇博客: OpenGL文字写入中的 实现起来比想象中简单,大致的过程就是找操作系统要指定字体指定大小和颜色的文字图片,然后拷贝绘制出来即可。代码如下: 部分也许能够解决你的问题, 你可以仔细阅读以下内容或者直接跳转源博客中阅读:
    #include <windows.h>
    #include <GL/gl.h>
    #include <GL/glu.h>
    #include <GL/freeglut.h>
    
    void selectFont(int size, int charset, const char* face)//选择字体对象(包括格式)
    {
    	HFONT hFont = CreateFontA(size, 0, 0, 0, FW_MEDIUM, 0, 0, 0,
    		charset, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
    		DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS, face);
    	HFONT hOldFont = (HFONT)SelectObject(wglGetCurrentDC(), hFont);//选择字体对象,返回旧的对象
    	DeleteObject(hOldFont);//删除旧的对象
    }
    
    void drawCNString(const char* str)
    {
    	int len, i;
    	wchar_t* wstring;
    	HDC hDC = wglGetCurrentDC();
    	GLuint list = glGenLists(1);
    	// 计算字符的个数
    	// 如果是双字节字符的(比如中文字符),两个字节才算一个字符
    	// 否则一个字节算一个字符
    	len = 0;
    	for (i = 0; str[i] != '\0'; ++i)
    	{
    		if (IsDBCSLeadByte(str[i]))
    			++i;
    		++len;
    	}
    	// 将混合字符转化为宽字符
    	wstring = (wchar_t*)malloc((len + 1) * sizeof(wchar_t));
    	MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, str, -1, wstring, len);
    	wstring[len] = L'\0';
    	// 逐个输出字符
    	for (i = 0; i<len; ++i)
    	{
    		wglUseFontBitmapsW(hDC, wstring[i], 1, list);
    		glCallList(list);
    	}
    	// 回收所有临时资源
    	free(wstring);
    	glDeleteLists(list, 1);
    }
    
    void display(void) {
    	glClear(GL_COLOR_BUFFER_BIT);
    
    	selectFont(48, GB2312_CHARSET, "微软雅黑");
    	glColor3f(1.0f, 1.0f, 0.0f);//设置字体颜色
    	glRasterPos2f(-0.7f, -0.1f);
    	drawCNString("像天使依赖着翅膀");
    
    	selectFont(48, DEFAULT_CHARSET, "楷体");
    	glColor3f(0.0f, 1.0f, 0.0f);
    	glRasterPos2f(-0.7f, -0.6f);
    	drawCNString("像海豚依赖海洋");
    
    	glutSwapBuffers();
    }
    
    int main(int argc, char ** argv)
    {
    	glutInit(&argc, argv);
    	glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
    	glutInitWindowSize(640, 480);
    	glutInitWindowPosition(100, 100);
    	glutCreateWindow("Hello ");
    	
    	display();
    	glutMainLoop();
    	return 0;
    }
    

如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^

你好,请问问题解决了吗