【图像处理基石】如何进行图像畸变校正?

news2025/6/4 21:05:44

在这里插入图片描述
图像畸变校正常用于计算机视觉、摄影测量学和机器人导航等领域,能够修正因镜头光学特性或传感器排列问题导致的图像失真。下面我将介绍几种常用的图像畸变校正算法,并提供Python实现和测试用例。

常用算法及Python实现

1. 径向畸变校正

径向畸变是最常见的畸变类型,表现为图像中心区域正常,边缘区域出现拉伸或压缩。校正公式如下:

import numpy as np
import cv2
from matplotlib import pyplot as plt

def correct_radial_distortion(image, k1, k2, k3=0):
    """
    校正图像的径向畸变
    
    参数:
    image: 输入的畸变图像
    k1, k2, k3: 径向畸变系数
    
    返回:
    corrected_image: 校正后的图像
    """
    h, w = image.shape[:2]
    # 创建网格坐标
    x, y = np.meshgrid(np.arange(w), np.arange(h))
    x_c, y_c = w / 2, h / 2  # 图像中心
    
    # 计算离中心的距离
    r = np.sqrt((x - x_c)**2 + (y - y_c)**2)
    
    # 径向畸变校正公式
    x_distorted = (x - x_c) * (1 + k1 * r**2 + k2 * r**4 + k3 * r**6) + x_c
    y_distorted = (y - y_c) * (1 + k1 * r**2 + k2 * r**4 + k3 * r**6) + y_c
    
    # 使用双线性插值进行重采样
    corrected_image = np.zeros_like(image)
    
    # 处理整数坐标
    x_distorted_int = np.clip(x_distorted.astype(int), 0, w - 1)
    y_distorted_int = np.clip(y_distorted.astype(int), 0, h - 1)
    
    # 应用校正
    if len(image.shape) == 3:  # 彩色图像
        corrected_image[y, x] = image[y_distorted_int, x_distorted_int]
    else:  # 灰度图像
        corrected_image[y, x] = image[y_distorted_int, x_distorted_int]
    
    return corrected_image

# 测试用例
def test_radial_distortion():
    # 创建测试图像(棋盘格)
    test_image = np.zeros((400, 400), dtype=np.uint8)
    for i in range(8):
        for j in range(8):
            if (i + j) % 2 == 0:
                test_image[i*50:(i+1)*50, j*50:(j+1)*50] = 255
    
    # 引入径向畸变(k1=0.00005, k2=0.0000002)
    distorted_image = correct_radial_distortion(test_image, 0.00005, 0.0000002)
    
    # 校正径向畸变
    corrected_image = correct_radial_distortion(distorted_image, -0.00005, -0.0000002)
    
    # 显示结果
    plt.figure(figsize=(15, 5))
    plt.subplot(131), plt.imshow(test_image, cmap='gray')
    plt.title('原始图像'), plt.axis('off')
    plt.subplot(132), plt.imshow(distorted_image, cmap='gray')
    plt.title('畸变图像'), plt.axis('off')
    plt.subplot(133), plt.imshow(corrected_image, cmap='gray')
    plt.title('校正图像'), plt.axis('off')
    plt.show()

# 运行测试
test_radial_distortion()
2. 切向畸变校正

切向畸变是由于镜头与图像传感器不平行引起的,表现为图像局部区域的倾斜。校正公式如下:

def correct_tangential_distortion(image, p1, p2):
    """
    校正图像的切向畸变
    
    参数:
    image: 输入的畸变图像
    p1, p2: 切向畸变系数
    
    返回:
    corrected_image: 校正后的图像
    """
    h, w = image.shape[:2]
    # 创建网格坐标
    x, y = np.meshgrid(np.arange(w), np.arange(h))
    x_c, y_c = w / 2, h / 2  # 图像中心
    
    # 计算离中心的距离
    r = np.sqrt((x - x_c)**2 + (y - y_c)**2)
    
    # 切向畸变校正公式
    x_distorted = (x - x_c) + (2 * p1 * (x - x_c) * (y - y_c) + p2 * (r**2 + 2 * (x - x_c)**2)) + x_c
    y_distorted = (y - y_c) + (p1 * (r**2 + 2 * (y - y_c)**2) + 2 * p2 * (x - x_c) * (y - y_c)) + y_c
    
    # 使用双线性插值进行重采样
    corrected_image = np.zeros_like(image)
    
    # 处理整数坐标
    x_distorted_int = np.clip(x_distorted.astype(int), 0, w - 1)
    y_distorted_int = np.clip(y_distorted.astype(int), 0, h - 1)
    
    # 应用校正
    if len(image.shape) == 3:  # 彩色图像
        corrected_image[y, x] = image[y_distorted_int, x_distorted_int]
    else:  # 灰度图像
        corrected_image[y, x] = image[y_distorted_int, x_distorted_int]
    
    return corrected_image

