水平相机校准
该图案必须贴在一个平面上,它应该与你所要测量的物体的距离大致相同
Prepare Calibration Images
Create a cell array of file names of calibration images.
准备校准图像
创建校准图像文件名的单元格数组。
numImages = 9;
files = cell(1, numImages);
for i = 1:numImages
files{i} = fullfile(matlabroot, 'toolbox', 'vision', 'visiondata', ...
'calibration', 'slr', sprintf('image%d.jpg', i));
end
% Display one of the calibration images显示一个校准图像
magnification = 25;
figure; imshow(files{1}, 'InitialMagnification', magnification);
title('One of the Calibration Images');
Estimate Camera Parameters 摄像机相机参数
% Detect the checkerboard corners in the images.图像棋盘检测
[imagePoints, boardSize] = detectCheckerboardPoints(files);
% Generate the world coordinates of the checkerboard corners in the
% pattern-centric coordinate system, with the upper-left corner at (0,0).
设定坐标,将最左边上方的棋盘格定为(0,0),单位毫米
squareSize = 29; % in millimeters
worldPoints = generateCheckerboardPoints(boardSize, squareSize);
% Calibrate the camera.
cameraParams = estimateCameraParameters(imagePoints, worldPoints);
% Evaluate calibration accuracy.校准精度评估
figure; showReprojectionErrors(cameraParams);
title('Reprojection Errors');
读取待测量的图片
加载包含要测量的对象的图像。该图像包含校准模式,并且该模式与您要测量的对象处于同一平面内。
在这个例子中,图案和硬币都在同一个桌面上。
或者,您可以使用两个独立的图像:一个包含模式,
另一个包含要测量的对象。同样,对象和模式必须位于同一平面内。此外,图像必须从完全相同的视点捕获,
这意味着摄像机必须固定在适当的位置。
imOrig = imread(fullfile(matlabroot, 'toolbox', 'vision', 'visiondata', ...
'calibration', 'slr', 'image9.jpg'));
figure; imshow(imOrig, 'InitialMagnification', magnification);
title('Input Image');
Undistort the Image失真图像
使用相机参数对象从图像中删除镜头畸变。这是精确测量所必需的。
[im, newOrigin] = undistortImage(imOrig, cameraParams, 'OutputView', 'full');
figure; imshow(im, 'InitialMagnification', magnification);
title('Undistorted Image');
注意,这个图像的镜头畸变很小。不失真的步骤更为重要,如果你使用广角镜头,或低端摄像头。
Segment Coins硬币分割
In this case, the coins are colorful on white background. Use the saturation component(饱和度分量) of the HSV
representation of the image to segment them out.
% Convert the image to the HSV color space.图像转为HSV
imHSV = rgb2hsv(im);
% Get the saturation channel.获得饱和通道
saturation = imHSV(:, :, 2);
% Threshold the image图像阈值
t = graythresh(saturation);
imCoin = (saturation > t);
figure; imshow(imCoin, 'InitialMagnification', magnification);
title('Segmented Coins');
寻找最大的分量检测硬币
% Find connected components.寻找组件
blobAnalysis = vision.BlobAnalysis('AreaOutputPort', true,...
'CentroidOutputPort', false,...
'BoundingBoxOutputPort', true,...
'MinimumBlobArea', 200, 'ExcludeBorderBlobs', true);
[areas, boxes] = step(blobAnalysis, imCoin);
% Sort connected components in descending order by area区域降序寻找组件
[~, idx] = sort(areas, 'Descend');
% Get the two largest components.得到最大的组件
boxes = double(boxes(idx(1:2), :));
% Adjust for coordinate system shift caused by undistortImage调整坐标系偏移引起的失真图像
boxes(:, 1:2) = bsxfun(@plus, boxes(:, 1:2), newOrigin);
% Reduce the size of the image for display.缩小显示图像大小
scale = magnification / 100;
imDetectedCoins = imresize(im, scale);
% Insert labels for the coins.给硬币插入标签
imDetectedCoins = insertObjectAnnotation(imDetectedCoins, 'rectangle', ...
scale * boxes, 'penny');
figure; imshow(imDetectedCoins);
title('Detected Coins');
计算外部
为了将图像坐标中的点映射到世界坐标点,我们需要计算摄像机相对于标定模式的旋转和平移。
注意:非本征函数假定没有镜头畸变。在这种情况下图像点已在已无失真图像检测应用。
% Detect the checkerboard.棋盘格检测
[imagePoints, boardSize] = detectCheckerboardPoints(im);
% Compute rotation and translation of the camera.计算摄像机的旋转与平移
[R, t] = extrinsics(imagePoints, worldPoints, cameraParams);
测量第一枚硬币
为了测量第一枚硬币,我们将包围框的左上角和右上角转换为世界坐标。然后
我们用毫米计算它们之间的距离。一个硬币实际直径是19.05毫米。
% Get the top-left and the top-right corners.得到左上和右上脚的位置
box1 = double(boxes(1, :));
imagePoints1 = [box1(1:2); ...
box1(1) + box1(3), box1(2)];
% Get the world coordinates of the corners 获取角的世界坐标
worldPoints1 = pointsToWorld(cameraParams, R, t, imagePoints1);
% Compute the diameter of the coin in millimeters.毫米计算直径的距离
d = worldPoints1(2, :) - worldPoints1(1, :);
diameterInMillimeters = hypot(d(1), d(2));
fprintf('Measured diameter of one penny = %0.2f mm\n', diameterInMillimeters);
Measure the Second Coin计算第二枚硬币
Measure the second coin the same way as the first coin.
% Get the top-left and the top-right corners.
box2 = double(boxes(2, :));
imagePoints2 = [box2(1:2); ...
box2(1) + box2(3), box2(2)];
% Apply the inverse transformation from image to world
worldPoints2 = pointsToWorld(cameraParams, R, t, imagePoints2);
% Compute the diameter of the coin in millimeters.
d = worldPoints2(2, :) - worldPoints2(1, :);
diameterInMillimeters = hypot(d(1), d(2));
fprintf('Measured diameter of the other penny = %0.2f mm\n', diameterInMillimeters);
Measured diameter of the other penny = 18.88 mm
测量第一个硬币的距离
% Compute the center of the first coin in the image.第一枚硬币的中心位置
center1_image = box1(1:2) + box1(3:4)/2;
% Convert to world coordinates. 转换为世界坐标
center1_world = pointsToWorld(cameraParams, R, t, center1_image);
% Remember to add the 0 z-coordinate. 给世界坐标标定初始值0的坐标
center1_world = [center1_world 0];
% Compute the distance to the camera.计算相机的距离
distanceToCamera = norm(center1_world + t);
fprintf('Distance from the camera to the first penny = %0.2f mm\n', ...
distanceToCamera);
(/***精度控制在2mm***/)
该图案必须贴在一个平面上,它应该与你所要测量的物体的距离大致相同
Prepare Calibration Images
Create a cell array of file names of calibration images.
准备校准图像
创建校准图像文件名的单元格数组。
numImages = 9;
files = cell(1, numImages);
for i = 1:numImages
files{i} = fullfile(matlabroot, 'toolbox', 'vision', 'visiondata', ...
'calibration', 'slr', sprintf('image%d.jpg', i));
end
% Display one of the calibration images显示一个校准图像
magnification = 25;
figure; imshow(files{1}, 'InitialMagnification', magnification);
title('One of the Calibration Images');
Estimate Camera Parameters 摄像机相机参数
% Detect the checkerboard corners in the images.图像棋盘检测
[imagePoints, boardSize] = detectCheckerboardPoints(files);
% Generate the world coordinates of the checkerboard corners in the
% pattern-centric coordinate system, with the upper-left corner at (0,0).
设定坐标,将最左边上方的棋盘格定为(0,0),单位毫米
squareSize = 29; % in millimeters
worldPoints = generateCheckerboardPoints(boardSize, squareSize);
% Calibrate the camera.
cameraParams = estimateCameraParameters(imagePoints, worldPoints);
% Evaluate calibration accuracy.校准精度评估
figure; showReprojectionErrors(cameraParams);
title('Reprojection Errors');
读取待测量的图片
加载包含要测量的对象的图像。该图像包含校准模式,并且该模式与您要测量的对象处于同一平面内。
在这个例子中,图案和硬币都在同一个桌面上。
或者,您可以使用两个独立的图像:一个包含模式,
另一个包含要测量的对象。同样,对象和模式必须位于同一平面内。此外,图像必须从完全相同的视点捕获,
这意味着摄像机必须固定在适当的位置。
imOrig = imread(fullfile(matlabroot, 'toolbox', 'vision', 'visiondata', ...
'calibration', 'slr', 'image9.jpg'));
figure; imshow(imOrig, 'InitialMagnification', magnification);
title('Input Image');
Undistort the Image失真图像
使用相机参数对象从图像中删除镜头畸变。这是精确测量所必需的。
[im, newOrigin] = undistortImage(imOrig, cameraParams, 'OutputView', 'full');
figure; imshow(im, 'InitialMagnification', magnification);
title('Undistorted Image');
注意,这个图像的镜头畸变很小。不失真的步骤更为重要,如果你使用广角镜头,或低端摄像头。
Segment Coins硬币分割
In this case, the coins are colorful on white background. Use the saturation component(饱和度分量) of the HSV
representation of the image to segment them out.
% Convert the image to the HSV color space.图像转为HSV
imHSV = rgb2hsv(im);
% Get the saturation channel.获得饱和通道
saturation = imHSV(:, :, 2);
% Threshold the image图像阈值
t = graythresh(saturation);
imCoin = (saturation > t);
figure; imshow(imCoin, 'InitialMagnification', magnification);
title('Segmented Coins');
寻找最大的分量检测硬币
% Find connected components.寻找组件
blobAnalysis = vision.BlobAnalysis('AreaOutputPort', true,...
'CentroidOutputPort', false,...
'BoundingBoxOutputPort', true,...
'MinimumBlobArea', 200, 'ExcludeBorderBlobs', true);
[areas, boxes] = step(blobAnalysis, imCoin);
% Sort connected components in descending order by area区域降序寻找组件
[~, idx] = sort(areas, 'Descend');
% Get the two largest components.得到最大的组件
boxes = double(boxes(idx(1:2), :));
% Adjust for coordinate system shift caused by undistortImage调整坐标系偏移引起的失真图像
boxes(:, 1:2) = bsxfun(@plus, boxes(:, 1:2), newOrigin);
% Reduce the size of the image for display.缩小显示图像大小
scale = magnification / 100;
imDetectedCoins = imresize(im, scale);
% Insert labels for the coins.给硬币插入标签
imDetectedCoins = insertObjectAnnotation(imDetectedCoins, 'rectangle', ...
scale * boxes, 'penny');
figure; imshow(imDetectedCoins);
title('Detected Coins');
计算外部
为了将图像坐标中的点映射到世界坐标点,我们需要计算摄像机相对于标定模式的旋转和平移。
注意:非本征函数假定没有镜头畸变。在这种情况下图像点已在已无失真图像检测应用。
% Detect the checkerboard.棋盘格检测
[imagePoints, boardSize] = detectCheckerboardPoints(im);
% Compute rotation and translation of the camera.计算摄像机的旋转与平移
[R, t] = extrinsics(imagePoints, worldPoints, cameraParams);
测量第一枚硬币
为了测量第一枚硬币,我们将包围框的左上角和右上角转换为世界坐标。然后
我们用毫米计算它们之间的距离。一个硬币实际直径是19.05毫米。
% Get the top-left and the top-right corners.得到左上和右上脚的位置
box1 = double(boxes(1, :));
imagePoints1 = [box1(1:2); ...
box1(1) + box1(3), box1(2)];
% Get the world coordinates of the corners 获取角的世界坐标
worldPoints1 = pointsToWorld(cameraParams, R, t, imagePoints1);
% Compute the diameter of the coin in millimeters.毫米计算直径的距离
d = worldPoints1(2, :) - worldPoints1(1, :);
diameterInMillimeters = hypot(d(1), d(2));
fprintf('Measured diameter of one penny = %0.2f mm\n', diameterInMillimeters);
Measure the Second Coin计算第二枚硬币
Measure the second coin the same way as the first coin.
% Get the top-left and the top-right corners.
box2 = double(boxes(2, :));
imagePoints2 = [box2(1:2); ...
box2(1) + box2(3), box2(2)];
% Apply the inverse transformation from image to world
worldPoints2 = pointsToWorld(cameraParams, R, t, imagePoints2);
% Compute the diameter of the coin in millimeters.
d = worldPoints2(2, :) - worldPoints2(1, :);
diameterInMillimeters = hypot(d(1), d(2));
fprintf('Measured diameter of the other penny = %0.2f mm\n', diameterInMillimeters);
Measured diameter of the other penny = 18.88 mm
测量第一个硬币的距离
% Compute the center of the first coin in the image.第一枚硬币的中心位置
center1_image = box1(1:2) + box1(3:4)/2;
% Convert to world coordinates. 转换为世界坐标
center1_world = pointsToWorld(cameraParams, R, t, center1_image);
% Remember to add the 0 z-coordinate. 给世界坐标标定初始值0的坐标
center1_world = [center1_world 0];
% Compute the distance to the camera.计算相机的距离
distanceToCamera = norm(center1_world + t);
fprintf('Distance from the camera to the first penny = %0.2f mm\n', ...
distanceToCamera);
(/***精度控制在2mm***/)