【图像处理基石】如何入门图像校正?
图像校正入门的核心是理解“校正的目标”——通过算法或工具修正图像中因拍摄条件(如角度、光线、设备)导致的偏差(如几何变形、色彩失衡、镜头畸变等)。入门可从几何校正(最直观)、色彩校正(最常用)和畸变校正(设备相关)三个方向切入,结合工具(如OpenCV)实践更易掌握。
一、工具准备
入门推荐用Python+OpenCV(开源、功能全),安装命令:
pip install opencv-python numpy # numpy用于数值计算
二、实例1:几何校正(透视变换)
场景:拍摄文档、白板时,因角度倾斜导致图像呈梯形/不规则四边形,需校正为正矩形(如扫描效果)。
原理:
通过“透视变换”将不规则四边形映射为矩形,核心是确定原始图像的4个顶点和目标矩形的4个顶点,计算变换矩阵并应用。
步骤与代码:
- 读取图像,手动标记文档的4个顶点(顺时针:左上→右上→右下→左下);
- 定义目标矩形的4个顶点(如宽500、高700,符合A4纸比例);
- 计算透视变换矩阵,并应用变换得到校正结果。
import cv2
import numpy as np# 1. 读取图像(替换为自己的图像路径)
img = cv2.imread("doc.jpg") # 假设图像是倾斜的文档
h, w = img.shape[:2] # 获取图像高、宽# 2. 手动标记原始图像中文档的4个顶点(需根据实际图像调整坐标)
# 格式:[左上, 右上, 右下, 左下],单位:像素
src_points = np.float32([[120, 80], # 左上[580, 100], # 右上[550, 450], # 右下[90, 430] # 左下
])# 3. 定义目标矩形的4个顶点(宽500,高700,可根据需求调整)
dst_points = np.float32([[0, 0], # 左上[500, 0], # 右上[500, 700], # 右下[0, 700] # 左下
])# 4. 计算透视变换矩阵M
M = cv2.getPerspectiveTransform(src_points, dst_points)# 5. 应用变换,得到校正图像
corrected_img = cv2.warpPerspective(img, M, (500, 700) # 目标图像尺寸:宽500,高700
)# 6. 显示结果
cv2.imshow("原始图像", img)
cv2.imshow("校正后图像", corrected_img)
cv2.waitKey(0) # 按任意键关闭窗口
cv2.destroyAllWindows()
效果对比:
左图为倾斜的原始文档(梯形),右图为校正后的矩形文档(可直接用于打印/存档)。
三、实例2:色彩校正(白平衡修复)
场景:拍摄时因光线(如暖光、背光)导致图像偏色(如整体偏黄/偏蓝),需修复为自然色彩。
原理:
基于“灰度世界假设”——自然场景中所有像素的RGB平均值趋近于灰色(R≈G≈B),通过调整三通道的增益使均值相等。
步骤与代码:
- 分离图像的RGB三通道;
- 计算各通道的平均值,通过增益调整使三通道均值相等;
- 合并通道得到校正结果。
import cv2
import numpy as np# 1. 读取偏色图像(替换为自己的图像路径)
img = cv2.imread("yellowish.jpg") # 假设图像偏黄(R、G通道过强)# 2. 分离B、G、R通道(OpenCV默认通道顺序为BGR)
b, g, r = cv2.split(img) # b:蓝色通道,g:绿色通道,r:红色通道# 3. 计算各通道的平均值
b_mean = np.mean(b) # 蓝色通道均值
g_mean = np.mean(g) # 绿色通道均值
r_mean = np.mean(r) # 红色通道均值# 4. 计算目标均值(三通道均值的平均)
target_mean = (b_mean + g_mean + r_mean) / 3# 5. 计算各通道的增益(使通道均值=目标均值)
b_gain = target_mean / b_mean # 蓝色通道增益(偏黄图像中b_mean通常较低,增益>1)
g_gain = target_mean / g_mean
r_gain = target_mean / r_mean# 6. 应用增益(截断到0-255,避免像素值溢出)
b_corrected = np.clip(b * b_gain, 0, 255).astype(np.uint8) # uint8是图像像素的标准类型
g_corrected = np.clip(g * g_gain, 0, 255).astype(np.uint8)
r_corrected = np.clip(r * r_gain, 0, 255).astype(np.uint8)# 7. 合并通道,得到校正图像
corrected_img = cv2.merge([b_corrected, g_corrected, r_corrected])# 8. 显示结果
cv2.imshow("偏色原始图", img)
cv2.imshow("色彩校正后", corrected_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
效果对比:
左图偏黄(暖光拍摄),右图通过增强蓝色通道、减弱红/绿色通道,色彩更自然。
四、实例3:镜头畸变校正
场景:鱼眼镜头、广角镜头拍摄的图像边缘会扭曲(如桶形畸变、枕形畸变),需修正为正常透视。
原理:
镜头畸变由设备光学特性导致,需先通过“相机标定”获取镜头的畸变系数,再用系数反向修正。
步骤与代码:
- 相机标定(提前操作):拍摄多张棋盘格图像,用OpenCV计算镜头内参(焦距、光心)和畸变系数;
- 用畸变系数对图像进行校正。
import cv2
import numpy as np# 1. 读取畸变图像(替换为自己的图像路径)
img = cv2.imread("fisheye.jpg") # 假设为鱼眼镜头拍摄的桶形畸变图像
h, w = img.shape[:2]# 2. 输入相机标定得到的参数(示例值,实际需自己标定)
# 内参矩阵K:[fx, 0, cx; 0, fy, cy; 0, 0, 1](fx/fy:焦距,cx/cy:光心)
K = np.array([[500, 0, 320], [0, 500, 240], [0, 0, 1]])
# 畸变系数:[k1, k2, p1, p2, k3](k为径向畸变,p为切向畸变)
dist_coeffs = np.array([[-0.3, 0.1, 0, 0, -0.05]]) # 3. 优化内参矩阵(避免校正后图像黑边过多)
new_K, roi = cv2.getOptimalNewCameraMatrix(K, dist_coeffs, (w, h), 1, (w, h) # 1:保留所有像素,(w,h):目标尺寸
)# 4. 应用畸变校正
corrected_img = cv2.undistort(img, K, dist_coeffs, None, new_K # 用新内参矩阵修正
)# 5. 裁剪黑边(根据roi:x,y为起点,w,h为宽高)
x, y, roi_w, roi_h = roi
corrected_img = corrected_img[y:y+roi_h, x:x+roi_w]# 6. 显示结果
cv2.imshow("畸变原始图", img)
cv2.imshow("校正后图像", corrected_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
说明:
相机标定需用cv2.findChessboardCorners
和cv2.calibrateCamera
函数,具体可参考OpenCV官方棋盘格标定教程,这里简化为示例参数。
三、入门总结
- 先明确校正目标:是几何变形、色彩问题还是镜头畸变?
- 从工具实践入手:用OpenCV跑通上述实例,观察参数变化对结果的影响;
- 理解基础原理:如透视变换的矩阵映射、灰度世界假设的适用场景;
- 进阶方向:自动检测校正点(如用边缘检测替代手动标记)、复杂场景的色彩校正(如白平衡算法优化)。
通过这三个实例,可快速掌握图像校正的核心逻辑,后续再结合具体场景深化细节即可。