当前位置:网站首页>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 :
边栏推荐
- About inquirerjs
- Transaction characteristics and isolation levels
- Should the audience choose observation mode or positioning mode?
- [Andoid][踩坑]CTS 11_r3开始出现的testBootClassPathAndSystemServerClasspath_nonDuplicateClasses FAIL问题分析
- Devaxpress Chinese description -- tdxgallerycontrol object (gallery component)
- [从零开始学习FPGA编程-21]:进阶篇 - 架构 - VerilogHDL编码规范
- csdn涨薪技术之Jmeter接口测试数据库断言的实现与设计
- Introduction to common ROS commands
- Auto commit attribute of MySQL
- 【官方文件汇总】国科大学位论文撰写规范
猜你喜欢

五、库存查询功能的完善

服务器安装jupyterlab以及远程登录配置

MySQL connection query

Matplotlib drawing Chinese garbled code

Uuid/guid introduction, generation rules and generation codes

URI, URL and urn difference, relation and syntax diagram

Implementation and design of JMeter interface test database assertion for CSDN salary increase technology

什么是立体角

谷歌加大型文字广告是什么?怎么用?

Developer contributions amd Xilinx Chinese Forum sharing - wisdom of questioning
随机推荐
[从零开始学习FPGA编程-21]:进阶篇 - 架构 - VerilogHDL编码规范
[wsl2] restrict wsl2 accessible hardware resources (cpu/ memory)
Getting started with phaser 3
【官方文件汇总】国科大学位论文撰写规范
Delphi7 compressed pictures (BMP, JPG, PNG)
Transaction characteristics and isolation levels
谷歌的受众群体是如何发挥作用的?
Using atexit to realize automatic destruct of singleton mode
csdn涨薪技术之Jmeter接口测试数据库断言的实现与设计
MySQL - use field alias after where
六、出库管理功能的实现
[MySQL password management] - [administrator password known, unknown (forgotten), cracked]
MySQL connection query
白噪声的详细理解
Magics 23.0如何激活和使用视图工具页的切片预览功能
Implementation and design of JMeter interface test database assertion for CSDN salary increase technology
How do you use your own data to achieve your marketing goals?
Super complete regular expressions
PyFlink实现自定义SourceFunction
Unity jsonutility failed to serialize list