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

article/2025/7/15 12:04:16

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

常用算法及Python实现

1. 径向畸变校正

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

import numpy as np
import cv2
from matplotlib import pyplot as pltdef 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_cy_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_cy_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.hkcw.cn/article/iMZtjXGDYR.shtml

相关文章

技术创新如何赋能音视频直播行业?

在全球音视频直播行业的快速发展中,技术的持续创新始终是推动行业进步的核心动力。作为大牛直播SDK的开发者,我很荣幸能分享我们公司如何从产品的维度出发,精准把握市场需求,并不断推动产品的发展,以满足不断变化的行业…

我的世界服务端搭建

文章目录 我的世界服务端搭建使用forge搭建服务端确保服务器的 Java 环境安装1.20.1服务端配置文件修改启动游戏服务器 Minecraft server.properties 文件解析**基础设置****世界设置****网络与安全****性能优化****高级功能****配置文件示例****注意事项**Minecraft 白名单系统…

官宣正式分手 特朗普马斯克说了什么临别感言

官宣正式“分手” 特朗普马斯克都说了什么“临别感言”当地时间5月30日,美国总统特朗普和美国企业家、政府效率部负责人埃隆马斯克在白宫举行新闻发布会。特朗普称赞“政府效率部”成就在发布会上,特朗普对马斯克领导的“政府效率部”所达成的成就表示称赞,他称“政府效率部…

STM32通过rt_hw_hard_fault_exception中的LR寄存器追溯程序问题​

1. 问题现象 程序运行导致rt_hw_hard_fault_exception 如图 显示错误相关代码 struct exception_stack_frame {uint32_t r0;uint32_t r1;uint32_t r2;uint32_t r3;uint32_t r12; uint32_t lr; // 链接寄存器 (LR)uint32_t pc; // 程序计数器 (PC)uint32_t psr; // 程序状态…

AgenticSeek,开源本地通用AI Agent,自主执行任务

AgenticSeek是一款完全本地化的开源AI助手,作为Manus的开源替代品,专为保护用户隐私而设计。它能够在本地设备上执行多种任务,包括网页浏览、代码编写和复杂项目的规划,确保所有操作和数据均在用户的设备上完成。 AgenticSeek是什…

深入理解 Java 反射机制:动态编程的核心利器

一、反射机制的本质与核心价值 在 Java 的世界里,反射机制(Reflection)被视为连接静态编译与动态执行的桥梁。当程序运行时,反射允许我们在内存中动态获取类的完整结构信息,并对类的成员(字段、方法、构造…

群晖synology nas安装curl教程

在群晖nas系统上发现没有curl这个命令,想通过opkg进行安装,发现opkg这个套件也没有,本章教程介绍如何安装opkg,并通过opkg 安装上curl命令工具,nas的系统版本是:x86_64 GNU/Linux synology_apollolake_918+ 一、安装opkg wget -O - http://bin.entware.net/x64-k3.2/inst…

非接触式数据引擎:RFID重塑锂电注液工艺实时交互生态

非接触式数据引擎:RFID重塑锂电注液工艺实时交互生态 浙江某锂电行业注液机上存在问题: 1.在锂电池制造的核心环节中,注液工艺直接影响电芯的电化学性能与安全稳定性。随着行业对电池一致性、生产效率及追溯能力的需求升级。 2.按设定的抽…

Shell基础命令

一、设置修改主机名称 1.文件方式(重启生效) 2.命令方式(立即生效) hostnamectl set-hostname myname 二、网络管理nmcli (NetworkManager command-line interface) nmcli 1、查看网卡 2、设置网卡 dhcp网络工作模式 静态网…

【JVM】Java程序运行时数据区

运行时数据区 运行时数据区是Java程序执行过程中管理的内存区域 Java 运行时数据区组成(JVM 内存结构) Java 虚拟机(JVM)的运行时数据区由以下核心部分组成: 线程私有:程序计数器、Java虚拟机栈、本地方…

力扣面试150题--二叉树的层平均值

Day 54 题目描述 思路 初次做法(笨):使用两个队列,一个队列存放树的节点,一个队列存放对应节点的高度,使用x存放上一个节点,highb存放上一个节点的高度,sum存放当前层的节点值之和…

机器学习与深度学习01--线性回归

目录 1.什么是线性回归2.如何用数学方式描述简单线性回归模型3.什么是最小二乘法,他有什么作用 1.什么是线性回归 线性回归是⼀种⼴泛⽤于统计学和机器学习中的回归分析⽅法,⽤于建⽴⾃变量(特征)与因变量(⽬标&#…

004时装购物系统技术解析:构建智能时尚消费平台

时装购物系统技术解析:构建智能时尚消费平台 在电商行业蓬勃发展的当下,时装购物系统凭借其便捷性与多样性,成为消费者选购时尚单品的重要渠道。该系统通过商品信息、订单管理等核心模块,结合前台展示与后台录入功能,…

无线通信模块简介

QuecPython 是运行在无线通信模块上的开发框架。对于首次接触物联网开发的用户而言,无线通信模块可能是一个相对陌生的概念。本文主要针对无线通信和蜂窝网络本身,以及模块的概念、特性和开发方式进行简要的介绍。 无线通信和蜂窝网络 物联网对无线通信…

从认识AI开始-----解密门控循环单元(GRU):对LSTM的再优化

前言 在此之前,我已经详细介绍了RNN和LSTM,RNN虽然在处理序列数据中发挥了重要的作用,但它在实际使用中存在长期依赖问题,处理不了长序列,因为RNN对信息的保存只依赖一个隐藏状态,当序列过长,隐…

历年西北工业大学计算机保研上机真题

2025西北工业大学计算机保研上机真题 2024西北工业大学计算机保研上机真题 2023西北工业大学计算机保研上机真题 在线测评链接:https://pgcode.cn/school 计算整数乘积 题目描述 给定 n n n 组数,每组两个整数,输出这两个整数的乘积。 …

ansible-playbook 进阶 接上一章内容

1.异常中断 做法1:强制正常 编写 nginx 的 playbook 文件 01-zuofa .yml - hosts : web remote_user : root tasks : - name : create new user user : name nginx-test system yes uid 82 shell / sbin / nologin - name : test new user shell : gete…

基于cornerstone3D的dicom影像浏览器 第二十七章 设置vr相机,复位视图

文章目录 前言一、VR视图设置相机位置1. 相机位置参数2. 修改mprvr.js3. 调用流程1) 修改Toolbar3D.vue2) 修改View3d.vue3) 修改DisplayerArea3D.vue 二、所有视图复位1.复位流程说明2. 调用流程1) Toolbar3D中添加"复位"按钮,发送reset事件2) View3d.vu…

以色列防长:哈马斯要么接受美方提案 要么面临毁灭

当地时间5月30日,以色列国防部长卡茨通过其个人社交媒体账号发表声明称,在以军强大的军事压力之下,巴勒斯坦伊斯兰抵抗运动(哈马斯)将被迫接受选择:接受美方提出加沙停火提案,或者被以色列消灭。△以色列国防部长卡茨(资料图)卡茨在声明中表示,当前以军正全力在加沙地…

古巴外交部召见美国临时代办 抗议其无礼行为

△古巴哈瓦那(资料图)当时间5月30日,古巴外交部召见了美国驻古巴临时代办迈克哈默(Mike Hammer)并表示,迈克哈默自2024年11月抵达古巴以来,对古巴表现出的不友好行为,既不符合他外交官的身份,也表现了对古巴人民的不尊重。古巴外交部美国双边事务总司主任加西亚向迈克…