# 测试用例
def test_tangential_distortion():
    # 创建测试图像(棋盘格)
    test_image = np.zeros((400, 400), dtype=np.uint8)
    for i in range(8):
        for j in range(8):
            if (i + j) % 2 == 0:
                test_image[i*50:(i+1)*50, j*50:(j+1)*50] = 255
    
    # 引入切向畸变(p1=0.001, p2=0.0008)
    distorted_image = correct_tangential_distortion(test_image, 0.001, 0.0008)
    
    # 校正切向畸变
    corrected_image = correct_tangential_distortion(distorted_image, -0.001, -0.0008)
    
    # 显示结果
    plt.figure(figsize=(15, 5))
    plt.subplot(131), plt.imshow(test_image, cmap='gray')
    plt.title('原始图像'), plt.axis('off')
    plt.subplot(132), plt.imshow(distorted_image, cmap='gray')
    plt.title('畸变图像'), plt.axis('off')
    plt.subplot(133), plt.imshow(corrected_image, cmap='gray')
    plt.title('校正图像'), plt.axis('off')
    plt.show()

# 运行测试
test_tangential_distortion()
3. 使用OpenCV进行相机标定与畸变校正

实际应用中,通常使用OpenCV提供的相机标定功能来自动计算畸变系数:

def camera_calibration_and_undistortion():
    """
    使用OpenCV进行相机标定和图像畸变校正
    """
    # 准备对象点,如 (0,0,0), (1,0,0), (2,0,0) ..., (7,5,0)
    objp = np.zeros((6*8, 3), np.float32)
    objp[:, :2] = np.mgrid[0:8, 0:6].T.reshape(-1, 2)
    
    # 存储对象点和图像点的数组
    objpoints = []  # 3D点在现实世界中的坐标
    imgpoints = []  # 2D点在图像平面中的坐标
    
    # 生成模拟标定图像(通常需要使用多幅图像)
    images = []
    for i in range(5):
        img = np.zeros((480, 640), dtype=np.uint8)
        # 生成模拟的棋盘格角点
        corners = np.zeros((48, 2), dtype=np.float32)
        for j in range(48):
            x = 50 + (j % 8) * 60 + np.random.randint(-5, 6)  # 添加随机畸变
            y = 50 + (j // 8) * 60 + np.random.randint(-5, 6)
            corners[j] = [x, y]
        imgpoints.append(corners)
        objpoints.append(objp)
        # 在图像上绘制角点
        for corner in corners:
            cv2.circle(img, (int(corner[0]), int(corner[1])), 5, 255, -1)
        images.append(img)
    
    # 相机标定
    ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, images[0].shape[::-1], None, None)
    
    # 生成测试图像
    test_img = np.zeros((480, 640), dtype=np.uint8)
    for i in range(8):
        for j in range(6):
            cv2.circle(test_img, (100 + i * 60, 100 + j * 60), 10, 255, -1)
    
    # 畸变校正
    h, w = test_img.shape[:2]
    newcameramtx, roi = cv2.getOptimalNewCameraMatrix(mtx, dist, (w, h), 1, (w, h))
    undistorted_img = cv2.undistort(test_img, mtx, dist, None, newcameramtx)
    
    # 显示结果
    plt.figure(figsize=(10, 5))
    plt.subplot(121), plt.imshow(test_img, cmap='gray')
    plt.title('畸变图像'), plt.axis('off')
    plt.subplot(122), plt.imshow(undistorted_img, cmap='gray')
    plt.title('校正图像'), plt.axis('off')
    plt.show()
    
    # 返回标定结果
    return mtx, dist

# 运行相机标定和畸变校正
camera_matrix, distortion_coeffs = camera_calibration_and_undistortion()
print("相机内参矩阵:\n", camera_matrix)
print("畸变系数:\n", distortion_coeffs)

