主要内容

用校准的相机测量平面物体

这个例子展示了如何测量硬币直径在世界单位使用一个校准相机。

概述

这个例子展示了如何校准相机,然后用它来测量平面物体的大小,比如硬币。该方法的一个应用实例是测量传送带上的零件以进行质量控制。

校准相机

摄像机标定是对镜头和图像传感器的参数进行估计的过程。这些参数是测量相机捕捉到的物体所需要的。这个例子展示了如何以编程方式校准相机。或者,您可以校准相机使用照相机校准仪应用程序。

为了校准相机,我们首先需要从不同角度拍摄校准图案的多张图像。典型的校准图案是不对称棋盘,其中一面包含偶数个正方形,包括黑色和白色,另一面包含奇数个正方形。

图案必须贴在一个平坦的表面上,并且它与相机的距离应该与你要测量的物体大致相同。正方形的大小必须用世界单位来测量,例如毫米,要尽可能精确。在本例中,我们使用9张模式图像,但在实践中,建议使用10到20张图像进行精确校准。

准备校准图像

创建校准图像文件名的单元格数组。

numImages = 9;= cell(1, numImages);对于i = 1:numImages files{i} = fullfile(matlabroot,“工具箱”,“愿景”,“视觉数据”,...“校准”,“单反”sprintf (“图像% d.jpg”,i));结束%显示其中一个校准图像放大率=25;I=imread(文件{1});图;imshow(I,“初始放大”,放大);标题(“其中一个校准图像”);

估计摄像机参数

%检测图像中的棋盘格角点。[imagePoints, boardSize] = detectCheckerboardPoints(files); / /检查文件中生成棋盘角的世界坐标%模式中心坐标系,左上角为(0,0)。squareSize = 29;%在毫米worldPoints=generateCheckerboardPoints(boardSize,squareSize);%校准照相机。imageSize=[大小(I,1),大小(I,2)];cameraParams=估计的CameraParameters(imagePoints,worldPoints,...“图象尺寸”、图象尺寸);%评估校准精度。图;showReprojectionErrors(cameraParams);标题(“重投射错误”);

条形图表明了校准的准确性。每个柱状图显示了对应校准图像的平均重投影误差。重投影误差是指图像中检测到的角点与投影到图像中的理想世界点之间的距离。

读取要测量的对象的图像

加载包含要测量的对象的图像。这个图像包含了校准模式,并且这个模式与你要测量的物体在同一个平面上。在这个例子中,图案和硬币都在同一个桌面上。

或者,您可以使用两个单独的图像:一个包含图案,另一个包含要测量的对象。同样,对象和图案必须位于同一平面上。此外,必须从完全相同的视点捕获图像,这意味着必须将相机固定到位。

imOrig=imread(完整文件(matlabroot,“工具箱”,“愿景”,“视觉数据”,...“校准”,“单反”,“image9.jpg”));图;imshow (imOrig“初始放大”,放大);标题(输入图像的);

使图像不失真

使用cameraParameters对象消除图像中的镜头失真。这是精确测量所必需的。

由于镜头引入了小失真,使用“全”输出视图来说明%图像未被还原。如果我们使用默认的“相同”选项,那将会很困难%以注意与原始图像相比的任何差异。注意小的黑色边框。[im,newOrigin]=未失真图像(imOrig,cameraParams,“OutputView”,“全部”);图;imshow (im,“初始放大”,放大);标题(“无畸变的图像”);

请注意,此图像显示的镜头失真非常小。如果使用广角镜头或低端网络摄像头,则不失真步骤更为重要。

段硬币

在这种情况下,硬币在白色背景上是彩色的。使用图像HSV表示的饱和度分量将它们分割出来。

%将图像转换为HSV颜色空间。imHSV=rgb2hsv(im);%获取饱和通道。饱和度= imHSV(:,:, 2);图像阈值t = graythresh(饱和);imCoin =(饱和度> t);图;imshow (imCoin“初始放大”,放大);标题(“分段硬币”);

侦测硬币

我们可以假设分割图像中两个最大的连接组件对应于硬币。

