当前位置:网站首页>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 :
边栏推荐
- ng-tv-focusable
- 开发者来稿|AMD赛灵思中文论坛分享 - 提问的智慧
- [learn FPGA programming from scratch -21]: Advanced - Architecture - VerilogHDL coding specification
- MySQL ---- where后使用字段别名
- Sonarqube local installation
- Matplotlib drawing Chinese garbled code
- How to solve practical problems through audience positioning?
- [Andoid][踩坑]CTS 11_r3开始出现的testBootClassPathAndSystemServerClasspath_nonDuplicateClasses FAIL问题分析
- The interviewer only asked me five questions and the interview was over
- STM32 3*3矩阵按键(寄存器版本)
猜你喜欢

Machine learning basic SVM (support vector machine)

指针链表的实现

About tkinter Canvas does not display pictures
![[WSL2]WSL2迁移虚拟磁盘文件ext4.vhdx](/img/e9/4e08e07c2de2f99c2938e79f7f1c44.png)
[WSL2]WSL2迁移虚拟磁盘文件ext4.vhdx

Stm32 3*3 matrix key (register version)

Camera model_

What is solid angle

Devaxpress Chinese description --tdximageslider (picture rotation control)

Crypto JS reports uglifyjs error

Design of distributed game server
随机推荐
About inquirerjs
How to solve the problems when using TV focusable to package APK in uni app
如何通过受众群体定位解决实际问题?
Delphi implements adding a column of serial number to the CXGRID list
This of phaser3 add. sprite
Reinstall opencv and step on the pit.
Implementation of pointer linked list
[Andoid][踩坑]CTS 11_r3开始出现的testBootClassPathAndSystemServerClasspath_nonDuplicateClasses FAIL问题分析
Logging system in chromium
【MathType】利用MathType输出LaTex样式的公式
About the proposed signature file migration to industry standard format pkcs12
What is the path field—— Competitive advertising
VI keyboard diagram
Workspace for ROS
leetcode743. 网络延迟时间(中等, dijkstra)
pytorch : srcIndex < srcSelectDimSize
Unity JsonUtility 无法序列化List
Cmake has no obvious error after compilation, but prompts that pthread cannot be found
3、 Upload fabric photos to SQL server and provide name to display fabric photos
Spit bubbles (stack)