Tags: Калибровка камера матрица внешние внутренние параметры вращение перенос OpenCV искажения объектива шахматная доска Python
Введение
Матрица внешних параметров камеры
Матрица внутренних параметров камеры
Коэффициенты радиальных и тангенциальных искажений объектива
Особенности калибровки камеры с помощью шахматной доски
Подготовка изображений для калибровки
Выполнение калибровки
Точность калибровки
Сохранение результатов калибровки
Полезные ссылки
Введение
Калибровка — это процедура установления зависимости между входом (эталонные данные) и выходом (измеренные данные)
Калибровка камеры – это задача получения точных математических отношений между точками в 3D пространстве и их 2D проекциями на экране камеры. Цель процесса калибровки — найти матрицы внешних и внутренних параметров, а также коэффициенты радиальных и тангенциальных искажений объектива.
Одна из стандартных процедур калибровки камеры — это использование шаблона шахматной доски. Система координат камеры связывается с системой координат шахматной доски через распознавание углов клеток шахматной доски. По угловым точкам через решение системы уравнений определяются параметры калибровки.
Алгоритм калибровки одной камеры, а также алгоритм стереокалибровки реализован в библиотеке OpenCV.
Матрица внешних параметров
При калибровке внешние параметры определяют взаимное положение камеры и шахматной доски. Перед выводом зависимостей необходимо знать, как привязаны системы координат к этим элементам и какой из них подвижен.
На основе анализа результатов использования функций OpenCV определяем по элементам матрицы смещений, что СК камеры неподвижна, а шахматная доска перемещается относительно нее.
Оси X и Y направлены соответственно влево и вниз. Начало СК шахматной доски привязано к левой верхней вершине. Начало СК камеры находится в точке оптического центра (подробнее см. внутренние параметры камеры).
Для определения положения объекта в 3D пространстве достаточно 6 независимых параметров — 3 угла и 3 перемещения. Выбираем 6 удобных параметров и указываем с ними последовательность из 6 элементарных преобразований:
- Перемещение на расстояние h вдоль оси Z
- поворот на угол γ вокруг оси Z
- поворот на угол β вокруг оси X
- поворот на угол α вокруг оси Y
- перемещение на расстояние n вдоль оси X
- перемещение на расстояние p вдоль оси Y
Для каждого из 6 преобразований запишем матрицы в однородных координатах :
Затем получаем композицию матриц, последовательно перемножая их.
Функция cv2.calibrateCamera выполняет основную задачу по калибровке. Она возвращает векторы поворота (3 * 1) и векторы переноса (3 × 1) калибровочного шаблона относительно камеры. Функция cv2.Rodrigues (rvec) преобразует вектор поворота в матрицу вращения. Функция np.concatenate((R_matrix, tvec), axis=1) объединяет матрицу вращения и вектор переноса в матрицу движения:
Сопоставляя элементы обоих матриц получаем 6 параметров:
Тестирую полученные выражения (программный код приводится ниже):
По модулю и по знаку углы beta, alpha и gamma соответствуют.
Сравниваю результаты для перемещений n, p и h с элементами матрицы смещений для того же фрейма (см. рисунок в начале подраздела).
Эти результаты также соответствуют.
Матрица внутренних параметров
Внутренние параметры определяют проективное преобразование от координат 3-D камеры в 2D координаты изображений в пиксельном представлении.
В матричном виде это преобразование записывается:
Положение точек снимка определяется в пиксельной системе координат uv, начало которой совмещено с верхним левым пикселем изображения.
Координаты центрального пикселя Cx и Cy (оптический центр) находятся на пересечении главной оптической оси объектива с матрицей камеры. Они также как и координаты любой другой точки на изображении определяются в пикселях — округляются с точностью до пикселя.
Посмотрим, как получена матрица внутренних параметров. Представим СК xyz, начало которой совпадает с фокусом камеры. Определим зависимости для проективного преобразования 3D координат xyz в 2D координаты изображения (uv) — в пиксельных единицах измерения:
- Из подобия треугольников получаем соотношения
- После ввода обозначений эти соотношения запишутся
- Переходим к пиксельному представлению координат
- Вводим обозначение
пиксели в датчике изображения могут быть не квадратными, поэтому у нас два разных фокусных расстояния fx и fy.
- получаем зависимости
Более простое для восприятия представление зависимостей:
Первые слагаемые в зависимостях для u и v округляются до целого.
В матричном виде зависимости запишутся:
или
Знак при координате y’ зависит от разновидности системы координат цифрового изображения. Различают две прямоугольных системы координат:
- началом которой является левый верхний пиксел — так называемая левая система координат (СК).
- началом которой является левый нижний пиксел — правая СК;
В фотограмметрии традиционно применяется левая СК (на рис. слева). В оконных WinAPI приложениях также используют эту систему координат. Правая СК (на рис. справа) принята при записи изображений в файл во всех форматах (включая и формат BMP файла). Для перехода из одной СК в другую достаточно выполнить преобразование v=H-u, где H — размер изображения в пикселях по вертикали.
Коэффициенты радиальных и тангенциальных искажений объектива
Коэффициенты искажения и коррекция
Существуют два основных вида дисторсии: радиальная дисторсия и тангенциальная дисторсия.
Радиальная дисторсия — искажение изображения в результате неидеальности параболической формы линзы. Искажения, вызванные радиальной дисторсией, равны 0 в оптическом центре сенсора и возрастают к краям. Как правило, радиальная дисторсия вносит наибольший вклад в искажение изображения.
Тангенциальная дисторсия — искажения изображения, вызванные погрешностями в установке линзы параллельно плоскости изображения.
Для устранения дисторсии координаты пикселей пересчитываются с помощью следующих уравнений:
- k1, k2, k3 — коэффициенты радиальной дисторсии (их может быть и больше, см. Camera Calibration),
- p1, p2 — коэффициенты тангенциальной дисторсии.
Особенности калибровки камеры с помощью шахматной доски
Одна из стандартных процедур для вычисления всех неизвестных, указанных выше, или простой калибровки камеры — это использование шаблона шахматной доски. Система координат камеры связывается с системой координат шахматной доски через распознавание углов клеток шахматной доски (места, где два темных квадрата касаются друг друга).
Такие точки легко распознаются. OpenCV предоставляет ряд функций для калибровки камер использованием шаблона шахматной доски (см. Выполнение калибровки).
Можно скачать изображение шахматной доски, распечатать его на принтере и приклеить на жесткую плоскую поверхность — стекло, картон или фанеру. К подготовке шаблона необходимо подходить с особой тщательностью. Подробнее см. статью Калибровка монокулярной камеры и комментарии к статье Как проверить правильность калибровки вебкамеры?.
Образец шахматной доски для калибровки не может быть квадратным. Это позволяет системе однозначно определять последовательность вершин — слева направо вдоль ряда и сверху вниз по рядам.
Если шахматная доска квадратная, то первая вершина однозначно не определена — может изменяться при повороте доски или камеры.
Подготовка изображений для калибровки
Итак, нам нужно выполнить калибровку Web-камеры, встроенной в notebook, по автоматически распознаваемым координатам вершин шахматной доски.
Мы должны заснять шахматную доску при разных ориентациях относительно Web-камеры. Можно зафиксировать камеру, а смещать шахматную доску. С точки зрения математики это одно и тоже.
Для подготовки изображений с Web-камеры ноутбука используем следующее Python приложение:
# Import Libraries import cv2 # Input "0" means your connected usb webcap. Can be replaced with a RTSP url cap = cv2.VideoCapture(0) cv2.namedWindow("Image Acquisition") # For file naming imgNum = 0 while True: ret, frame = cap.read() if not ret: print("Cannot Read Frame!!!") break cv2.imshow("Image Acquisition", frame) comm = cv2.waitKey(1) if comm%256 == 27: # ESC key is pressed print(" Command: Ending program..") break elif comm%256 == 32: # SPACE key is pressed fileName = "CalibFrame{}.png".format(imgNum) cv2.imwrite(fileName, frame) imgNum += 1 print(" Command: {} is saved!".format(fileName)) cap.release() cv2.destroyAllWindows()
Запускаете приложение, ожидаете, пока включится камера. Выбираете ориентацию шахматной доски и нажимаете клавишу SPACE. В результате этого сохраняется png-файл изображения в директории проекта, где находится файл кода. Создайте несколько изображений (> 10) и нажмите клавишу ESC для выхода из программы.
Выбирайте ориентацию шахматной доски под наклоном и на расстоянии около 1м.
Выполнение калибровки
Создаем новый Python проект и помещаем изображения для калибровки камеры в папке frames — внутри проекта, там же, где и код приложения. Изображение для тестирования помещаем внутри проекта в папке frames_test.
Следующий Python код калибрует камеру по подготовленным изображениям и демонстрирует тестируемое изображение до и после калибровки:
Перед запуском программы обратите внимание, чтобы значение переменных boardWidth и boardHeight соответствовало количеству вершин шахматной доски. Если соответствия не будет, такие изображения программой игнорируются.
import cv2 import numpy as np import glob import matplotlib.pyplot as plt import pickle boardWidth = 7 boardHeight = 6 # Prepare object points, like (0,0,0), (1,0,0), (2,0,0) ....,(6,5,0) objp = np.zeros((boardHeight*boardWidth,3), np.float32) objp[:,:2] = np.mgrid[0:boardWidth, 0:boardHeight].T.reshape(-1,2) # Arrays to store object points and image points from all the images. objpoints = [] # 3d points in real world space imgpoints = [] # 2d points in image plane. # Make a list of calibration images images = glob.glob('./frames/CalibFrame*.png') # Step through the list and search for chessboard corners for idx, fname in enumerate(images): img = cv2.imread(fname) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # Find the chessboard corners ret, corners = cv2.findChessboardCorners(gray, (boardWidth,boardHeight), None) # If found, add object points, image points if ret == True: objpoints.append(objp) imgpoints.append(corners) # Draw and display the corners cv2.drawChessboardCorners(img, (boardWidth,boardHeight), corners, ret) #write_name = 'corners_found'+str(idx)+'.jpg' #cv2.imwrite(write_name, img) cv2.imshow('img', img) cv2.waitKey(500) cv2.destroyAllWindows() # Read a test image fname = './frames_test/CalibFrame50.png' img = cv2.imread(fname) img_size = (img.shape[1], img.shape[0]) # Do camera calibration given object and image points rms, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, img_size,None,None) print("Img_size:") print(img_size) print("\nCamera matrix:") print(mtx) print("\nDistor_coeffs:") print(dist) #print("\nR_vecs:") #for rvec in rvecs: #print(rvec) #print("\nT_matrix:") #for tvec in tvecs: #print(tvec) print ("\nError(RMS): ", rms) # Re-projection Error mean_error = 0 for i in range(len(objpoints)): imgpoints2, _ = cv2.projectPoints(objpoints[i], rvecs[i], tvecs[i], mtx, dist) error = cv2.norm(imgpoints[i],imgpoints2, cv2.NORM_L2)/len(imgpoints2) mean_error += error print ("\nTotal error: ", mean_error/len(objpoints)) newcameramtx, roi = cv2.getOptimalNewCameraMatrix (mtx, dist, img_size, 1, img_size) dst = cv2.undistort(img, mtx, dist, None, newcameramtx) cv2.imwrite('./frames_test/Undist.png',dst) img = cv2.imread(fname) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # Find the chessboard corners ret, corners = cv2.findChessboardCorners(gray, (boardWidth,boardHeight), None) objp = objp.astype('float32') corners = corners.astype('float32') _, rvec, tvec = cv2.solvePnP(objp, corners, mtx, dist) print("\nR_vec_test:") print(rvec) print("\nT_vec_test:") print(tvec) # Calculate euler angle print("\nR_matrix_test:") R_matrix, _ = cv2.Rodrigues(rvec) print(R_matrix) print(tvec) Rt = np.concatenate((R_matrix, tvec), axis=1) print("\nRt_matrix_test:") print(Rt) beta = asin(Rt[2,1]) beta_dgrs = 180*beta/3.14159 print ("\nbeta: ", beta_dgrs) alpha = asin(-Rt[2,0]/cos(beta)) #alpha = acos(Rt_matrix[2,2]/cos(beta)) # acos дает только полож. результаты alpha_dgrs = 180*alpha/3.14159 print ("alpha: ", alpha_dgrs) gamma = asin(-Rt[0,1]/cos(beta)) gamma_dgrs = 180*gamma/3.14159 print ("gamma: ", gamma_dgrs) n=(Rt[1,3]*Rt[0,1]-Rt[0,3]*Rt[1,1])/(Rt[1,0]*Rt[0,1]-Rt[0,0]*Rt[1,1]) print ("n: ", n) p= (Rt[0,3]-n*Rt[0,0])/Rt[0,1] print ("p: ", p) h= Rt[2,3]-p*Rt[2,1]-n*Rt[2,0] print ("h: ", h) # Visualize calibrated result f, (ax1, ax2) = plt.subplots(1, 2, figsize=(6,3)) ax1.imshow(img) ax1.set_title('Original Image', fontsize=10) ax2.imshow(dst) ax2.set_title('Undistorted Image', fontsize=10) plt.show()
Функция cv2.calibrateCamera выполняет основную задачу по калибровке. Она оценивает внутренние и внешние параметры камеры для каждого из видов калибровочного шаблона. Алгоритм основан на A Flexible New Technique for Camera Calibration и Camera Calibration Toolbox for Matlab.
Для калибровки необходимо знать координаты точек 3D-объекта и определить соответствующие им 2D-проекции. Этого несложно добиться, используя объект с известной геометрией и легко обнаруживаемыми характерными точками. Такой объект называется калибровочным шаблоном, и OpenCV имеет встроенную поддержку шахматной доски в качестве такого шаблона (см. FindChessboardCorners).
rms, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, img_size,None,None)
Входные параметры:
- objpoints — 3d points in real world space. Вектор векторов точек калибровочного образца в 3d пространстве.
- imgpoints — 2d points in image plane. Вектор векторов проекций точек калибровочного шаблона.
- img_size — (img.shape[1], img.shape[0]) . Размер изображения
Возвращаемые значения:
- rms — (Root Mean Square, RMS) среднеквадратичное значение ошибки повторного проецирования
- mtx — внутренняя матрица камеры (параметры fx,fy, Cx,Cy)
- dist — коэффициенты искажения линз ( k1, k2, k3, p1,p2)
- rvecs — массив векторов поворота (3 * 1) калибровочного шаблона относительно камеры. Направление вектора поворота определяет ось вращения, а модуль вектора определяет угол поворота.
- tvecs — Вектора переноса (3 × 1) калибровочного шаблона относительно камеры.
Функция построена на итеративном алгоритме оптимизации. Алгоритм выполняет следующие шаги:
- Вычисляются начальные внутренние параметры. При этом все коэффициенты искажения изначально установлены на нули.
- Оценивается исходная позиция камеры, как если бы внутренние параметры были точно уже известны. Это делается с помощью solvePnP.
- Запускается глобальный алгоритм оптимизации Левенберга-Марквардта, чтобы минимизировать ошибку перепроецирования, то есть общую сумму квадратов расстояний между наблюдаемыми характерными точками imagePoints и проецируемыми (с использованием текущих оценок внутренних и внешних параметров камеры) точками объекта objectPoints.
Функция возвращает окончательную ошибку повторного проецирования rms
Функция SolvePnP.
found, rvec, tvec = cv2.solvePnP(objp, corners, mtx, dist)
где found — (True или False). Смысл других параметров функции solvePnP аналогичен функции calibrateCamera.
В чем разница между SolvePnP и CalibrateCamera? Функция solvePnP принимает внутренние параметры mtx, dist в качестве входных данных и возвращает внешние параметры rvec, tvec . А функция CalibrateCamera возвращает по точкам изображений, используемых для калибровки, как внешние так и внутренние параметры для всех изображений.
Логика использования этих функций следующая. При изменении положения камеры ее внутренние параметры сохраняются. Поэтому, можно сначала откалибровать внутренние параметры камеры с помощью calibrateCamera, а затем использовать функцию solvePnP для определения внешних параметров камеры по заданным внутренним параметрам и точкам всего лишь одного изображения.
Обратите внимание: если внутренние параметры известны, нет необходимости использовать эту функцию calibrateCamera только для оценки внешних параметров. Вместо этого используйте solvePnP.
Сравнил внешние параметры камеры для одного и того же изображения, определяемые обеими функциями. Они оказались практически одинаковыми. Это объяснимо, поскольку, по сути, была добавлена еще одна итерация в алгоритм оптимизации, используемый в функции calibrateCamera .
Функция cv2.getOptimalNewCameraMatrix.
Подобранные при калибровке коэффициенты дисторсии устраняют искажения только вокруг шахматной доски. За ее пределами искажения усиливаются — очевидно, это компенсация за выравнивание изображения вокруг шахматной доски. Изображение после калибровки может быть представлено обрезанным — удаляется часть рисунка с искажениями. Для этого значение 3-го параметра указанной ниже функции заменяется (с 1 на 0):
newcameramtx, roi = cv2.getOptimalNewCameraMatrix (mtx, dist, img_size, 0, img_size) dst = cv2.undistort(img, mtx, dist, None, newcameramtx) cv2.imwrite('./frames_test/Undist.png',dst)
Функция cv2.Rodrigues
R_matrix, _ = cv2.Rodrigues(rvec)
Эта функция преобразует вектор поворота rvec (3 * 1), возвращаемый функциями calibrateCamera и solvePnP, в матрицу поворота (3 * 3). Кроме этого, вы можете объединить их в матрицу движения [R t]:
Rt_matrix = np.concatenate((R_matrix, tvec), axis=1)
Точность калибровки
Точность калибровки камеры оценивается по среднеквадратичной ошибке (Root Mean Square Error, RMS Error, RMSE) перепроецирования точки.
Что такое ошибка перепроецирования точки? По положению точки, как минимум на двух изображениях камеры, вычисляются ее трехмерные координаты с использованием внутренних и внешних параметров камеры.
Как только трехмерные координаты точки вычислены, трехмерная точка повторно проецируется на все изображения, которые она появляется. Расстояние между отмеченной и перепроецированной точкой на одном изображении является ошибкой перепроецирования точки.
Функция cv2.calibrateCamera возвращает среднеквадратичную ошибку повторного проецирования (rms), обычно она должна находиться в пределах от 0.1 до 1.0 пикселя при хорошей калибровке.
Среднеквадратичная ошибка 1.0 означает, что в среднем каждая из перепроецируемых точек (Reprojected point) находится на расстоянии 1.0 пикселя от своего фактического положения (3D point, marked on the image).
Rms находится через решение задачи оптимизации — определяется набор параметров (cameraMatrix, distCoeffs, rvecs и tvecs), который минимизирует rms итеративно.
What does the getOptimalNewCameraMatrix do in OpenCV?
Сохранение результатов калибровки
см. Калибровка камеры Intel RealSense d435 с помощью OpenCV и ROS
# калибрируем и сохраняем результаты ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1],None,None) np.save('/path_to_images/calibration', [mtx, dist, rvecs, tvecs])
После того, как мы исполним скрипт, результаты калибрования будут сохранены в файл
calibration.npy. Эти данные затем можно использовать следующим скриптом:
calibration_data = np.load('path_to_images/calibration.npy') mtx = calibration_data[0] dist = calibration_data[1] rvecs = calibration_data[2] tvecs = calibration_data[3]
Полезные ссылки:
- Нежное введение в геометрическое глубокое обучение
- Калибровка при обработке изображений
- Lane finding using advanced Computer Vision for Self-Driving cars
- 3D position estimation of a known object using a single camera
- Measuring Planar Objects with a Calibrated Camera
- Каков наилучший метод калибровки камеры?
- Как проверить правильность калибровки a webcam?
- Значение возвращаемого значения retval в cv2.CalibrateCamera
- What is the reprojection error
- Калибровка (Градуировка)
- ЛИНЗА ОБЪЕКТИВА – ОСНОВНЫЕ ТИПЫ ОБЪЕКТИВОВ
- Измерение и коррекция искажений изображения, вызванных дисторсией объектива сканера
- Калибровка камеры (Материал из Википедии)
- Camera calibration: Explaining camera distortions
- Fine Tune of the Mapping Matrix for Camera Calibrationusing Particle Swamp Optimization
- Analysis of reprojection error of calibrateCamera function projectPoints function in OpenCV camera correction!!!!!
- Серия беспилотных датчиков Fusion — внутренняя эталонная калибровка камеры
- Обзор методов и технологий отслеживания положения для виртуальной реальности
- Метод автоматической внешней калибровки камеры
- Общая формулировка задачи внешней калибровки камеры
- Шесть степеней свободы: 3D object detection и не только
- Калибровка камеры с использованием с OpenCV
- Calibration Overview
- Camera Calibration Using Homography Estimation!!!
- Augmented reality with Python and OpenCV
- Projector Calibration for Pattern Projection Systems
- [Python — OpenCV] project practice — pose estimation
- Среднеквадратичная ошибка (RMSE)
- Алгоритмы калибровки камеры
- Camera Calibration and 3D Reconstruction (функции OpenCV)
- МЕТОДЫ КАЛИБРОВКИ ЦИФРОВЫХ КАМЕР
- Camera calibration: analysis from the world coordinate system to the image pixel coordinate system conversion process
- Визуализация малых отверстий и геометрическая калибровка камеры
- Я пытаюсь использовать cv2.solvePnP (), но получаю сообщение об ошибке
- What format does cv2.solvePnP use for points in Python?
- What is the difference between solvePnP and calibrateCamera in opencv?
- Monocular camera calibration (reproduced)
- Проектная работа РАЗРАБОТКА И СОЗДАНИЕ ПРОГРАММЫ ДЛЯ КАЛИБРОВКИ КАМЕРЫ ПОД КВАДРОКОПТЕР «КЛЕВЕР»
- Коэффициенты искажения и коррекция!!!
- OpenCV Camera Calibration
- Illustration of corner ordering
- Camera Calibration using OpenCV
- Calibrating Multi Camera Rig for Point Clouds Acguisition
- Калибровка неметрических цифровых фото и видеокамер для фотограмметрических измерений
- Калибровка камеры с использованием с OpenCV
- Camera Calibration!!!
- Camera calibration With OpenCV
- Calibrating a camera: Theory
- Dissecting the Camera Matrix, Part 3: The Intrinsic Matrix
- Calculate X, Y, Z Real World Coordinates from Image Coordinates using OpenCV
- Reprojection error
- What Is Camera Calibration?
- Camera Calibration!
- Лабораторная калибровка цифровых камер с большой дисторсией
- Фотограмметрическая калибровка цифровых съемочных камер
- О некоторых способах калибровки видеокамеры
- Camera calibration: Explaining camera distortions
- Camera Calibration and 3D Reconstruction!
- The Beginner’s Guide: Camera Calibration (Un-distortion)!!!
- Калибровка Kinect v2 с помощью OpenCV на Python
- Understanding Lens Distortion
- Калибровка камеры мобильного телефона
- Improving Convolutional Networks With Self-Calibrated Convolutions
- Исследование процесса калибровки и оптических характеристик стереонасадки 3Dberry
Автор: Николай Свирневский