赞
踩
昨天讨论了关于摄像头校准方面的问题,其实刚开始时工作的时候在相机、摄像机方面从事一段时间的开发,大体上还是应用类的研发工作。
当时是基于SDK方案,在其基础上做一些参数调整,但是总的逻辑大致是一致的。现在技术发展已经远超当年,尤其有强大的后端数据处理时,要处理这个校准问题的手段就更加多了。
回忆总结下,关于摄像头校准方面的一些校准内容,如果还有其他没有提及的,请各位路过的兄弟们指点下,我后续补充:
摄像头畸变校准是指校正镜头引起的图像畸变,使图像中的直线和比例恢复正常。常见的畸变包括径向畸变和切向畸变。以下是摄像头畸变校准的详细步骤,包括畸变模型、参数计算和图像校正。
径向畸变(Radial Distortion):
切向畸变(Tangential Distortion):
畸变模型的数学表示如下:
x
distorted
=
x
(
1
+
k
1
r
2
+
k
2
r
4
+
k
3
r
6
)
+
2
p
1
x
y
+
p
2
(
r
2
+
2
x
2
)
]
x_{\text{distorted}} = x(1 + k_1 r^2 + k_2 r^4 + k_3 r^6) + 2p_1 xy + p_2 (r^2 + 2x^2)]
xdistorted=x(1+k1r2+k2r4+k3r6)+2p1xy+p2(r2+2x2)]
y
distorted
=
y
(
1
+
k
1
r
2
+
k
2
r
4
+
k
3
r
6
)
+
p
1
(
r
2
+
2
y
2
)
+
2
p
2
x
y
y_{\text{distorted}} = y(1 + k_1 r^2 + k_2 r^4 + k_3 r^6) + p_1 (r^2 + 2y^2) + 2p_2 xy
ydistorted=y(1+k1r2+k2r4+k3r6)+p1(r2+2y2)+2p2xy
其中, r 2 = x 2 + y 2 r^2 = x^2 + y^2 r2=x2+y2。
棋盘格图案:
拍摄校准图像:
使用OpenCV库检测棋盘格的角点。
import cv2 import numpy as np import glob # 设置棋盘格的尺寸 chessboard_size = (9, 6) square_size = 1.0 # 设置棋盘格每个方块的实际尺寸 # 准备棋盘格的世界坐标系点(3D点) objp = np.zeros((chessboard_size[0]*chessboard_size[1], 3), np.float32) objp[:, :2] = np.mgrid[0:chessboard_size[0], 0:chessboard_size[1]].T.reshape(-1, 2) objp *= square_size # 用于存储所有图像的对象点和图像点 objpoints = [] # 3d point in real world space imgpoints = [] # 2d points in image plane. # 读取所有校准图像 images = glob.glob('calibration_images/*.jpg') for fname in images: img = cv2.imread(fname) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 检测棋盘格角点 ret, corners = cv2.findChessboardCorners(gray, chessboard_size, None) if ret: objpoints.append(objp) corners2 = cv2.cornerSubPix(gray, corners, (11, 11), (-1, -1), (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)) imgpoints.append(corners2) # 绘制并显示角点 cv2.drawChessboardCorners(img, chessboard_size, corners2, ret) cv2.imshow('Chessboard corners', img) cv2.waitKey(500) cv2.destroyAllWindows()
使用calibrateCamera
函数计算摄像头的内参数矩阵和畸变系数。
# 进行摄像头校准
ret, camera_matrix, dist_coeffs, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1], None, None)
print("Camera matrix:")
print(camera_matrix)
print("\nDistortion coefficients:")
print(dist_coeffs)
使用计算得到的参数进行图像畸变校正。
# 示例:矫正一张图像 img = cv2.imread('calibration_images/example.jpg') h, w = img.shape[:2] # 获取新的相机矩阵 new_camera_matrix, roi = cv2.getOptimalNewCameraMatrix(camera_matrix, dist_coeffs, (w, h), 1, (w, h)) # 矫正图像 dst = cv2.undistort(img, camera_matrix, dist_coeffs, None, new_camera_matrix) # 裁剪图像 x, y, w, h = roi dst = dst[y:y+h, x:x+w] cv2.imshow('Undistorted Image', dst) cv2.waitKey(0) cv2.destroyAllWindows()
观察校正后的图像,确保直线恢复正常,图像畸变得到有效校正。
计算重投影误差,评估校准的精度。
mean_error = 0
for i in range(len(objpoints)):
imgpoints2, _ = cv2.projectPoints(objpoints[i], rvecs[i], tvecs[i], camera_matrix, dist_coeffs)
error = cv2.norm(imgpoints[i], imgpoints2, cv2.NORM_L2) / len(imgpoints2)
mean_error += error
print("Total error: ", mean_error / len(objpoints))
根据误差评估结果,调整拍摄方式或增加校准图像数量,优化校准参数。
摄像头的白平衡校准是为了确保在不同的光照条件下,摄像头拍摄的图像中的白色看起来是白色,从而使图像的颜色还原更准确。这对于计算机视觉应用和图像处理非常重要。下面是详细的白平衡校准步骤,包括自动白平衡和手动白平衡的方法。
白平衡校准的目标是调整图像的色温,使得图像中中性的灰色或白色区域在不同光照条件下依然保持中性,即没有颜色偏差。
灰世界假设法:
import cv2 import numpy as np def gray_world_awb(img): b, g, r = cv2.split(img) avg_b = np.mean(b) avg_g = np.mean(g) avg_r = np.mean(r) avg_gray = (avg_b + avg_g + avg_r) / 3 b = cv2.addWeighted(b, avg_gray / avg_b, 0, 0, 0) g = cv2.addWeighted(g, avg_gray / avg_g, 0, 0, 0) r = cv2.addWeighted(r, avg_gray / avg_r, 0, 0, 0) return cv2.merge([b, g, r]) img = cv2.imread('test_image.jpg') awb_img = gray_world_awb(img) cv2.imshow('AWB Image', awb_img) cv2.waitKey(0) cv2.destroyAllWindows()
图像统计法:
def simple_color_balance(img, percent): half_percent = percent / 200.0 channels = cv2.split(img) out_channels = [] for channel in channels: assert len(channel.shape) == 2 flat = channel.flatten() flat = np.sort(flat) n_cols = flat.shape[0] low_val = flat[int(n_cols * half_percent)] high_val = flat[int(n_cols * (1.0 - half_percent))] thresholded = np.clip(channel, low_val, high_val) thresholded = ((thresholded - low_val) / (high_val - low_val) * 255.0).astype(np.uint8) out_channels.append(thresholded) return cv2.merge(out_channels) img = cv2.imread('test_image.jpg') balanced_img = simple_color_balance(img, 1) cv2.imshow('Balanced Image', balanced_img) cv2.waitKey(0) cv2.destroyAllWindows()
使用标准灰卡:
计算校正系数:
def manual_white_balance(img, gray_card_region): x, y, w, h = gray_card_region gray_card = img[y:y+h, x:x+w] avg_b = np.mean(gray_card[:, :, 0]) avg_g = np.mean(gray_card[:, :, 1]) avg_r = np.mean(gray_card[:, :, 2]) avg_gray = (avg_b + avg_g + avg_r) / 3 b, g, r = cv2.split(img) b = cv2.addWeighted(b, avg_gray / avg_b, 0, 0, 0) g = cv2.addWeighted(g, avg_gray / avg_g, 0, 0, 0) r = cv2.addWeighted(r, avg_gray / avg_r, 0, 0, 0) return cv2.merge([b, g, r]) img = cv2.imread('test_image.jpg') gray_card_region = (50, 50, 100, 100) # 假设灰卡位于这个区域 wb_img = manual_white_balance(img, gray_card_region) cv2.imshow('Manual WB Image', wb_img) cv2.waitKey(0) cv2.destroyAllWindows()
视觉验证:
误差评估:
重复调整:
CMOS传感器的坏点(dead pixels)校准是指检测和校正图像传感器上失效的像素,以提高图像质量。坏点通常表现为图像上的黑点、白点或固定的彩色点。坏点校准的目的是通过替换坏点的像素值,使图像看起来更自然。以下是详细的CMOS坏点校准步骤:
坏点通常分为三类:
将摄像头盖住或在完全黑暗的环境中拍摄多张图像,坏点在这些图像中通常表现得很明显。
使用阈值法检测坏点。阈值可以基于像素值的统计特性来设置。
import cv2
import numpy as np
# 读取一张黑暗场图像
dark_frame = cv2.imread('dark_frame.jpg', cv2.IMREAD_GRAYSCALE)
# 设定阈值,假设超过200的像素为坏点
threshold = 200
_, bad_pixel_map = cv2.threshold(dark_frame, threshold, 255, cv2.THRESH_BINARY)
cv2.imshow('Bad Pixel Map', bad_pixel_map)
cv2.waitKey(0)
cv2.destroyAllWindows()
用坏点周围的有效像素的平均值替换坏点值。
def correct_bad_pixels(image, bad_pixel_map): corrected_image = image.copy() bad_pixels = np.argwhere(bad_pixel_map == 255) for y, x in bad_pixels: neighbors = [] for dy in [-1, 0, 1]: for dx in [-1, 0, 1]: ny, nx = y + dy, x + dx if 0 <= ny < image.shape[0] and 0 <= nx < image.shape[1] and not (dy == 0 and dx == 0): neighbors.append(image[ny, nx]) corrected_image[y, x] = np.mean(neighbors) return corrected_image # 读取一张包含坏点的图像 image_with_bad_pixels = cv2.imread('image_with_bad_pixels.jpg', cv2.IMREAD_GRAYSCALE) corrected_image = correct_bad_pixels(image_with_bad_pixels, bad_pixel_map) cv2.imshow('Corrected Image', corrected_image) cv2.waitKey(0) cv2.destroyAllWindows()
使用双边滤波保留图像边缘的同时平滑坏点。
corrected_image = cv2.bilateralFilter(image_with_bad_pixels, d=9, sigmaColor=75, sigmaSpace=75)
cv2.imshow('Corrected Image with Bilateral Filter', corrected_image)
cv2.waitKey(0)
cv2.destroyAllWindows()
检查校正后的图像,确保坏点被有效校正,图像质量明显提升。
将坏点检测和校正步骤集成到图像处理管道中,实现自动化处理。
定期拍摄黑暗场图像,更新坏点地图,并进行校正,确保图像质量稳定。
必须从校准的原理、方法的角度彻底的了解来龙去脉,才能在实际应用中更好的达成应用目的。
摄像头畸变校准通过检测特征点、计算内参数和畸变系数,以及进行图像校正,能够有效地减少图像中的畸变,提高图像的精度和质量。通过定期校准和优化,可以确保摄像头在各种应用场景中的性能稳定。
通过自动白平衡和手动白平衡的方法,可以有效地对摄像头进行白平衡校准,从而保证在不同光照条件下,摄像头拍摄的图像颜色准确性。根据具体应用场景和需求,可以选择适合的方法进行白平衡校准。
CMOS坏点校准是通过检测坏点并用邻域平均或双边滤波等方法进行校正,以提高图像质量的过程。通过自动化的检测和校正,可以有效地减少图像中的坏点影响,提升整体图像效果。根据应用需求和实际情况,选择合适的坏点校正方法,确保摄像头的性能和图像质量达到最佳。
摄像头校准的主要目的是确定摄像头的内参数和外参数。这些参数在计算机视觉和图像处理任务用于将现实世界中的三维坐标映射到二维图像平面上。
通过校准,可以精确地得到摄像头的内参数和外参数,从而能够进行图像校正、3D重建、姿态估计等计算机视觉任务。这些参数的准确性对于很多应用场景来说至关重要,比如机器人导航、增强现实、测量和监控等。
具体来说,摄像头校准需要确定以下参数:
焦距(Focal Length, f x , f y f_x, f_y fx,fy):
光学中心(Principal Point, c x , c y c_x, c_y cx,cy):
畸变系数(Distortion Coefficients):
内参数矩阵(Intrinsic Matrix, K K K):
K
=
[
f
x
0
c
x
0
f
y
c
y
0
0
1
]
K =
旋转矩阵(Rotation Matrix, R R R):
平移向量(Translation Vector, t t t):
K
=
[
f
x
0
c
x
0
f
y
c
y
0
0
1
]
K =
外参数矩阵由旋转矩阵和平移向量组成:
[
R
∣
t
]
=
[
r
11
r
12
r
13
t
x
r
21
r
22
r
23
t
y
r
31
r
32
r
33
t
z
]
[R|t] =
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。