此示例显示如何使用单个校准相机测量世界单位中的硬币直径。
此示例显示如何校准相机,然后使用它来测量平面对象的大小,例如硬币。这种方法的示例应用是测量输送带上的用于质量控制的部件。
相机校准是估计镜头和图像传感器的参数的过程。需要这些参数来测量相机捕获的对象。此示例显示如何以编程方式校准相机。或者,您可以使用使用的相机校准相机cameraCalibrator
应用程序。
为了校准相机,我们首先需要从不同的角度拍摄一个校准模式的多个图像。典型的校准模式是一个不对称的棋盘,其中一边包含偶数个正方形,包括黑色和白色,另一边包含奇数个正方形。
图案必须固定到平坦的表面上,并且它应该与相机的距离大致相同,因为您要测量的对象。必须在世界单位中测量正方形的大小,例如毫米,尽可能精确地。在此示例中,我们使用图案的9个图像,但实际上建议使用10到20个图像以精确校准。
创建一个单元格数组的文件名称的校准图像。
numimages = 9;files = cell(1,NumImages);为了i = 1:Numimages文件{i} = fullfile(matlabroot,'工具箱',“愿景”,“visiondata”,...'校准','SLR',Sprintf('图像%d.jpg',我));结尾%显示一个校准图像放大率= 25;i = imread(文件{1});图;imshow(我,'InitialMagnification'、放大);标题(“其中一张校准图像”);
%检测图像中的棋盘角落。[ImagePoints,BoardSize] =侦探校验erboardPoints(文件);%生成棋盘角落的世界坐标%以图案为中心的坐标系,左上角(0,0)。Squaresize = 29;%以毫米worldPoints = generateCheckerboardPoints(boardSize, squareSize);校准相机。imageSize = [size(I, 1), size(I, 2)];cameraParams = estimatecamerparameters (imagePoints, worldPoints,...'图片大小', 图片大小);%评估校准精度。图;showReprojectionErrors (cameraParams);标题(“Reprojection错误”);
条形图表示校准的准确性。每个条形显示相应校准图像的平均刻录误差。重注错误是图像中检测到的角点之间的距离,并投影到图像中的相应理想世界点。
加载包含要测量的对象的图像。此图像包括校准模式,模式与您要测量的对象在同一平面中。在该示例中,图案和硬币都在同一台上。
或者,您可以使用两个独立的图像:一个包含模式,另一个包含要测量的对象。同样,物体和图案必须在同一个平面上。此外,图像必须从完全相同的视角捕获,这意味着相机必须固定在适当的位置。
imOrig = imread (fullfile (matlabroot'工具箱',“愿景”,“visiondata”,...'校准','SLR','image9.jpg'));图;imshow(imorig,'InitialMagnification'、放大);标题('输入图像');
使用cameraParameters对象从图像中去除镜头失真。这对精确测量是必要的。
%镜头引入了很小的失真,使用“完整”输出视图来说明%图像未分解。如果我们使用默认的“相同”选项,那将是困难的与原始图像相比,%要注意任何差异。注意小黑边界。[im, newOrigin] = un畸变图像(imOrig, camerparams)'OutputView','满的');图;imshow(我,'InitialMagnification'、放大);标题('不朽的形象');
请注意,此图像显示很少的透镜畸变。如果你使用的是广角镜头或低端网络摄像头,保持镜头不失真这一步就重要得多。
在这种情况下,硬币是彩色的白色背景。利用图像HSV表示的饱和分量来分割它们。
%将图像转换为HSV颜色空间。imHSV = rgb2hsv (im);%获取饱和通道。饱和= imhsv(:,:,2);%阈值图像t =曲线(饱和度);imcoin =(饱和> t);图;imshow(imcoin,'InitialMagnification'、放大);标题('分段硬币');
我们可以假设分割图像中两个最大的连接组件对应于硬币。
%查找连接组件。Blobanalysis = Vision.Blobanalysis('AreaOutputport', 真的,...'centroidoutputport', 错误的,...'bandingboxoutputport', 真的,...'MiniplingBlobarea',200,“ExcludeBorderBlobs”,真正的);[areas, boxes] = step(blobAnalysis, imCoin);%按区域降序排列连接组件[〜,IDX] =排序(区域,“下降”);得到两个最大的组件。Boxes = double(框(idx(1:2),:));%缩小图像的大小以供显示。秤=放大/ 100;IMDetectedCoins = Imresize(IM,Scale);%插入硬币标签。IMDetectedCoins = InsertObjectAnnotation(IMDetectedCoins,'长方形',...规模*盒子,'一分钱');图;imshow(imdetectedcoins);标题(“发现硬币”);
为了将图像坐标中的点映射到世界坐标中的点,我们需要计算相机相对于校准模式的旋转和平移。请注意,外在
功能假设没有镜头失真。在这种情况下,在已经不变的图像中检测到映像点undistortImage
.
%检测棋盘。[ImagePoints,BoardSize] =侦探校验erboardPoints(IM);%调整imagePoints,以便它们在坐标系统中表示%在原始图像中使用,在未置换之前。这个调整%使其与为原始图像计算的CameraParameters对象兼容。imagePoints = imagePoints + neworigin;%添加newororigin到imagePoints的每一行%计算旋转和相机翻译。[R, t] = extrinsics(imagePoints, worldPoints, cameraParams);
为了测量第一枚硬币,我们将边界框的左上角和右上角转换为世界坐标。然后计算它们之间的欧几里德距离,单位是毫米。请注意,一美元硬币的实际直径是19.05毫米。
%调整边界框的左上角以进行坐标系统的移动%由未置换显图像引起的“完整”输出视图。这不是%需要输出'相同'。调整使得点兼容含有原始图像的Cameraparameters。盒子=盒子+ [neworigin,0,0];为Widht和Height添加%零填充%得到左上角和右上角。Box1 = double(boxes(1,:));imagePoints1 = [box1 (1:2);...BOX1(1)+ BOX1(3),BOX1(2)];%得到了角落的世界坐标worldPoints1 = pointsToWorld(camerparams, R, t, imagePoints1);%计算硬币的直径为毫米。d = worldPoints1(2,:) - WorldPoints1(1,:);直径百分比=半径(D(1),D(2));fprintf('一便士的测量直径= %0.2f毫米\n',直径尺);
测量直径为一分钱= 19.00毫米
以与第一个硬币相同的方式测量第二枚硬币。
%得到左上角和右上角。Box2 = double(boxes(2,:));imagePoints2 = [box2 (1:2);...BOX2(1)+ BOX2(3),BOX2(2)];%应用图像到世界的逆变换worldPoints2 = pointsToWorld(camerparams, R, t, imagePoints2);%计算硬币的直径为毫米。d = worldPoints2(2,:) - WorldPoints2(1,:);直径百分比=半径(D(1),D(2));fprintf('另一枚硬币的测量直径= %0.2f mm\n',直径尺);
另一枚硬币的测量直径= 18.85毫米
除了测量硬币的尺寸外,我们还可以测量它来自相机的距离。
%计算图像中第一个硬币的中心。Center1_Image = Box1(1:2)+ Box1(3:4)/ 2;%转换为世界坐标。center1_world = pointsToWorld(camerparams, R, t, center1_image);%记住添加0 z坐标。Center1_world = [Center1_world 0];%计算到相机的距离。[〜,核心系列] = utInsicstocamerapose(R,T);distancetocamera = norm(Center1_world - 亚美陆热带);fprintf('从相机到第一个PENNY =%0.2F mm \ n'的距离,...distanceToCamera);
距离相机到第一笔= 719.52 mm的距离
这个例子展示了如何使用一个校准的相机来测量平面物体。注意,测量精度在0.2毫米以内。
[1] Z.张。一种灵活的相机校准技术。图案分析和机器智能的IEEE交易,22(11):1330-1334,2000。