主要内容

用校准摄像机测量平面物体

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

概述

本示例演示如何校准相机,然后使用它测量平面对象(如硬币)的大小。此方法的一个示例应用是测量传送带上的零件以进行质量控制。

校准相机

相机校准是估计镜头和图像传感器参数的过程。这些参数是测量相机捕获的对象所必需的。此示例演示如何以编程方式校准相机。或者,您可以使用cameraCalibrator应用程序。

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

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

准备校准图片

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

numImages=9;files=cell(1,numImages);i=1:numimage文件{i}=fullfile(matlabroot,“工具箱”“愿景”“visiondata”...“校准”“单反”,斯普林特('图像%d.jpg',我));终止%显示其中一个校准图像放大倍数= 25;I = imread(文件{1});图;imshow(我“InitialMagnification”、放大);标题(“其中一幅校正图像”);

图中包含一个轴对象。标题为“One of The Calibration Images”的轴对象包含一个类型为image的对象。

估计摄像机参数

%检测图像中的棋盘角。[imagePoints,boardSize]=检测电路板点(文件);%在中生成棋盘格角点的世界坐标%模式中心坐标系,左上角为(0,0)。平方大小=29;%毫米worldPoints = generateCheckerboardPoints(boardSize, squareSize);校准相机。imageSize = [size(I, 1), size(I, 2)];cameraParams = estimatecamerparameters (imagePoints, worldPoints,...“图象尺寸”、图象尺寸);评估校准精度。图;showReprojectionErrors (cameraParams);标题(“Reprojection错误”);

图中包含一个轴对象。标题为“重投影错误”的轴对象包含3个类型为bar, line的对象。这个对象表示总体平均误差:0.90像素。

条形图表示校准的精度。每个条形图显示相应校准图像的平均重投影误差。重投影误差是图像中检测到的角点与投影到图像中的相应理想世界点之间的距离。

读取待测物体的图像

加载包含要测量的对象的图像。此图像包括校准图案,并且该图案与要测量的对象位于同一平面上。在本例中,图案和硬币都位于同一桌面上。

或者,您可以使用两个独立的图像:一个包含模式,另一个包含要测量的对象。同样,物体和图案必须在同一个平面上。此外,图像必须从完全相同的视角捕捉,这意味着相机必须固定在合适的位置。

imOrig = imread (fullfile (matlabroot“工具箱”“愿景”“visiondata”...“校准”“单反”‘image9.jpg’));图;imshow(imOrig,“InitialMagnification”、放大);标题(输入图像的);

图中包含一个轴对象。标题为“输入图像”的轴对象包含类型为“图像”的对象。

Undistort图像

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

%由于镜头引入的失真很小,请使用“完整”输出视图来说明这一点%图像未被破坏。如果我们使用默认的“相同”选项,这将很困难%注意与原始图像相比的任何差异。请注意黑色的小边框。[im, newOrigin] = undistortion timage (imOrig, cameraParams,“OutputView”“全部”);数字;imshow(im,“InitialMagnification”、放大);标题(“未失真图像”);

图中包含一个轴对象。标题为“未变形图像”的轴对象包含类型为“图像”的对象。

注意,这幅图像显示出非常小的镜头失真。如果你使用的是广角镜头或低端摄像头,那么不失真这一步就重要得多。

段硬币

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

%将图像转换为HSV颜色空间。imHSV = rgb2hsv (im);%获取饱和通道。饱和度=imHSV(:,:,2);%对图像设置阈值t=灰度阈值(饱和度);imCoin=(饱和度>t);数字;imshow(imCoin,“InitialMagnification”、放大);标题(“分割硬币”);

图中包含axes对象。标题为分段硬币的axes对象包含image类型的对象。

侦测硬币

我们可以假设分割后的图像中最大的两个连通分量对应于硬币。

%查找连接的组件。blobananalysis=vision.blobananalysis(“区域输出端口”,真的,...“中心输出端口”错误的...“BoundingBoxOutputPort”,真的,...“MinimumBlobArea”, 200,“ExcludeBorderBlobs”,真正的);[area, boxes] = step(blobAnalysis, imCoin);%按区域降序排列连接组件[~,idx]=排序(区域,“下降”);%得到两个最大的分量。box = double(box (idx(1:2),:))); / /指定一个值减少显示的图像的大小。比例=放大倍数/ 100;imDetectedCoins = imresize(im, scale);%插入硬币的标签。imDetectedCoins=插入对象注释(imDetectedCoins,“矩形”...规模*盒子,“便士”);数字;imshow(imDetectedCoins);标题(“发现硬币”);

图中包含axes对象。标题为的axes对象包含image类型的对象。

计算外部因素

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

%检测棋盘。[imagePoints, boardSize] = detectCheckerboardPoints(im);%调整imagePoints,使其在坐标系统中表示%在原始图像未失真之前,在原始图像中使用。这种调整%使其与为原始图像计算的cameraParameters对象兼容。imagePoints = imagePoints + newOrigin;%添加newOrigin到imagePoints的每一行%计算相机的旋转和平移。[R, t] = extrinsics(imagePoints, worldPoints, cameraParams);

测量第一枚硬币

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

调整边界框的左上角以实现坐标系统的移位%由undistortion timage造成,输出视图为'full'。这就不是如果输出“相同”,则需要%。调整使各点兼容%使用原始图像的摄影机参数。[newworigin, 0, 0]; / /点击[newworigin, 0, 0]%为宽度和高度添加零填充%得到左上角和右上角。Box1 = double(boxes(1,:));imagePoints1 = [box1 (1:2);...盒子1(1)+盒子1(3),盒子1(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 mm

量第二枚硬币

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

%得到左上角和右上角。Box2 = double(boxes(2,:));imagePoints2 = [box2 (1:2);...Box2 (1) + Box2 (3), Box2 (2)];%应用从图像到世界的逆变换worldPoints2 = pointsToWorld(cameraParams, R, t, imagePoints2);%以毫米为单位计算硬币的直径。d=世界点2(2,:)-世界点2(1,:);直径毫米=海波(d(1),d(2));fprintf('测量的另一便士直径= %0.2f mm\n', diameterInMillimeters);
另一枚硬币的直径为18.85毫米

测量到第一枚硬币的距离

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

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

总结

这个例子展示了如何使用一个校准的相机来测量平面物体。注意,测量精度在0.2 mm以内。

参考文献

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