You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

201 lines
6.5 KiB

import cv2
import numpy as np
import glob
from scipy.optimize import minimize
import model
import math
import calc_way
def needs_correction(dist_coeffs, error_threshold=0.5):
k1, k2, p1, p2, k3 = dist_coeffs.ravel()
if (abs(k1) > 0.1 or abs(k2) > 0.01 or abs(p1) > 0.005 or
abs(p2) > 0.005 or abs(k3) > 0.01):
return True
return False
def calibrate(image_fold, columns, rows, size):
# 设置棋盘格参数
chessboard_size = (columns, rows) # 内部角点数量 (columns, rows)
square_size = size # 棋盘格方块实际大小(单位:毫米/厘米/英寸等)
# 准备对象点 (0,0,0), (1,0,0), (2,0,0) ..., (8,5,0)
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) * square_size
# 存储对象点和图像点的数组
objpoints = [] # 3D点真实世界坐标
imgpoints = [] # 2D点图像坐标
# 获取标定图像
images = glob.glob(image_fold)
# print("找到的图像文件:", images)
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)
# 亚像素级精确化
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)
corners2 = cv2.cornerSubPix(gray, corners, (11, 11), (-1, -1), criteria)
imgpoints.append(corners2)
# 绘制并显示角点
cv2.drawChessboardCorners(img, chessboard_size, corners2, ret)
cv2.imshow('Corners', img)
cv2.waitKey(500)
cv2.destroyAllWindows()
# 相机标定
ret, camera_matrix, dist_coeffs, rvecs, tvecs = cv2.calibrateCamera(
objpoints, imgpoints, gray.shape[::-1], None, None)
# 输出标定结果
print("相机内参矩阵K矩阵:\n", camera_matrix)
print("\n畸变系数k1, k2, p1, p2, k3:\n", dist_coeffs)
print("\n重投影误差:", ret)
if needs_correction(dist_coeffs):
print("需要矫正:畸变系数过大")
else:
print("无需矫正:畸变可忽略")
return camera_matrix, dist_coeffs, rvecs, tvecs
def find_corners(image_path, columns, rows):
# 读取图像
image = cv2.imread(image_path)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 定义棋盘格尺寸 (内角点数量,非方格数)
pattern_size = (columns, rows) # 例如8x8的棋盘有7x7内角点
# 查找棋盘格角点
ret, corners = cv2.findChessboardCorners(gray, pattern_size, None)
if ret:
# 提高角点检测精度
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)
corners = cv2.cornerSubPix(gray, corners, (11, 11), (-1, -1), criteria)
# 绘制检测结果
cv2.drawChessboardCorners(image, pattern_size, corners, ret)
cv2.imshow('Chessboard Corners', image)
cv2.waitKey(0)
cv2.destroyAllWindows()
else:
print("未检测到棋盘格")
print(corners)
# 将形状从 (N,1,2) 转换为 (N,2)
corners_reshaped = corners.reshape(-1, 2)
# print("所有角点坐标:\n", corners_reshaped)
fixed_value = 960 # 固定值
column_index = 1 # 操作第2列索引从0开始
# 方法:固定值 - 列值
corners_reshaped[:, column_index] = fixed_value - corners_reshaped[:, column_index]
3 months ago
print(corners_reshaped)
return corners_reshaped
def fun_test(x,cls,corners):
print("标定开始")
# print(corners)
error = 0
3 months ago
error_y = 0
model = cls()
f = model.f
H = model.H - 9
gamma = math.atan(1 / (math.tan(x[0]) * math.tan(x[1])))
seta = math.atan(1 / math.sqrt(pow(math.tan(x[1]), 2) + 1 / pow(math.tan(x[0]), 2)))
column = 0
3 months ago
k = 0
for index, value in enumerate(corners):
if index % 11 == 10:
column += 1
index += 1
3 months ago
k += 1
continue
Xw, Yw = calc_way.calc_distance(value[0], value[1], x[0], x[1])
Xw1, Yw1 = calc_way.calc_distance(corners[index+1][0], corners[index+1][1], x[0], x[1])
3 months ago
print(f"{index}个点")
print(f"Xw: {Xw}, Yw: {Yw}")
print(f"Xw1: {Xw1}, Yw1: {Yw1}")
d2 = math.sqrt((Xw1 - Xw) ** 2 + (Yw1 - Yw) ** 2)
3 months ago
print(f"两点距离为:{d2:.2f}")
error = error + abs(d2 - 60)
3 months ago
d_y = abs(570-60*k-50+Yw)
error_y = error_y + d_y
print(f"平均误差为:{error/80:.2f}")
print(f"errpr_y:{error/80:.2f}")
return error/80 + error_y/80
def get_result_test(cls,corners):
params = cls,corners
bounds = [(0.1, 1.7), (0.1, 1.7)]
result = minimize(
fun_test,
x0=[0.7, 0.9],
args=params,
# method='Nelder-Mead', # 或 'trust-constr'
method='L-BFGS-B', bounds=bounds,
3 months ago
tol=1e-6, # 高精度容差
options={'gtol': 1e-6, 'maxiter': 1000}
)
return result
3 months ago
def undistort_image(image_path, camera_matrix, dist_coeffs):
# 读取图像
img = cv2.imread(image_path)
# 获取图像尺寸
h, w = img.shape[:2]
# 优化相机矩阵
new_camera_matrix, roi = cv2.getOptimalNewCameraMatrix(
camera_matrix, dist_coeffs, (w, h), 1, (w, h))
# 使用undistort
dst = cv2.undistort(img, camera_matrix, dist_coeffs, None, new_camera_matrix)
# 裁剪图像(使用roi)
x, y, w, h = roi
dst = dst[y:y + h, x:x + w]
return dst
# 示例使用
# 假设你已经通过相机标定获得了相机矩阵和畸变系数
# result = calibrate(r"C:\Users\Administrator\Desktop\BYD\20250711\*.jpg",11,8,60)
# camera_matrix = result[0]
# dist_coeffs = result[1]
# corrected_img = undistort_image(r"C:\Users\Administrator\Desktop\BYD\20250711\frame_2100_3.jpg", camera_matrix, dist_coeffs)
# cv2.imwrite("corrected.jpg", corrected_img)
# result = get_result_test(model.Model,find_corners("corrected.jpg",11,8))
# print(result)
# find_corners("corrected.jpg",11,8)
# x_zeros,y_zeros = calc_way.calc_zeros_yto0(-200)
# print(x_zeros,y_zeros)
# # 读取图像
# img = cv2.imread("corrected.jpg")
#
# # 定义两点坐标
# pt1 = (int(x_zeros[0]), int(960-y_zeros[0]))
# pt2 = (int(x_zeros[-1]), int(960-y_zeros[-1]))
#
# # 画红色线条粗细为3
# cv2.line(img, pt1, pt2, (0, 0, 255), 3)
#
# # 保存结果
# cv2.imwrite("output.jpg", img)