## Calibrate camera

• It is not difficult to know the importance of the accuracy of the camera to the image recognition program. In order to ensure that the camera will not have serious image distortion, you can shoot the chess board through the camera, and calculate the camera matrix and distortion coefficient of the camera through the captured chessboard image. The camera calibration can be completed by loading the calculated camera matrix and distortion coefficient.

• Of course, due to the use of a flat camera, the tutorial does not load calibration parameters. If you feel that calibration is troublesome, you can skip.

#### 1、Generate an international chessboard chart

Prepare an all black picture of 630*890 and rename it to 3a4.bmp. Run the following program to get a picture of a chess board.

``````#!/usr/bin/env python3

"""Generate chess board picture"""

import os
import cv2

path = os.path.join(os.path.dirname(__file__), "3a4.bmp")
print(path)

row, col, nc = frame.shape

width_of_roi = 90
# Here is the processing of all black pictures, which are separated in black and white zh
for j in range(row):
data = frame[j]
for i in range(col):
f = int(i / width_of_roi) % 2 ^ int(j / width_of_roi) % 2
if f:
frame[j][i] = 255
frame[j][i] = 255
frame[j][i] = 255
cv2.imshow("", frame)
cv2.waitKey(0) & 0xFF == ord("q")
cv2.imwrite(os.path.join(os.path.dirname(__file__), "1.png"), frame)
``````

#### 2、Take chessboard pictures

Display the chessboard pictures on the computer and take multiple chessboard pictures through the camera.

``````#!/usr/bin/env python3

"""
This is an auxiliary file to help calibrate the camera.

It will call the camera, get the picture and display it in real time.

You can enter any value in the console to save the picture.
"""

import os
import cv2

if_save = False
# Set the camera number (due to different computer models, the number assigned to the USB camera may be different, usually 0 or 1)
cap_num = int(input("Input the camare number:"))
# Set the name of the stored picture to 1, which means that it is accumulated and stored from 1. For example: 1.jpg, 2.jpg, 3.jpg.....
name = int(input("Input start name, use number:"))

cap = cv2.VideoCapture(cap_num)
dir_path = os.path.dirname(__file__)

def save():
global if_save
while True:
input("Input any to save a image:")
if_save = True

# Start the thread for camera shooting
# Set to run asynchronously
t.setDaemon(True)
t.start()

while cv2.waitKey(1) != ord("q"):
if if_save:
# Set the name to the current path, otherwise the storage location will change due to the running environment
img_name = os.path.join(dir_path,str(name)+".jpg")
# Store pictures
cv2.imwrite(img_name, frame)
print("Save {} successful.".format(img_name))
name += 1
if_save = False
cv2.imshow("", frame)
``````

#### 3、Obtain the camera matrix and distortion coefficient

• Opencv has its own camera calibration function, which automatically generates the camera matrix and distortion coefficient we need by identifying the grid in the chessboard. Here we just need to make sure that the pictures taken in the second step can be recognized. It doesn't matter if we all recognize the failure. We just need to repeat the second step again. Of course, if you don't want to repeat the second and third steps in such trouble, you can directly skip the second step,

• In the third step, when calling the calibration_camera function, set the cap_num parameter, that is, the camera number, and conduct real-time processing to obtain the camera and distortion coefficient. For detailed instructions, you can carefully read the comments in the code.

``````#!/usr/bin/env python3
import os
import glob
import numpy as np
import cv2 as cv
from pprint import pprint

def calibration_camera(row, col, path=None, cap_num=None, saving=False):
"""Calibrate camera

Parameter Description:
row (int): the number of rows in the grid.
col (int): the number of columns in the grid.
path (string): the location where the calibration picture is stored.
cap_num (int): indicates the number of the camera, usually 0 or 1
saving (bool): whether to store the camera matrix and distortion coefficient (. npz)
"""

# Termination criteria / failure criteria
criteria = (cv.TERM_CRITERIA_EPS + cv.TERM_CRITERIA_MAX_ITER, 30, 0.001)
# Prepare object points, such as (0,0,0), (1,0,0), (2,0,0) ....,(6,5,0)
obj_p = np.zeros((row * col, 3), np.float32)
obj_p[:, :2] = np.mgrid[0:row, 0:col].T.reshape(-1, 2)
# Groups are used to store object points and image points from all images.
obj_points = []  # The position of 3D points in the real world.
img_points = []  # Position of 2D point in the picture.

gray = None

def _find_grid(img):
# Use parameters outside the function
nonlocal gray, obj_points, img_points
# Convert picture to gray picture
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
# Look for the corner of the chessboard
ret, corners = cv.findChessboardCorners(gray, (row, col), None)
# If found, the processed 2D points and 3D points are added
if ret == True:
obj_points.append(obj_p)
corners2 = cv.cornerSubPix(gray, corners, (11, 11), (-1, -1), criteria)
img_points.append(corners)
# Draw and show the corner found in the picture
cv.drawChessboardCorners(img, (row, col), corners2, ret)

# It is required that you must select one of image calibration or camera real-time capture calibration
if path and cap_num:
raise Exception("The parameter `path` and `cap_num` only need one.")
# Picture calibration
if path:
# Get all pictures in the current path
images = glob.glob(os.path.join(path, "*.jpg"))
pprint(images)
# Process each acquired picture
for f_name in images:
_find_grid(img)
# Show pictures
cv.imshow("img", img)
# Picture display wait for 0.5s
cv.waitKey(500)
# Camera real-time capture calibration
if cap_num:
# Turn on the camera
cap = cv.VideoCapture(cap_num)
while True:
# Read every picture after the camera is turned on
_find_grid(img)
cv.imshow("img", img)
cv.waitKey(500)
print(len(obj_points))
if len(obj_points) > 14:
break
# Destroy display window
cv.destroyAllWindows()
# The camera matrix and distortion coefficient are obtained by calculating the obtained 3D points and 2D points
ret, mtx, dist, rvecs, tvecs = cv.calibrateCamera(
obj_points, img_points, gray.shape[::-1], None, None
)
print("ret: {}".format(ret))
print("matrix:")
pprint(mtx)
print("distortion: {}".format(dist))
# Decide whether to store the calculated parameters
if saving:
np.savez(os.path.join(os.path.dirname(__file__), "mtx_dist.npz"), mtx=mtx, dist=dist)

mean_error = 0
for i in range(len(obj_points)):
img_points_2, _ = cv.projectPoints(obj_points[i], rvecs[i], tvecs[i], mtx, dist)
error = cv.norm(img_points[i], img_points_2, cv.NORM_L2) / len(img_points_2)
mean_error += error
print("total error: {}".format(mean_error / len(obj_points)))

return mtx, dist

if __name__ == "__main__":
path = os.path.dirname(__file__)
mtx, dist = calibration_camera(8, 6, path, saving=True)
# Set whether the calculated parameters need to be tested
if_test = input("If testing the result (default: no), [yes/no]:")
if if_test not in ["y", "Y", "yes", "Yes"]:
exit(0)

cap_num = int(input("Input camera number:"))
cap = cv.VideoCapture(cap_num)
while cv.waitKey(1) != ord("q"):
h, w = img.shape[:2]
# Camera calibration
dst = cv.undistort(img, mtx, dist)
cv.imshow("", dst)
``````

#### 4、Load camera matrix and distortion factor

``````"""Load calibration parameters to calibrate the camera."""

import os
import numpy as np
import cv2 as cv

if __name__ == "__main__":