一、OpenCV 包含的具体模块Core该模块包含 OpenCV 库的基础结构以及基本操作。Improc图像处理模块包含基本的图像转换包括滤波以及类似的卷积操作。Highgui在 OpenCV 3.0中分割为 imcodecs、videoio 以及 highgui 三部分。这个模块包含可以用来显示图像或者简单的输入的用户交互函数。这可以看作是一个非常轻量级的 Windows UI 工具包。Video该模块包含读取和写视频流的函数。Calib3d这个模块包括校准单个、双目以及多个相机的算法实现。Feature2d这个模块包含用于检测、描述以及匹配特征点的算法。Objdectect这个模块包含检测特定目标比如人脸或者行人的算法。也可以训练检测器并用来检测其他物体。Ml机器学习模块本身是一个非常完备的模块包含大量的机器学习算法实现并且这些算法都能和 OpenCV 的数据类型自然交互。FlannFlann 的意思是“快速最邻近库”。这个库包含一些你也许不会直接使用的方法但是其他模块中的函数会调用它在数据集中进行最邻近搜索。GPU在 OpenCV 中被分割为多个 cuda* 模块。GPU 模块主要是函数在 CUDA GPU 上的优化实现此外还有一些仅用于 GPU 的功 能。其中一些函数能够返回很好的结果但是需要足够好的计算资源如果硬件没有GPU则不会有什么提升。Photo这是一个相当新的模块包含计算摄影学的一些函数工具。Stitching本模块是一个精巧的图像拼接流程实现。这是库中的新功能但是就像 Photo 模块一样这个领域未来预计有很大的增长。Nonfree在 OpenCV 3.0 中被移到 opencv_contrib/xfeatures2d。OpenCV 包含一些受到专利保护的或者受到使用限制的比如 SIFT 算法算法。这些算法被隔离到它们自己的模块中以表明你需要做一些特殊的工作才可以在商业产品中使用它们。Contrib在 OpenCV 3.0 中融合进了 opencv_contrib。这个模块包含一些新的、还没有被集成进 OpenCV 库的东西。Legacy在 OpenCV 3.0 中被取消。这个模块包含一些老的尚未被完全取消的东西。ocl在OpenCV 3.0 中被取消取而代之的是 T-API。这是一个较新的模块可以认为它和 GPU 模块相似它实现了开放并行编程的 Khronos OpenCL 标准。虽然现在模块的特性比 GPU 模块少很多但 ocl 模块的目标是提供可以运行在任何 GPU 或者是其他可以搭载 Khronos 的并行设备。这与 GPU 模 块形成了鲜明的对比后者使用 Nividia CUDA 工具包进行开发因此只能在 Nividia GPU 设备上工作。二、criteria (cv2.TERM_CRITERIA_EPS cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)criteria是OpenCV中用来指定迭代算法的终止条件的参数。OpenCV中有两个终止条件用来判断迭代算法是否已经收敛即cv2.term_criteria_eps和cv2.term_criteria_max_iter。cv2.term_criteria_eps表示精度epsilon也就是说当每次迭代计算最优解过程中的误差小于该值时算法就会停止。具体来说这个参数代表的是两次结果之间的距离达到了一个很小的阈值算法就会认为结果已经收敛。cv2.term_criteria_max_iter表示最大迭代次数如果算法在迭代过程中达到了最大迭代次数也会停止。最大迭代次数的设定可以避免算法的无限循环提高算法效率。例如如果设定criteria (cv2.term_criteria_eps, cv2.term_criteria_max_iter,30,0.001)那么算法会在误差小于0.001或进行了30次迭代之后停止。这个选择可以确保算法在迭代过程中不会无限制地进行同时也可以保证结果足够精确三、cv2.calibrateCamera() 函数用于相机标定,它基于 OpenCV 提供的标定板图像来计算相机的内参和畸变系数。它的使用方法如下:1. 收集标定板图像:你需要多张(至少20张)包含标定板(chessboard)的图像。可以使用OpenCV提供的findChessboardCorners()函数检测标定板角点。2. 标定板规格:需要给出标定板的规格,如角点数量(corners)和一个方块的大小(squareSize)。3. 标定图像点:使用findChessboardCorners()检测所有图像的角点4. 相机矩阵和局部畸变向量:使用calibrateCamera()函数计算:- cameraMatrix - 相机矩阵,包含 focal lengths (fx, fy)和 principal point (cx, cy)- distCoeffs - 相机的局部畸变系数,一个4维或5维向量5.其他参数:- flags - 设置计算内参和/或畸变系数。- criteria - 设置迭代停止准则。四、cv2.getOptimalNewCameraMatrix()该函数可以用来校正相机的畸变。通过校正相机的非线性畸变来获得更准确的投影和测量结果它的用法是:python k ... # 相机内参矩阵 dist ... # 畸变系数 img_size ... # 图片大小(width, height) alpha 0.8 # 设置畸变校正程度 0~1, 0为不校正,1为最大校正通常取值为 0.05 到 0.2 newcameramtx, roi cv2.getOptimalNewCameraMatrix(k, dist, img_size, alpha)参数:- newcameramtx :新的相机矩阵,包含畸变校正后的相关参数- roi: 是一个矩形区域表示校正后图像的有效区域。如果图像四周裁剪,则返回ROI它的作用是:基于给定的相机内参和畸变参数,计算出一个畸变校正程度为alpha的新相机矩阵。通过使用新相机矩阵,我们就可以对图像进行畸变校正。使用方式:1. 调用函数计算出新的相机矩阵newcameramtx和ROI2. 使用cv2.remap()函数,并传入新的相机矩阵,进行图像畸变校正五、cv2.remap()函数cv2.initUndistortRectifyMap暂时没用到函数用于在图像上执行像素映射操作可以通过将每个像素位置映射到新的位置来对图像进行变换cv2.initUndistortRectifyMap函数用于计算相机校正所需的映射表。也是用来去畸变的。这个函数通常与cv2.undistort函数一起使用用于校正图像的畸变。map1, map2 cv2.initUndistortRectifyMap(camera_matrix, dist_coeffs, None, camera_matrix)undistorted_image cv2.remap(image, map1, map2, cv2.INTER_LINEAR)六、cv2.undistort函数cv2.undistort函数用于对图像进行去畸变操作。该函数会根据提供的相机内参和畸变参数对图像进行畸变校正返回校正后的图像。以下是cv2.undistort函数的使用方法cv2.undistort(src, cameraMatrix, distCoeffs, dstNone newCameramMatrix)参数说明src输入的原始图像可以是单通道灰度图像或彩色图像。cameraMatrix相机内参矩阵一个 3x3 的矩阵包含相机的焦距和中心点坐标等信息。distCoeffs相机畸变系数一个包含 k1、k2、p1、p2、k3 等参数的一维向量。这些参数可以通过相机标定等方法获得。newCameramMatrix如果提供了该参数表示需要在进行去畸变操作的同时对图像进行校正使用该参数指定新的相机内参矩阵。dst如果提供了该参数表示将校正后的图像保存到指定的输出图像中不提供则将结果直接返回。七、cv2.projectPoints函数cv2.projectPoints函数用于将一个或多个人工标识点使用np.float32类型的二维数组表示从 3D 空间投影到图像平面上。它需要以下参数points: 一个包含N个(x, y, z)坐标的人工标识点的二维数组其中N是标识点的数量。cameraMatrix相机内参矩阵一个 3x3 的矩阵包含相机的焦距和中心点坐标等信息。distCoeffs相机畸变系数一个包含 k1、k2、p1、p2、k3 等参数的一维向量。这些参数可以通过相机标定等方法获得。R可选旋转矩阵一个 3x3 的旋转矩阵用于描述从 3D 空间到相机坐标系的旋转关系。t可选平移向量一个 3D 的平移向量用于描述从 3D 空间到相机坐标系的平移关系。该函数将返回一个包含投影后的人工标识点坐标的二维数组每个元素是一个(u, v)坐标imgpoints2, depth cv2.projectPoints(obj_points[i], rvecs[i], tvecs[i], mtx, dist)cv2.projectPoints函数返回一个元组tuple其中包含两个数组投影后的二维点坐标数组这个数组包含了投影后的二维点坐标每个点由其 x 和 y 坐标组成。这个数组的形状与输入的点云数组相同可以用于在图像中进行显示、计算等操作。对应点的深度数组可选这个数组包含了每个投影后二维点在相机坐标系中的深度即 z 坐标。如果不提供相机内参矩阵cameraMatrix和畸变系数distCoeffs则该数组将为 None。深度信息可以用于计算物体的大小、距离等实际应用八、cv2.norm(img_points[i], imgpoints2, cv2.NORM_L2)是一个 OpenCV 函数用于计算两个点云之间的欧氏距离。函数的返回值是两个点云中对应点的欧氏距离。具体来说该函数会计算第一个点云中的每个点与第二个点云中的每个点之间的距离然后将这些距离的平方和开根号得到最终的欧氏距离棋盘格opencv标定我们拍摄的物体都处于三维世界坐标系中而相机拍摄时镜头看到的是三维相机坐标系成像时三维相机坐标系向二维图像坐标系转换。不同的镜头成像时的转换矩阵不同同时可能引入失真标定的作用是近似地估算出转换矩阵和失真系数。为了估算需要知道若干点的三维世界坐标系中的坐标和二维图像坐标系中的坐标也就是拍摄棋盘的意义。际中镜头并非理想的透视成像带有不同程度的畸变。理论上镜头的畸变包括径向畸变和切向畸变切向畸变影响较小通常只考虑径向畸变。• 为什么需要相机标定1一个是由于每个镜头的在生产和组装过程中的畸变程度各不相同通过相机标定可以校正这种镜头畸变生成矫正后的图像——矫正透镜畸变2另一个是根据标定后的到的相机参数建立相机成像几何模型由获得的图像重构出三维场景。具体来说当我们用摄像机拍照时从照片里得到一些空间信息比如距离尺寸等是要利用二维图像得到三维信息。我们拍照的时候把空间物体信息通过摄像机变成了二维图像这个过程本来是不可逆的。但如果我们可以找到一个摄像机的数学模型就可以 从二维图像模型逆推得到原来三维信息。标定就是在找这个模型• 相机标定可以做什么1相机在出厂之前都需要进行相机标定用软件的方法校正生成的图像避免拍摄出的图像产生桶形和枕形畸变2根据相机成像的几何模型将世界坐标系中的3D物体映射到2D成像平面上3求解多个相机对之间的映射关系。• 相机标定后可以得到什么1相机的内参矩阵Adx,dy,r,u,v,f外参矩阵[R|T]、畸变系数[k1,k2,k3,,p1,p2,]。2内参矩阵各元素意义一个像素的物理尺寸dx和dy焦距f图像物理坐标的扭曲因子r图像原点相对于光心成像点的的纵横偏移量u和v像素为单位。3外参矩阵 世界坐标系转换到相机坐标系的旋转R和平移T矩阵。4畸变系数 包括相机的径向畸变系数k1,k2,k3,~ 和相机的切向畸变系数p1,p2,~。2.张正友标定法”张正友标定法” 是指张正友教授1998年提出的单平面棋盘格的摄像机标定方法。文中提出的方法介于传统标定法和自标定法之间但克服了传统标定法需要的高精度标定物的缺点。相对于自标定而言提高了精度便于操作。因此张正友标定法被广泛应用于计算机视觉方面。在张氏标定法中用于标定的棋盘格是三维场景中的一个平面Π其在成像平面的像是另一个平面π知道了两个平面的对应点的坐标就可以求解得到两个平面的单应矩阵H。其中标定的棋盘格是特制的其角点的坐标是已知的图像中的角点可以通过角点提取算法得到如Harris角点这样就可以得到棋盘平面Π和图像平面π的单应矩阵H。一、准备为了标定相机我们需要输入一系列三维点和它们对应的二维图像点。在黑白相间的棋盘格上二维图像点很容易通过角点检测找到。而对于真实世界中的三维点呢由于我们采集中是将相机放在一个地方而将棋盘格定标板进行移动变换不同的位置然后对其进行拍摄。所以我们需要知道(X,Y,Z)的值。但是简单来说我们定义棋盘格所在平面为XY平面即Z0。对于定标板来说我们可以知道棋盘格的方块尺寸例如30mm这样我们就可以把棋盘格上的角点坐标定义为(0,0,0)(30,0,0)(60,0,0)···这个结果的单位是mm二、检测棋盘格角点为了找到棋盘格模板我们使用openCV中的函数cv2.findChessboardCorners()。我们也需要告诉程序我们使用的模板是什么规格的例如8*8的棋盘格或者5*5棋盘格等建议使用x方向和y方向个数不相等的棋盘格模板。下面实验中我们使用的是10*7的棋盘格每个方格边长是20mm即含有9*6的内部角点。这个函数如果检测到模板会返回对应的角点并返回true。当然不一定所有的图像都能找到需要的模板所以我们可以使用多幅图像进行定标。找到角点后我们可以使用cv2.cornerSubPix()可以得到更为准确的角点像素坐标。我们也可以使用cv2.drawChessboardCorners()将角点绘制到图像上显示三、标定通过上面的步骤我们得到了用于标定的三维点和与其对应的图像上的二维点对。我们使用cv2.calibrateCamera()进行标定这个函数会返回标定结果、相机的内参数矩阵、畸变系数、旋转矩阵和平移向量。四、去畸变第三步我们已经得到了相机内参和畸变系数在将图像去畸变之前我们还可以使用cv.getOptimalNewCameraMatrix()优化内参数和畸变系数通过设定自由自由比例因子alpha。当alpha设为0的时候将会返回一个剪裁过的将去畸变后不想要的像素去掉的内参数和畸变系数当alpha设为1的时候将会返回一个包含额外黑色像素点的内参数和畸变系数并返回一个ROI用于将其剪裁掉。然后我们就可以使用新得到的内参数矩阵和畸变系数对图像进行去畸变了。有两种方法进行去畸变1# undistort dst cv2.undistort(img, mtx, dist, None, newcameramtx) # crop the image x,y,w,h roi dst dst[y:yh, x:xw] cv2.imwrite(calibresult.png,dst)2使用remap# undistort mapx,mapy cv2.initUndistortRectifyMap(mtx,dist,None,newcameramtx,(w,h),5) dst cv2.remap(img,mapx,mapy,cv2.INTER_LINEAR) # crop the image x,y,w,h roi dst dst[y:yh, x:xw] cv2.imwrite(calibresult.png,dst)五、反投影误差通过反投影误差我们可以来评估结果的好坏。越接近0说明结果越理想。通过之前计算的内参数矩阵、畸变系数、旋转矩阵和平移向量使用cv2.projectPoints()计算三维点到二维图像的投影然后计算反投影得到的点与图像上检测到的点的误差最后计算一个对于所有标定图像的平均误差这个值就是反投影误差下面是完整程序import cv2 import numpy as np import glob def calibrate_camera(): w_n 8 h_n 6 棋盘上每一排和每一列的内角数。w_n 棋盘板一行上黑白块的数量 - 1h_n 棋盘板一列上黑白块的数量 - 1例如10 x6的棋盘板则(w, h) (9, 5) # 设置迭代终止条件max_iter为30epsilon为0.001 criteria (cv2.TERM_CRITERIA_EPS cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001) # 世界坐标系中的棋盘格点,例如(0,0,0), (1,0,0), (2,0,0) ....,(8,5,0)去掉Z坐标记为二维矩阵认为在棋盘格这个平面上Z0 objp np.zeros((w_n * h_n, 3), np.float32) # 48,3,构造零矩阵88行3列用于存放角点的世界坐标 # 这里np.mgrid[](2,8,6)的数组第一个每列的数值都是从0到7第二个每行的数值从0到7 objp[:, :2] np.mgrid[0:8, 0:6].T.reshape(-1, 2) # 三维网格划分,(2*8*6)再转置6*8*2再变为48,2, # 将世界坐标系建在标定板上所有点的Z坐标全部为0所以只需要赋值x和y # 储存棋盘格角点的世界坐标和图像坐标对 obj_points [] # 在世界坐标系中的三维点 img_points [] # 在图像平面的二维点 images_path glob.glob(./images/original/*.png) # 返回所有文件路径 for i, img_path in enumerate(images_path): img cv2.imread(img_path) gray cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 转换为8位灰度图 粗略找到棋盘格角点 这里找到的是这张图片中角点的亚像素点位置共8×6 48个点gray必须是8位灰度或者彩色图w,h为角点规模 该函数试图确定输入图像是否是棋盘图案的视图并定位棋盘内部的角。如果找到了所有的角并且它们按一定的顺序逐行每行从左到右放置 则函数返回一个非零值。否则如果函数未能找到所有的角或对其重新排序则返回0。 例如一个普通的棋盘有8 x 8个方格和7 x 7个内角也就是说黑色方格相互接触的点。检测到的坐标是近似的 为了更准确地确定它们的位置函数调用#cornerSubPix。如果返回的坐标不够准确您也可以使用具有不同参数的函数#cornerSubPix ret, rough_corners cv2.findChessboardCorners(gray, (w_n, h_n), None) # rough_corners(48,1,2),w,h if ret: # 精确找到角点坐标,该函数迭代以找到角点或径向鞍点的亚像素精确位置 param image输入单通道、8位或浮点图像。 .param corners输入角的初始坐标和为输出提供的精确坐标 .param winSize搜索窗口边长的一半。例如如果winSizeSize5,5 .param zeroZone位于搜索区域中间的死区大小的一半在该死区上不进行以下公式中的求和。它有时被用来避免自相关矩阵的可能奇异性。-1-1的值表示不存在这样的大小。 .param criteria终止角点细化迭代过程的标准。也就是说在criteria.maxCount迭代之后或者在某次迭代中当角点位置移动小于criteria.epsilon时角点位置细化过程停止。 accurate_corners cv2.cornerSubPix(gray, rough_corners, (11, 11), (-1, -1), criteria) obj_points.append(objp) img_points.append(accurate_corners) # 将角点在图像上显示,渲染检测到的棋盘角 .param image目标图像。它必须是8位彩色图像。 .param patternSize每个棋盘行和列的内角数.patternSizecv:大小points_per_rowpoints_per_column。 .param corners检测到的角的数组#findChessbordCorners的输出。 .param patternWasFound指示是否找到完整的板的参数。此处应传递#findChessbordCorners的.rereturn值。 该函数将检测到的各个棋盘角绘制为红色圆圈如果未找到棋盘或绘制为彩色角如果找到棋盘。 cv2.drawChessboardCorners(img, (8, 6), accurate_corners, ret) cv2.imshow(findCorners, img) cv2.waitKey(500) # 以毫秒为单位 cv2.imwrite(f./images/findCorners/{i}.jpg, img) cv2.destroyAllWindows() #标定 ret表示的是重投影误差mtx是相机的内参矩阵dist表述的相机畸变参数 rvecs表示标定棋盘格世界坐标系到相机坐标系的旋转参数rotation vectors需要进行罗德里格斯转换 tvecs表示translation vectors主要是平移参数,mtx为camera_matrix ret, mtx, dist, rvecs, tvecs cv2.calibrateCamera(obj_points, img_points, gray.shape[::-1], None, None) np.savetxt(./csv/mtx.csv, mtx) np.savetxt(./csv/dist.csv, dist) # 去畸变 for i, image_path in enumerate(images_path): img2 cv2.imread(image_path) h, w img2.shape[:2] # 取二维大小 # 该函数可以用来校正相机的畸变。通过校正相机的非线性畸变来获得更准确的投影和测量结果 new_camera_mtx, roi cv2.getOptimalNewCameraMatrix(mtx, dist, (w, h), 0, (w, h)) # 自由比例参数 # 用于对图像进行去畸变操作。该函数会根据提供的相机内参和畸变参数对图像进行畸变校正返回校正后的图像。 dst cv2.undistort(img2, mtx, dist, None, new_camera_mtx) x, y, w, h roi dst dst[y:yh, x:xw] cv2.imshow(Distortion_removal, dst) cv2.waitKey(500) cv2.imwrite(f./images/distortion_removal_image/{i}.jpg, dst) cv2.destroyAllWindows() # 反投影误差 total_error 0 for i in range(len(obj_points)): imgpoints2, depth cv2.projectPoints(obj_points[i], rvecs[i], tvecs[i], mtx, dist) error cv2.norm(img_points[i], imgpoints2, cv2.NORM_L2) / len(imgpoints2) # MSE total_error error print(total error: , total_error / len(obj_points)) if __name__ __main__: calibrate_camera()其中objp是棋盘格的三维坐标如下图一、在机器视觉领域摄像头的标定指通过技术手段拿到相机的内参、外参及畸变参数径向畸变比如鱼眼相机的效果特征是越往镜头边缘线条弯曲的就越明显。消除畸变就是把这些曲线尽量还原成本来的样子径向畸变校正公式切向畸变一般来说是因为相机镜头制造工艺精度不够透镜和感光器原件没有平行从而造成了图像的变形。矫正公式两个畸变的参数用一个向量表示k1,k2,p1,p2,k3一般要得到一个比较好的标定效果的话大概需要标定 20 张图片左右对标定图片的要求在标定的整个过程中不能调节相机的光圈、焦距要保证在标定中摄像头进光量与焦距的一致。建议在摄像头视野内五个不同位置上左上、右上、左下、右下、正中心分别拍摄图片。拍摄的图片最好为摄像头视野的1/4左右。不要只拍摄标定板与镜头面平行的图片也要拍摄一些有倾斜角度的图片。拍摄过程中可以对标定板适当的进行补光调节标定板到镜头的距离以便于排出清晰的图片。标定时用的标定板最好选择x方向与y方向棋盘格不同的便于标定程序识别标定板方向。