算法解释

  1. 径向畸变校正

    • 径向畸变是最常见的畸变类型,表现为图像中心区域正常,边缘区域出现拉伸或压缩。
    • 校正公式基于多项式模型,通过径向畸变系数(k1, k2, k3)来调整像素位置。
  2. 切向畸变校正

    • 切向畸变是由于镜头与图像传感器不平行引起的,表现为图像局部区域的倾斜。
    • 校正公式使用切向畸变系数(p1, p2)来调整像素位置。
  3. 相机标定与OpenCV实现

    • 实际应用中,通常使用已知的标定板(如棋盘格)来计算相机的内参矩阵和畸变系数。
    • OpenCV提供了完整的相机标定和畸变校正功能,能够自动计算所有参数并进行图像校正。

以上代码实现了常见的图像畸变校正算法,并提供了测试用例来验证算法的有效性。在实际应用中,你可能需要根据具体的相机型号和场景来调整参数。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2396882.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

电力系统时间同步系统

电力系统中,电压、电流、功率变化等特征量测量都是时间相关函数[1],统一精准的时间源对于电网安全稳定运行至关重要,因此,电力系统运行规程[2]中明确要求继电保护装置、自动化装置、安全稳定控制系统、能量管理系统和生产信息管理…

Vue使用toFixed保留两位小数的三种写法

