去除图像畸变及C++实现

本文详细介绍了图像畸变的两种类型——切向畸变(包括向外弯曲和向内弯曲)和径向畸变(桶形和枕形),并展示了如何使用OpenCV库在C++中通过相机标定参数对图像进行畸变校正的示例代码。

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

1.简介

图像畸变是指图像中出现的形变或失真,通常由于光学系统的非理想性(透镜和成像平面很难做到完全平行)或摄像机的透镜特性引起。图像畸变通常分为两种:径向畸变和切向畸变。

2.切向畸变

切向畸变(Tangential Distortion)通常是由于镜头与图像传感器之间的距离不正确造成的。这种畸变表现为图像边缘的直线向外延伸形成倾斜,使得物体的角部出现切割或拉伸的效果。

切向畸变有两种形式:

  • 第一类切向畸变:当透镜靠图像传感器太近时发生,导致图像边缘的直线向外弯曲。
  • 第二类切向畸变:当透镜离图像传感器太远时发生,导致图像边缘的直线向内弯曲。

好了,说人话。“切向畸变”就是矢量端点沿切线方向发生的变化,也就是角度的变化dt。还有一种解释是由于摄像机制造上的缺陷使得透镜本身与图像平面不平行而产生的。

注意,通常假设这些畸变呈多项式关系,以下是其数学模型:

x_{correct}=x+2p_1xy+p_2(r^2+2x^2)\\ y_{correct}=y+p_1(r^2+2y^2)+2p_2xy

其中,(x,y)是畸变点在图像上的原始坐标,(x_{correct},y_{correct})是校正后的新坐标,p_1p_2为切向畸变系数,r为极坐标系下畸变点到坐标原点的距离(即镜头中心到图像点的距离)。

3.径向畸变

径向畸变(Radial Distortion)主要是由于镜头内部的透镜元素对通过它们的光线施加了不均匀的放大率造成的。这种畸变通常在图像的边缘更为明显,因为边缘的光线通过镜头时光轴形成的角度较大。径向畸变通常有以下两种形式。

3.1桶形畸变

桶形畸变(Barrel Distortion)是当径向畸变导致图像中心的放大率高于边缘时发生的。结果是图像中心部分的直线向外弯曲,形成一种“桶”状的膨胀效果。桶形畸变常见于广角镜头。

3.2枕形畸变

枕形畸变(Pincushion Distortion)与桶形畸变相反,当边缘的放大率高于中心时,会发生枕形畸变。这种情况下,图像边缘的直线向内弯曲,好像被“挤压”进图像中心,形成枕形效果。枕形畸变常见于长焦镜头。

这是最经典的一张图,大家可以简单记作:桶形畸变(向外弯曲),枕形畸变(向内弯曲)。以下是其数学模型:

x_{correct}=x(1+k_1r^2+k_2r^4+k_3r^6)\\ y_{correct}=y(1+k_1r^2+k_2r^4+k_3r^6)

其中,(x,y)是畸变点在图像上的原始坐标,(x_{correct},y_{correct})是校正后的新坐标,k_1,k_2,k_3为径向向畸变系数,r为极坐标系下畸变点到坐标原点的距离(即镜头中心到图像点的距离)。

4.C++实现

以下代码均在ubuntu20.04上验证通过,使用的OpenCV C++版本为3.4.15。代码主要调用了OpenCV库中的undistort函数,并利用我的另一篇博客(相机标定及C++实现-优快云博客)得到的相机内参和畸变系数来对图像进行校正。

在运行代码前可以按照我的相机标定那篇博客创建build,images,src文件夹和CMakeLists.txt文件,以下是放在src文件夹下的源代码:

#include<iostream>
#include<opencv2/opencv.hpp>

using namespace std;

int main(int argc, char **argv)
{
    if(argc < 2)
    {
        cout<<"输入正确的图片路径"<<endl;
        return -1;
    }

    //读取图片
    cv::Mat image = cv::imread(argv[1],cv::IMREAD_COLOR);

    //图像是否读取成功
    if(image.empty())
    {
        cout<<"图片读取失败"<<endl;
        return -1;
    }

    //读取相机内参和畸变系数,这里的相机内参和畸变系数是相机标定的结果,需要提前标定
  
    cv::Mat cameraMatrix, distCoeffs;
    cameraMatrix = (cv::Mat_<double>(3,3)<<533.0082745226835, 0, 341.891649034585,
                    0, 533.0298665139785, 234.6399491136406,
                    0, 0, 1);
    distCoeffs = (cv::Mat_<double>(1,5)<<-0.2797096204667459, 0.02806520133705146, 0.001221734842500993, 3.843081231723055e-05, 0.128566132396488);
    
    //去除畸变
    cv::Mat undistortedImage;
    //使用相机内参和畸变系数进行去畸变
    cv::undistort(image,undistortedImage,cameraMatrix,distCoeffs,cv::Mat());


    //显示原图和去畸变后的图片
    cv::imshow("originalImage",image);
    cv::imshow("undistortedImage",undistortedImage);
    cv::waitKey(0);

    return 0;
}

以下是CMakeLists.txt中的代码,注意按照你的源代码文件名修改倒数第二行src/undistort.cpp这句代码。

#设置当前cmake运行的最低版本
cmake_minimum_required(VERSION 3.2)

# 设置项目名称
project(undistort)

# 设置C++标准为11
set(CMAKE_CXX_STANDARD 11)

# 查找OpenCV库
find_package(OpenCV REQUIRED)

#包含OpenCV的头文件
include_directories(${OpenCV_INCLUDE_DIRS})

# 添加可执行文件
add_executable(undistort src/undistort.cpp)

# 链接OpenCV库

target_link_libraries(undistort ${OpenCV_LIBS})

进入到build文件夹下,打开终端,输入以下命令:

cmake ..
make

具体运行结果如下:

上面ls命令下绿色的undistort就是我们的可执行文件,这个可执行文件名和我们CMakeLists.txt文件中最后两行是相对应的。接着在build文件夹下执行我们的可执行文件(undistort)

./undistort ./../images/left01.jpg

运行结果如下,看着有点效果。

【资源说明】 基于C++图像视觉实现的坐姿检测矫正提醒系统源码(openpose算法+演示视频+论文).tar基于C++图像视觉实现的坐姿检测矫正提醒系统源码(openpose算法+演示视频+论文).tar基于C++图像视觉实现的坐姿检测矫正提醒系统源码(openpose算法+演示视频+论文).tar基于C++图像视觉实现的坐姿检测矫正提醒系统源码(openpose算法+演示视频+论文).tar基于C++图像视觉实现的坐姿检测矫正提醒系统源码(openpose算法+演示视频+论文).tar基于C++图像视觉实现的坐姿检测矫正提醒系统源码(openpose算法+演示视频+论文).tar基于C++图像视觉实现的坐姿检测矫正提醒系统源码(openpose算法+演示视频+论文).tar 基于C++图像视觉实现的坐姿检测矫正提醒系统源码(openpose算法+演示视频+论文).tar 基于C++图像视觉实现的坐姿检测矫正提醒系统源码(openpose算法+演示视频+论文).tar基于C++图像视觉实现的坐姿检测矫正提醒系统源码(openpose算法+演示视频+论文).tar 基于C++图像视觉实现的坐姿检测矫正提醒系统源码(openpose算法+演示视频+论文).tar 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,也适用于小白学习入门进阶。当然也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或者热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载,沟通交流,互相学习,共同进步!
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值