%查找连接的组件。blobAnalysis =愿景。BlobAnalysis (“AreaOutputPort”,真的,...“CentroidOutputPort”错误的...“BoundingBoxOutputPort”,真的,...“MinimumBlobArea”, 200,“排除边界点”,对);[区域,方框]=步骤(BlobanAnalysis,imCoin);%按区域降序排列连接的零部件[~, idx] = sort(区域,“下”);%得到两个最大的组件。box = double(box (idx(1:2),:))); / /指定一个值减少显示的图像的大小。比例=放大倍数/ 100;imDetectedCoins = imresize(im, scale);%为硬币插入标签。imDetectedCoins = insertObjectAnnotation (imDetectedCoins,“矩形”,...缩放*框,“一分钱”);图;imshow (imDetectedCoins);标题(“检测到的硬币”);

计算外在

要将图像坐标中的点映射到世界坐标中的点,我们需要计算相机相对于校准模式的旋转和平移外在的函数假设没有透镜畸变。在这种情况下,imagePoints已经检测到的图像已经被纠正使用不失真图像.

%检测棋盘。[imagePoints, boardSize] = detectCheckerboardPoints(im);%调整图像点,使其在坐标系中表达%用于原始图像,在它未被扭曲之前。这种调整%使它与为原始图像计算的camerarameters对象兼容。imagePoints = imagePoints + newOrigin;%向每行imagePoints添加新原点%计算相机的旋转和平移。[R,t]=外部(成像点、世界点、摄像机参数);

测量第一枚硬币

要测量第一枚硬币,我们将边界框的左上角和右上角转换为世界坐标。然后我们计算它们之间的欧几里德距离(单位为毫米)。请注意,美国硬币的实际直径为19.05毫米。

%调整边界框的左上角以进行坐标系偏移%由输出视图为“full”的未失真图像引起。这不会是如果输出“相同”,则需要%。调整使各点兼容%与相机参数的原始图像。[newworigin, 0, 0]; / /点击[newworigin, 0, 0]宽度和高度添加了% 0填充%获取左上角和右上角。框1=双(框(1,:);imagePoints1=[box1(1:2);...Box1 (1) + Box1 (3), Box1 (2)];得到各个角落的世界坐标worldPoints1=pointsToWorld(cameraParams、R、t、imagePoints1);用毫米计算硬币的直径。d = worldPoints1(2,:) - worldPoints1(1,:);直径in毫米= hypot(d(1), d(2));流('一便士的测量直径=%0.2f mm\n', diameterInMillimeters);
测量直径一便士= 19.00毫米

测量第二枚硬币

测量第二枚硬币的方法与测量第一枚硬币的方法相同。

%获取左上角和右上角。box2=double(框(2,:);imagePoints2=[box2(1:2);...Box2 (1) + Box2 (3), Box2 (2)];%应用从图像到世界的逆变换worldPoints2=pointsToWorld(cameraParams、R、t、imagePoints2);用毫米计算硬币的直径。d = worldPoints2(2,:) - worldPoints2(1,:);直径in毫米= hypot(d(1), d(2));流('另一便士的测量直径=%0.2f mm\n', diameterInMillimeters);
另一便士的测量直径=18.85 mm

测量到第一枚硬币的距离

除了测量硬币的大小,我们还可以测量它离相机有多远。

%计算图像中第一枚硬币的中心。center1_image=box1(1:2)+box1(3:4)/2;%转换为世界坐标。center1_world=pointsToWorld(摄像机参数、R、t、center1_图像);%记得添加0 z坐标。[Center1_world 0];%计算到摄像机的距离。[~, cameraLocation] = extrinsicsToCameraPose(R, t);distanceToCamera = norm(center1_world - cameraLocation);流('从相机到第一便士的距离= %0.2f mm\n',...距离照相机);
从相机到第一便士的距离= 719.52毫米

总结

此示例演示了如何使用已校准的相机测量平面对象。请注意,测量精度在0.2 mm以内。

参考文献

[1] z。一种灵活的摄像机标定新技术。计算机工程与应用,2017,36(11):1330-1334,2000。