当前位置:网站首页>Opencv camera calibration (1): internal and external parameters, distortion coefficient calibration and 3D point to 2D image projection
Opencv camera calibration (1): internal and external parameters, distortion coefficient calibration and 3D point to 2D image projection
2022-06-13 01:46:00 【No change of name】
0. Content
It can be used for camera calibration picture filtering
Camera calibration
3-D point re projection will affect 2-D image
draw Z Plane and connecting line
Be careful : This calibration method is suitable for ordinary cameras with small distortion , The calibration of the fish eye camera is as follows :Opencv Camera calibration (2): Fish eye camera calibration _m0_58772523 The blog of -CSDN Blog ...
1. Picture screening
utilize opencv in findChessboardCorners Determine whether the corresponding corner can be detected in the picture , If a corner is detected ret The value is True, Delete the corresponding picture when no corner is detected .
import os
import cv2
import glob
def delete_pic(inter_corner_shape, img_dir, img_type):
images = glob.glob(img_dir + os.sep + '**.' + img_type)
for fname in images:
img = cv2.imread(fname)
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, cp_img = cv2.findChessboardCorners(gray_img,
(inter_corner_shape[0], inter_corner_shape[1]), None)
if not ret:
os.remove(fname)
if __name__ == '__main__':
inter_corner_shape = (9, 6)
img_dir = "./data"
img_type = "jpg"
delete_pic(inter_corner_shape, img_dir, img_type)
2. Line and plane drawing auxiliary functions ( With detailed notes )
# Two dimensional pictures , Picture corner coordinates , The coordinates of the projection points of the 3D points to be projected in the image
def draw(img, corners, imgpts):
# Get the first image corner information
corner = tuple(corners[0].ravel().astype(np.int64))
# Use the coordinates of the first image corner and projection point to draw the desired line and plane
# np.ravel() The function reduces the dimension of a multidimensional array to one dimension
# The new version of the opencv When drawing lines and planes, it is necessary to manually convert the coordinate information to integer , In the old version, you don't need to ( The test found )
img = cv2.drawContours(img, [np.array([list(corners[0].ravel()), list(imgpts[1].ravel()),
list(imgpts[2].ravel()), list(imgpts[3].ravel())]).astype(np.int64)], -1,
(175, 0, 175), -3)
img = cv2.line(img, corner, tuple(imgpts[0].ravel().astype(np.int64)), (255, 0, 0), 5)
img = cv2.line(img, corner, tuple(imgpts[1].ravel().astype(np.int64)), (0, 255, 0), 5)
# img = cv2.line(img, corner, tuple(imgpts[2].ravel().astype(np.int64)), (0, 0, 255), 5)
img = cv2.line(img, corner, tuple(imgpts[3].ravel().astype(np.int64)), (0, 0, 255), 5)
return img3. The main function ( Camera calibration : Get internal parameters 、 Distortion coefficient , External reference < The calibration phase is not very useful >)
# Define number of corners , Chessboard size ( It should be possible to write at will , It does not affect the parameter calibration ), Image path , Image type
def calib(inter_corner_shape, size_per_grid, img_dir, img_type):
# Generate the world coordinate system coordinates of the corner
# np.mgrid() Return to multidimensional structure , It is recommended to try the specific functions by yourself
w, h = inter_corner_shape
cp_int = np.zeros((w * h, 3), np.float32)
cp_int[:, :2] = np.mgrid[0:w, 0:h].T.reshape(-1, 2)
cp_world = cp_int * size_per_grid
obj_points = []
img_points = []
# Corner extraction
images = glob.glob(img_dir + os.sep + '**.' + img_type)
for fname in images:
img = cv2.imread(fname)
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# Get whether there are corners and corners
ret, cp_img = cv2.findChessboardCorners(gray_img, (w, h), None)
if ret:
# Get the optimized corner
cp_img = cv2.cornerSubPix(gray_img, cp_img, (11, 11), (-1, -1), criteria)
obj_points.append(cp_world)
img_points.append(cp_img)
# Draw corners , You can check whether corner extraction is accurate
cv2.drawChessboardCorners(img, (w, h), cp_img, ret)
cv2.imshow('FoundCorners', img)
cv2.waitKey(100)
cv2.destroyAllWindows()
# Camera calibration
# Parameters : World coordinate system coordinates , Corner coordinates , Images ,None,None( Calibration method , Default )
# We need to pay attention to :opencv The middle image is wide 、 high , And numpy Is read differently
# Parameters shall be transmitted in sequence numpy Of 1, 0 Two dimensions
_, mat_inter, coff_dis, v_rot, v_trans = cv2.calibrateCamera(obj_points,
img_points, gray_img.shape[::-1], None, None)
# Internal reference
print("internal matrix:\n", mat_inter)
# Distortion coefficient
print("distortion cofficients:\n", coff_dis)
# Rotating vector
# print("rotation vectors:\n", v_rot)
# Translation vector
# print("translation vectors:\n", v_trans)
# Project the points of the world coordinate system back to the 2D plane , Calculate the distance error between the projection point and the corner point
total_error = 0
for i in range(len(obj_points)):
img_points_repro, _ = cv2.projectPoints(obj_points[i], v_rot[i], v_trans[i], mat_inter, coff_dis)
error = cv2.norm(img_points[i], img_points_repro, cv2.NORM_L2) / len(img_points_repro)
total_error += error
print(("Average Error of Reproject: "), total_error / len(obj_points))
return mat_inter, coff_dis, cp_world4. Realization ( With detailed notes )
if __name__ == '__main__':
# Define number of corners
inter_corner_shape = (9, 6)
# Define the size of the checkerboard
size_per_grid = 0.02
# Define image path
img_dir = "./data"
# Define picture format
img_type = "jpg"
# Camera calibration
mat_inter, coff_dis, cp_world = calib(inter_corner_shape, size_per_grid, img_dir, img_type)
# Read the picture to test the calibration effect
img = cv2.imread("./data/test01.jpg")
h, w = img.shape[:2]
# new To optimize the parameter matrix ,roi by opencv Areas of interest considered , It can be used to cut the black edge after distortion removal
# When parameters 1 Change it to 0 when ,opencv Will automatically crop the image
# Be careful w and h
new, roi = cv2.getOptimalNewCameraMatrix(mat_inter, coff_dis, (w, h), 1, (w, h))
x, y, w, h = roi
print(roi)
# Image de distortion , Method 1
dst = cv2.undistort(img, mat_inter, coff_dis, None, new)
# Image de distortion , Method 2 , There is a little problem , You can try it yourself
# mapx, mapy = cv2.initUndistortRectifyMap(mat_inter, coff_dis, None, new, (w, h), 5)
# dst = cv2.remap(img, mapx, mapy, cv2.INTER_LINEAR)
cv2.namedWindow('origin', cv2.WINDOW_NORMAL)
cv2.namedWindow('no_cut', cv2.WINDOW_NORMAL)
cv2.namedWindow('cut', cv2.WINDOW_NORMAL)
cv2.namedWindow('img_with_line', cv2.WINDOW_NORMAL)
cv2.imshow('origin', img)
cv2.imshow('cut', dst[y: y+h, x: x+w])
cv2.imshow('no_cut', dst)
# Visual wiring , The process is as follows
gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
# Corner finding -> Optimize corner -> Get external parameters -> Transformation of external parameter matrix -> Select the world coordinate system points to draw -> Get the projection point of the world coordinate system point on the image -> Draw a line
ok, corners = cv2.findChessboardCorners(gray, (inter_corner_shape[0], inter_corner_shape[1]), )
if ok:
exact_corners = cv2.cornerSubPix(gray, corners, (11, 11), (-1, -1), criteria)
_, rvec, tvec, inliers = cv2.solvePnPRansac(cp_world, exact_corners, mat_inter, coff_dis)
axis = 0.02 * np.float32([[0, 0, -8], [8, 0, 0], [8, 5, 0], [0, 5, 0]]).reshape(-1, 3)
imgpts, _ = cv2.projectPoints(axis, rvec, tvec, mat_inter, coff_dis)
img = draw(img, corners, imgpts)
cv2.imshow('img_with_line', img)
cv2.waitKey(0)5. Result display

