SLAM练习题(六)—— 相机成像模型

计算机视觉life从零开始一起学习SLAM 学习笔记

文章目录

  • 相机成像模型
  • 讨论

相机成像模型

以下题目来自计算机视觉life从零开始一起学习SLAM系列

题目: 相机视场角比较小(比如手机摄像头)时,一般可以近似为针孔相机成像,三维世界中的直线成像也是直线。但是很多时候需要用到广角甚至鱼眼相机,此时会产生畸变,三维世界中的直线在图像里会弯曲。因此,需要做去畸变。 本题给定一张广角畸变图像,以及相机的内参,请完成图像去畸变过程。
框架链接:https://pan.baidu.com/s/17KNXoprrYmY87s_xcDYK_g 密码:z2f0

参考答案:

#include 

using namespace std;
string image_file = "./test.png";   // 请确保路径正确

int main(int argc, char **argv) {
     
 
    double k1 = -0.28340811, k2 = 0.07395907;  // 畸变参数
    double fx = 458.654, fy = 457.296, cx = 367.215, cy = 248.375;

    cv::Mat image = cv::imread(image_file, CV_8UC1);   // 图像是灰度图
    int rows = image.rows, cols = image.cols;
    cv::Mat image_undistort = cv::Mat(rows, cols, CV_8UC1);   // 去畸变以后的图
    cv::imshow("image distorted", image);
    // 计算去畸变后图像的内容
    for (int v = 0; v < rows; v++)
        for (int u = 0; u < cols; u++) {
     

            double u_distorted = 0, v_distorted = 0;
            // 开始代码,注意(u,v)要先转化为归一化坐标
            
            double x1 = (u-cx)/fx;
            double y1 = (v-cy)/fy;
            double r = sqrt(x1*x1 + y1*y1);

            double x2 = x1*(1+k1*pow(r,2)+k2*pow(r,4));
            double y2 = y1*(1+k1*pow(r,2)+k2*pow(r,4));

            u_distorted = x2*fx + cx;
            v_distorted = y2*fy + cy;
            // 结束代码

            if (u_distorted >= 0 && v_distorted >= 0 && u_distorted < cols && v_distorted < rows) {
     
                image_undistort.at<uchar>(v, u) = image.at<uchar>((int) v_distorted, (int) u_distorted);
            } else {
     
                image_undistort.at<uchar>(v, u) = 0;
            }
        }

    cv::imshow("image undistorted", image_undistort);
    cv::waitKey();

    return 0;
}


CMakeLists.txt:

cmake_minimum_required( VERSION 2.8 )
project( undistort )

set( CMAKE_CXX_FLAGS "-std=c++11" )

find_package( OpenCV REQUIRED )

include_directories( ${
     OpenCV_INCLUDE_DIRS} )

add_executable( undistort_image undistort_image.cpp )

target_link_libraries( undistort_image ${
     OpenCV_LIBS} )

讨论

投影顺序:

世界坐标系中的3D点->相机坐标系中的3D点->归一化平面(X/Z,Y/Z,1)->乘以内参矩阵得到像素坐标(u,v)。

( u v 1 ) = 1 Z ( f x 0 c x 0 f y c y 0 0 1 ) [ R t 0 T 1 ] ( x w y w z w 1 ) = 1 Z K T ( x w y w z w 1 ) \left(\begin{array}{l} u \\ v \\ 1 \end{array}\right)=\frac{1}{Z}\left(\begin{array}{ccc} f_{x} & 0 & c_{x} \\ 0 & f_{y} & c_{y} \\ 0 & 0 & 1 \end{array}\right)\left[\begin{array}{cc} \boldsymbol{R} & \boldsymbol{t} \\ \boldsymbol{0}^{T} & 1 \end{array}\right]\left(\begin{array}{c} x_{w} \\ y_{w} \\ z_{w} \\ 1 \end{array}\right)=\frac{1}{Z} \boldsymbol{K} T\left(\begin{array}{c} x_{w} \\ y_{w} \\ z_{w} \\ 1 \end{array}\right) uv1=Z1fx000fy0cxcy1[R0Tt1]xwywzw1=Z1KTxwywzw1

畸变主要有径向畸变和切向畸变。

切向畸变切向畸变是由于透镜和CMOS或者CCD的安装位置误差导致。随着相机制造工艺的大大提升,这种情况很少出现了,我们一般也不考虑切向的畸变。

标定可以得到相机的所有畸变系数,用标定的畸变系数就能对畸变的图像进行去畸变。

去畸变公式:

x distorted  = x ( 1 + k 1 r 2 + k 2 r 4 + k 3 r 6 ) y distorted  = y ( 1 + k 1 r 2 + k 2 r 4 + k 3 r 6 ) r 2 = x 2 + y 2 \begin{array}{l} x_{\text {distorted }}=x\left(1+k_{1} r^{2}+k_{2} r^{4}+k_{3} r^{6}\right) \\ y_{\text {distorted }}=y\left(1+k_{1} r^{2}+k_{2} r^{4}+k_{3} r^{6}\right) \\ r^{2}=x^{2}+y^{2} \end{array} xdistorted =x(1+k1r2+k2r4+k3r6)ydistorted =y(1+k1r2+k2r4+k3r6)r2=x2+y2

课后题里面利用已有的去畸变图像,也就是假设已知x,y(不知道(x,y)处的像素值),然后带入右边式子,最后得到一个x_distorted, y_distorted的坐标,这个坐标对应的就是扭曲的图里的坐标,把这个坐标的像素值填入去畸变图像的(x,y)位置。

参考:
从零开始一起学习SLAM | 相机成像模型

你可能感兴趣的:(SLam,计算机视觉,opencv,slam,相机模型,cmake)