{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Halszem optikák kalibrációja OpenCV-vel\n", "\n", "Az eljárás itt is hasonló a projektív optika kalibrációjához, azonban a halszemoptikák (és az omnidirekcionális optikák) geometriai tulajdonságai mások. Ezt figyelembe véve az OpenCV-ben megtaláljuk a ```cv2.fisheye``` csomagot, amelyet a halszemoptikák kalibrációjához használhatunk. \n", "\n", "## A kalibráció lépései\n", "\n", "1. A kalibrációs mintát tartalmazó képek beolvasása. \n", "2. A képek szürkeárnyalatosság konvertálása.\n", "3. Ideális rácsminta inicializálása\n", "4. Sarokpontok keresése a képen. Ha találtunk a mintának megfelelő sarokpontokat, akkor a képpontok koordinátáit felvesszük a képpontokat tartalmazó tömbbe. \n", "5. A ```cv2.fisheye.calibrate()``` függvénnyel elvégezzük a kalibrációt. Ez a függvény abban különbözik a projektív kalibrációhoz használhatos ```cv2.calibrateCamera()``` függvénytől, hogy az inicializált $K$ kamera mátrixot és $D$ disztorzítós együttható-vektort is meg kell adni paraméterként. \n", "6. Az optika belső paramétereit ismét a ```cv2.calibrationMatrixValues()``` függvénnyel kapjuk, hiszen a kamera mátrixunk most is $3\\times 3$-as mátrix. \n", "\n" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "reading images:\n", "kamera_kalibracio/python_code/fisheye_8mm_grid22mm/Chessboard_01.jpg\n", "True\n", "kamera_kalibracio/python_code/fisheye_8mm_grid22mm/Chessboard_02.jpg\n", "True\n", "kamera_kalibracio/python_code/fisheye_8mm_grid22mm/Chessboard_03.jpg\n", "True\n", "kamera_kalibracio/python_code/fisheye_8mm_grid22mm/Chessboard_04.jpg\n", "True\n", "kamera_kalibracio/python_code/fisheye_8mm_grid22mm/Chessboard_05.jpg\n", "True\n", "kamera_kalibracio/python_code/fisheye_8mm_grid22mm/Chessboard_06.jpg\n", "True\n", "kamera_kalibracio/python_code/fisheye_8mm_grid22mm/Chessboard_07.jpg\n", "True\n", "kamera_kalibracio/python_code/fisheye_8mm_grid22mm/Chessboard_08.jpg\n", "True\n", "kamera_kalibracio/python_code/fisheye_8mm_grid22mm/Chessboard_09.jpg\n", "False\n", "kamera_kalibracio/python_code/fisheye_8mm_grid22mm/Chessboard_10.jpg\n", "True\n", "kamera_kalibracio/python_code/fisheye_8mm_grid22mm/Chessboard_11.jpg\n", "True\n", "kamera_kalibracio/python_code/fisheye_8mm_grid22mm/Chessboard_12.jpg\n", "True\n", "kamera_kalibracio/python_code/fisheye_8mm_grid22mm/Chessboard_13.jpg\n", "True\n", "K = [[1.70558950e+03 0.00000000e+00 2.38483963e+03]\n", " [0.00000000e+00 1.70474917e+03 1.59237682e+03]\n", " [0.00000000e+00 0.00000000e+00 1.00000000e+00]]\n", "D = [[-0.04010495]\n", " [ 0.04333119]\n", " [-0.0755851 ]\n", " [ 0.0408196 ]]\n", "rms = 0.6414400771612184\n", "focalLength = 8.219275977408246\n", "fovx = 108.65485619096727\n", "fovy = 85.79382371835727\n", "aspectRatio = 0.9995073137591669\n" ] } ], "source": [ "## A forráskód az OpenCV függvénykönyvtár hivatalos tutorialja alapján \n", "## készült. \n", "## Dr. Németh Gábor \n", "## Szegedi Tudományegyetem\n", "\n", "import numpy as np\n", "import cv2\n", "import cv2.fisheye\n", "import glob\n", "import os\n", "\n", "IMAGES_DIR='kamera_kalibracio/python_code/fisheye_8mm_grid22mm'\n", "gridsize = 22 ## laptop:22, monitor 37 mm egy négyzet a mintán\n", "SENSOR_WIDTH=22.9 # canon eos 50d = 22.3mm\n", "SENSOR_HEIGHT=14.9 # canon eos 50d = 14.9mm\n", "\n", "#megállási feltétel a subpixel kereséshez\n", "criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)\n", "\n", "#valós világbeli pontok\n", "real_world_points = np.zeros( (1,6*9, 3), np.float32) \n", "\n", "# egy 6x9-os minta lesz, amely tuladonképpen egy rács, a Z koordináta mindenhol 0\n", "real_world_points[0,:,:2] = np.mgrid[0:6*gridsize:gridsize,0:9*gridsize:gridsize].T.reshape(-1,2) \n", "\n", "# ezekben a tömbökben tároljuk a pontokat minden fényképhez\n", "objpoints = [] # a 3D valós világbeli pontoknak\n", "imgpoints = [] # a képen detektált pontoknak\n", "\n", "images = glob.glob(IMAGES_DIR+'/Chessboard*.jpg')\n", "#print(images)\n", "img = cv2.imread(IMAGES_DIR+'/Chessboard_01.jpg')\n", "gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)\n", "imgsize = gray.shape[::-1]\n", "\n", "## -----------------\n", "## képek beolvasása\n", "## -----------------\n", "image_counter = 0;\n", "# végighaladunk a képeken\n", "print('reading images:'); \n", "for fname in images:\n", "\tprint(fname)\n", "\timg = cv2.imread(fname)\n", "\tgray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # a képet szürkeárnyalatossá konvertáljuk\n", "\t\n", "\t## Megkeressük a sarokpontokat a sakktáblán\n", "\tret, corners = cv2.findChessboardCorners(gray, (6,9), None, cv2.CALIB_CB_FAST_CHECK | cv2.CALIB_CB_NORMALIZE_IMAGE | cv2.CALIB_CB_ADAPTIVE_THRESH );\n", "\t\n", "\t## ha találtunk (ret == True), akkor \n", "\t## az objpoints tömbhöz hozzáadjuk a valós világbeli pontrácsot\n", "\t## az imgpointshoz pedig a képen detektált sarokpontokat\n", "\tprint(ret)\n", "\tif ret == True:\n", "\t\tobjpoints.append(real_world_points)\n", "\t\tcorners2 = cv2.cornerSubPix(gray, corners, (11,11), (-1,-1), criteria)\n", "\t\timgpoints.append(corners2)\n", "\t\t\n", "\t\t# kirajzoljuk a képre a megtalált sarokpontokat \n", "\t\t##print('rajzolunk')\n", "\t\timg = cv2.drawChessboardCorners(img, (6,9), corners2, ret)\n", "\t\tcv2.imwrite('corners_' + os.path.basename(fname), img )\n", "\t\t#cv2.imshow('img', img)\n", "\t\t#cv2.waitKey(500);\n", "\t\t\n", "#cv2.destroyAllWindows();\n", "\n", "\n", "## --------------------\n", "## Kalibráció \n", "## --------------------\n", "calibration_flags = cv2.fisheye.CALIB_RECOMPUTE_EXTRINSIC+cv2.fisheye.CALIB_CHECK_COND+cv2.fisheye.CALIB_FIX_SKEW\n", "# rms: visszatérési érték\n", "# K: kamera mátrix\n", "# D: disztorziós együtthatók\n", "# rvecs: forgatás mátrix paraméterek\n", "# tvecs: eltolás vektor paraméterek\n", "K = np.zeros((3,3))\n", "D = np.zeros((4,1))\n", "N_OK = len(objpoints)\n", "rvecs = [np.zeros((1,1,3), dtype=np.float64) for i in range(N_OK)]\n", "tvecs = [np.zeros((1,1,3), dtype=np.float64) for i in range(N_OK)]\n", "rms, _, _, _, _ = cv2.fisheye.calibrate(objpoints, imgpoints, imgsize, K, D, rvecs, tvecs, calibration_flags, (cv2.TERM_CRITERIA_EPS+cv2.TERM_CRITERIA_MAX_ITER, 30, 1e-6))\n", "\n", "fovx, fovy, focalLength, principalPoint, aspectRatio = cv2.calibrationMatrixValues(K,imgsize, SENSOR_WIDTH,SENSOR_HEIGHT)\n", "## kb 5mm-es apertúra mellett kapom meg a valódi értékeket\n", "\n", "#print('Calibration result: ' + ret)\n", "#if ret == True:\n", "print('K = ' +str(K))\n", "print('D = ' + str(D))\n", "print('rms = ' + str(rms))\n", "print('focalLength = ' + str(focalLength) )\n", "print('fovx = ' + str(fovx) )\n", "print('fovy = ' + str(fovy) )\n", "print('aspectRatio = ' + str(aspectRatio) )\n", "\t\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## A kalibrációs program futtatása\n", "\n", "1. Töltsük le a [fisheye_calibration.py](kamera_kalibracio/python_code/fisheye_calibration.py) forrásfájlt, valamint a [15 mm-es fókuszávolsággal készült képeket](kamera_kalibracio/python_code/fisheye_15mm_grid22mm.zip) és a [8 mm-es fókusztávolsággal készült képeket](kamera_kalibracio/python_code/fisheye_15mm_grid22mm.zip)\n", "Nyissuk ki ezeket a forrásfájl mellé! \n", "2. Futtassuk le a kalibrációs programot! \n", "> ```python fisheye_calibration.py```\n", "3. Nézzük meg a kamera paramétereket! \n", "\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Feladatok\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "1. Számold ki a lencsetorzítás korrekcióját!" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [], "source": [ "# írd ide a python kódot a számításhoz" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "2. Számold ki az átlagos visszavetítési hibát! " ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [], "source": [ "# írd ide a python kódot a számításhoz" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.6.5" } }, "nbformat": 4, "nbformat_minor": 2 }