6. Code link
360sorround/calibration at main · liuweixue001/360sorround (github.com)
7. Subsequent updates
1. Image de distortion 、 Aerial view generation 、 Image mosaic 、 Image fusion :liuweixue001/360sorround: 360 Look around -- Camera calibration -> Distortion treatment -> Overhead transformation -> Image mosaic (github.com)
2. C++ Version related work :
边栏推荐
- This of phaser3 add. add. image
- [wsl2] restrict wsl2 accessible hardware resources (cpu/ memory)
- Wsl2 + vcxsrv + opengl3.3 configuration
- Implementation of pointer linked list
- Installing pytorch geometric
- How to solve the problems when using TV focusable to package APK in uni app
- [MySQL password management] - [administrator password known, unknown (forgotten), cracked]
- Reinstall opencv and step on the pit.
- ng-tv-focusable
- dfs与bfs解决宝岛探险
猜你喜欢

A DPU architecture without CPU: Hyperion

Workspace for ROS

谷歌的受众群体是如何发挥作用的?

Stm32 3*3 matrix key (register version)

白噪声的详细理解

V-inline-date, similar to Ctrip, flying pig, time selection with price

Quickly set the computer to turn off automatically

Establishment of microservice development environment

Numpy multidimensional array transpose transpose

谷歌加大型文字广告是什么?怎么用?
随机推荐
Stone from another mountain: Web3 investment territory of a16z
PyFlink实现自定义SourceFunction
受众群体应该选择观察模式还是定位模式?
如何通过受众群体定位解决实际问题?
Delphi Google API text to speech MP3 file
Traversal of binary tree - first order traversal, middle order traversal, and second order traversal
Restful interface specification annotation of pringboot (2)
Detailed understanding of white noise
Introduction to common ROS commands
TensorFlow 2.x 多显卡分布式训练
About constructive code blocks, static code blocks, and constructor execution order
Crypto JS reports uglifyjs error
Detailed explanation of maxpooling corresponding to conv1d, conv2d and conv3d machines of tensorflow2
Large end storage and small end storage
Devaxpress Chinese description -- tdxgallerycontrol object (gallery component)
pringboot之restfull接口规范注解(二)
This of phaser3 add. add. image
JSON and protobuf Any interchange
Detailed explanation of audience characteristics
Magics 23.0如何激活和使用视图工具页的切片预览功能