当前位置:网站首页>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 img
3. 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_world
4. 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 :
边栏推荐
- JSON and protobuf Any interchange
- [wsl2] restrict wsl2 accessible hardware resources (cpu/ memory)
- Record the VMware installation process of VMware Tools and some problems encountered
- (no plug-in) summary of vim basic shortcut keys
- 什么是立体角
- D template instance does not match declaration
- Implementation of pointer linked list
- leetcode743. Network latency (medium, Dijkstra)
- 开发者来稿|AMD赛灵思中文论坛分享 - 提问的智慧
- Differences among bio, NiO and AIO
猜你喜欢
A DPU architecture without CPU: Hyperion
Should the audience choose observation mode or positioning mode?
三、上传织物图片至SQL Server并提供name进行展示织物照片
Quickly set the computer to turn off automatically
What is the path field—— Competitive advertising
DFS and BFS to solve Treasure Island exploration
6、 Implementation of warehouse out management function
5、 Improvement of inventory query function
Magics 23.0如何激活和使用视图工具页的切片预览功能
六、出库管理功能的实现
随机推荐
六、出库管理功能的实现
D template instance does not match declaration
Unity JsonUtility 无法序列化List
谷歌加大型文字广告是什么?怎么用?
Devaxpress Chinese description --tcxpropertiesstore (property store recovery control)
How does Google's audience work?
五、库存查询功能的完善
pytorch : srcIndex < srcSelectDimSize
Magics 23.0 how to activate and use the slice preview function of the view tool page
Unity jsonutility failed to serialize list
4、 Improvement of warehousing management function
Auto commit attribute of MySQL
MySQL ---- where后使用字段别名
[learn FPGA programming from scratch -21]: Advanced - Architecture - VerilogHDL coding specification
Matplotlib drawing Chinese garbled code
How many smart bids does Google have?
[wsl2]wsl2 migrate virtual disk file ext4 vhdx
【软考】软件设计师知识点整理(待更新)
Stone from another mountain: Web3 investment territory of a16z
The interviewer only asked me five questions and the interview was over