第一种:直接写在js里面,这是最简单的 val.toFixed(2)第二种:在ElementUi表格中使用 第三种:在取值符号中使用 {{}} 定义一个方法 towNumber(val) { return val.toFixed(2) } 使用 {{ towNumber(row.equiV…

Arch安装botw-save-state

devkitPro https://blog.csdn.net/qq_39942341/article/details/148387077?spm1001.2014.3001.5501 cargo https://blog.csdn.net/qq_39942341/article/details/148387783?spm1001.2014.3001.5501 megaton https://blog.csdn.net/qq_39942341/article/details/148388164?spm…

电脑为什么换个ip就上不了网了

在日常使用电脑上网时,很多人可能遇到过这样的问题:当IP地址发生变化后,突然就无法连接网络了。当电脑更换IP地址后无法上网,这一现象可能由多种因素导致,涉及网络配置、硬件限制或运营商策略等层面。以下是系统性分析…

github 2FA双重认证丢失解决

文章目录 前言一. 凭借ssh 解锁步骤1.1 要求输入设备码1.2.进入二重验证界面1.3.开始2FA恢复1.4.选择使用ssh验证 二.预防措施2.1 云盘上传git_recover_codes.txt2.2 开启多源FA认证2.2.1 大陆无法使用手机验证码 三.参考资料 前言 场景:没有意识到github recovery …

linux驱动 - 5: simple usb device驱动

参考第2节, 准备好编译环境并实现hello.ko: linux驱动 - 2: helloworld.ko_linux 驱动开发 hello world ko-CSDN博客 下面在hello模块的基础上, 添加代码, 实现一个usb设备驱动的最小骨架. #include <linux/init.h> #include <linux/module.h> #include <lin…

ETL脚本节点使用的方式

随着大数据时代的到来&#xff0c;企业对数据处理的需求日益增长&#xff0c;ETL 作为数据整合的关键技术&#xff0c;逐渐走进我们的视野。本文将为您揭秘 ETL 脚本节点的使用方式&#xff0c;助您轻松驾驭数据处理新境界。 一、ETL脚本的优势 1.提高效率&#xff1a;ETL 脚…

PH热榜 | 2025-06-02

1. Circuit Tracer 标语&#xff1a;Anthropic的开放工具&#xff1a;让我们了解AI是如何思考的 介绍&#xff1a;Anthropic的开源工具Circuit Tracer可以帮助研究人员理解大型语言模型&#xff08;LLMs&#xff09;&#xff0c;它通过将内部计算可视化为归因图的方式展现相关…

: influxdb + grafana+JMeter

influxdb和Grafana 不安装在被测机器上&#xff0c;可以统一放到一台机器上面 1、influxdb&#xff1a;一种时序数据库&#xff0c; 可以永久性保存数据【除非手动清除和数据库坏了】 2、Grafana&#xff1a;grafana是一款用go编写的开源应用&#xff0c;用于大规模指标数据的可…

TDengine 基于 TDgpt 的 AI 应用实战

基于 TDgpt 时序数据智能体的风力发电预测 作者&#xff1a; derekchen Demo 数据集准备 我们使用公开的UTSD数据集里面的某风场发电数据&#xff0c;作为预测算法的数据来源&#xff0c;基于历史数据预测未来一天内的每15分钟的发电量。原始数据集的采集频次为4秒&#xff…

RocketMQ 消息发送核心源码解析:DefaultMQProducerImpl.send () 方法深度剖析

引言 在分布式系统中&#xff0c;消息队列是实现异步通信、服务解耦和流量削峰的关键组件。Apache RocketMQ 作为一款高性能、高可靠的消息中间件&#xff0c;被广泛应用于各类互联网场景。其中&#xff0c;消息发送是最基础也是最重要的功能之一。本文将深入剖析 RocketMQ 中…

BiliNote部署实践

​ 开源地址&#xff1a; https://github.com/JefferyHcool/BiliNote &#x1f680; 快速开始 1. 克隆仓库 git clone https://github.com/JefferyHcool/BiliNote.git cd BiliNote mv .env.example .env2. 启动后端&#xff08;FastAPI&#xff09; cd backend pip insta…

bismark OT CTOT OB CTOB 以及mapping后的bam文件中的XG,XR列的含义

首先&#xff0c;OT&#xff0c;OB&#xff0c;CTOT&#xff0c;CTOB都是描述测序reads的&#xff0c;而不是描述参考基因组的。 bisul-fate建库会将DNA双链文库中非甲基化的C转化成U。转化结束后&#xff0c;被转化的U和互补链的G并不配对。此时正链&#xff08;&#xff0c;…

Android Native 之 adbd进程分析

目录 1、adbd守护进程 2、adbd权限降级 3、adbd命令解析 1&#xff09;adb shell 2&#xff09;adb root 3&#xff09;adb reboot 4、案例 1&#xff09;案例之实现不需要执行adb root命令自动具有root权限 2&#xff09;案例之实现不需要RSA认证直接能够使用adb she…

CAN通讯协议中各种参数解析

1.各种参数缩写 2.多帧传输时间参数解析 - Sender&#xff08;左侧&#xff09; 指的是 多帧数据的发送者&#xff0c;也就是&#xff1a; ECU&#xff08;被测系统 / 响应方&#xff09; - Receiver&#xff08;右侧&#xff09; 指的是 多帧数据的接收者&#xff0c;也就是…

网络攻防技术三:网络脆弱性分析

文章目录 一、影响安全的因素二、计算机网络三、网络体系结构脆弱性1、因特网容易被攻击的特性 四、典型网络协议安全性分析&#xff08;重要&#xff09;1、IPv42、RIP&#xff08;UDP)3、ICMP(UDP)4、ARP5、OSPF(IP数据报&#xff09;6、BGP(TCP)7、UDP8、TCP9、DNS(UDP)10、…

(八)登录认证与学生写作画像

本次将赵昱琨同学之前完成的学生写作画像与智能学习路径规划的后端与目前已有的后端框架进行整合。同时为了实现学生写作画像与智能学习路径规划&#xff0c;需要在之前简易的登录系统上进行重构&#xff0c;所以本次大规模重写了登录模块&#xff0c;同时发现很多过去冗余的代…

Netty学习example示例

文章目录 simpleServer端NettyServerNettyServerHandler Client端NettyClientNettyClientHandler tcp&#xff08;粘包和拆包&#xff09;Server端NettyTcpServerNettyTcpServerHandler Client端NettyTcpClientNettyTcpClientHandler protocolcodecCustomMessageDecoderCustomM…

[RoarCTF 2019]Easy Calc

查看源代码 <!--Ive set up WAF to ensure security.--> <script>$(#calc).submit(function(){$.ajax({url:"calc.php?num"encodeURIComponent($("#content").val()),type:GET,success:function(data){$("#result").html(<div …

[Windows]在Win上安装bash和zsh - 一个脚本搞定

目录 前言安装步骤配置要求下载安装脚本启动程序 前言 Windows是一个很流行的系统, 但是在Windows上安装bash和zsh一直是一个让人头疼的问题. 本蛙特意打包了一个程序, 用于一站式解决这一类的问题. 安装步骤 配置要求 系统: Windows软件: Powershell 5.1或以上 下载安装…