【图像处理基石】如何入门图像校正?

图像校正入门的核心是理解"校正的目标"------通过算法或工具修正图像中因拍摄条件(如角度、光线、设备)导致的偏差(如几何变形、色彩失衡、镜头畸变等)。入门可从几何校正 (最直观)、色彩校正 (最常用)和畸变校正(设备相关)三个方向切入,结合工具(如OpenCV)实践更易掌握。

一、工具准备

入门推荐用Python+OpenCV(开源、功能全),安装命令:

bash 复制代码
pip install opencv-python numpy  # numpy用于数值计算

二、实例1:几何校正(透视变换)

场景:拍摄文档、白板时,因角度倾斜导致图像呈梯形/不规则四边形,需校正为正矩形(如扫描效果)。

原理:

通过"透视变换"将不规则四边形映射为矩形,核心是确定原始图像的4个顶点和目标矩形的4个顶点,计算变换矩阵并应用。

步骤与代码:
  1. 读取图像,手动标记文档的4个顶点(顺时针:左上→右上→右下→左下);
  2. 定义目标矩形的4个顶点(如宽500、高700,符合A4纸比例);
  3. 计算透视变换矩阵,并应用变换得到校正结果。
python 复制代码
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),通过调整三通道的增益使均值相等。

步骤与代码:
  1. 分离图像的RGB三通道
  2. 计算各通道的平均值,通过增益调整使三通道均值相等;
  3. 合并通道得到校正结果。
python 复制代码
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:镜头畸变校正

场景:鱼眼镜头、广角镜头拍摄的图像边缘会扭曲(如桶形畸变、枕形畸变),需修正为正常透视。

原理:

镜头畸变由设备光学特性导致,需先通过"相机标定"获取镜头的畸变系数,再用系数反向修正。

步骤与代码:
  1. 相机标定(提前操作):拍摄多张棋盘格图像,用OpenCV计算镜头内参(焦距、光心)和畸变系数;
  2. 用畸变系数对图像进行校正。
python 复制代码
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.findChessboardCornerscv2.calibrateCamera函数,具体可参考OpenCV官方棋盘格标定教程,这里简化为示例参数。

三、入门总结

  1. 先明确校正目标:是几何变形、色彩问题还是镜头畸变?
  2. 从工具实践入手:用OpenCV跑通上述实例,观察参数变化对结果的影响;
  3. 理解基础原理:如透视变换的矩阵映射、灰度世界假设的适用场景;
  4. 进阶方向:自动检测校正点(如用边缘检测替代手动标记)、复杂场景的色彩校正(如白平衡算法优化)。

通过这三个实例,可快速掌握图像校正的核心逻辑,后续再结合具体场景深化细节即可。