Измерение плоских объектов калиброванной камерой

Этот пример показывает, как измерить диаметр монет в мировых единицах измерения с помощью одной калиброванной камеры.

Обзор

В этом примере показано, как калибровать камеру, а затем использовать ее для измерения размера планарных объектов, таких как монеты. Примером применения этого подхода является измерение деталей на конвейерной ленте для контроля качества.

Калибровка камеры

Калибровка камеры - это процесс оценки параметров объектива и датчика изображения. Эти параметры необходимы для измерения объектов, захваченных камерой. В этом примере показано, как выполнить программную калибровку камеры. Также можно калибровать камеру с помощью cameraCalibrator приложение.

Чтобы калибровать камеру, нам сначала нужно сделать несколько изображения калибровочного шаблона с разных углов. Типичным калибровочным шаблоном является асимметричная шахматная доска, где одна сторона содержит четное количество квадратов, как черных, так и белых, а другая - нечетное количество квадратов.

Шаблон должен быть прикреплен к плоской поверхности, и он должен находиться примерно на том же расстоянии от камеры, что и объекты, которые вы хотите измерить. Размер квадрата должен быть измерен в мировых единицах измерения, для примера миллиметров, как можно точнее. В этом примере мы используем 9 изображений шаблона, но на практике рекомендуется использовать от 10 до 20 изображений для точной калибровки.

Подготовка калибровочных изображений

Создайте массив ячеек с именами файлов калибровочных изображений.

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;
I = imread(files{1});
figure; imshow(I, 'InitialMagnification', magnification);
title('One of the Calibration Images');

Figure contains an axes. The axes with title One of the Calibration Images contains an object of type image.

Оценка параметров камеры

% 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).
squareSize = 29; % in millimeters
worldPoints = generateCheckerboardPoints(boardSize, squareSize);

% Calibrate the camera.
imageSize = [size(I, 1), size(I, 2)];
cameraParams = estimateCameraParameters(imagePoints, worldPoints, ...
                                     'ImageSize', imageSize);

% Evaluate calibration accuracy.
figure; showReprojectionErrors(cameraParams);
title('Reprojection Errors');

Figure contains an axes. The axes with title Reprojection Errors contains 3 objects of type bar, line. This object represents Overall Mean Error: 0.90 pixels.

Штриховой график указывает точность калибровки. На каждой панели показана средняя ошибка репроекции для соответствующего калибровочного изображения. Ошибками репроекции являются расстояния между угловыми точками, обнаруженными в изображении, и соответствующими идеальными мировыми точками, проецируемыми в изображение.

Чтение изображения объектов, которые будут измеряться

Загрузите изображение, содержащее объекты, которые будут измеряться. Это изображение включает калибровочный шаблон, и шаблон находится в той же плоскости, что и объекты, которые вы хотите измерить. В этом примере и шаблоне, и монеты находятся на одной и той же таблице верхней части.

Кроме того, можно использовать два отдельных изображения: одно, содержащее шаблон, а другое, содержащее объекты, которые будут измеряться. Снова объекты и шаблон должны быть в одной плоскости. Кроме того, изображения должны быть получены точно с той же точки зрения, что означает, что камера должна быть зафиксирована на месте.

imOrig = imread(fullfile(matlabroot, 'toolbox', 'vision', 'visiondata', ...
        'calibration', 'slr', 'image9.jpg'));
figure; imshow(imOrig, 'InitialMagnification', magnification);
title('Input Image');

Figure contains an axes. The axes with title Input Image contains an object of type image.

Отмена искажения изображения

Используйте объект cameraParameters, чтобы удалить искажение объектива с изображения. Это необходимо для точного измерения.

% Since the lens introduced little distortion, use 'full' output view to illustrate that
% the image was undistored. If we used the default 'same' option, it would be difficult
% to notice any difference when compared to the original image. Notice the small black borders.
[im, newOrigin] = undistortImage(imOrig, cameraParams, 'OutputView', 'full');
figure; imshow(im, 'InitialMagnification', magnification);
title('Undistorted Image');

Figure contains an axes. The axes with title Undistorted Image contains an object of type image.

Обратите внимание, что это изображение демонстрирует очень маленькое искажение объектива. Шаг неискажения намного важнее, если вы используете широкоугольный линз или веб-камеру низкого уровня.

Сегментные монеты

При этом монеты красочны на белом фоне. Используйте компонент насыщенности представления HSV изображения, чтобы сегментировать их.

% Convert the image to the HSV color space.
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');

Figure contains an axes. The axes with title Segmented Coins contains an object of type image.

Обнаружение монет

Можно предположить, что два самых больших связанных компонента в сегментированном изображении соответствуют монетам.

% 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), :));

% 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');

Figure contains an axes. The axes with title Detected Coins contains an object of type image.

Вычисление внешних данных

Чтобы сопоставить точки в координатах изображения с точками в мировых координатах, нам нужно вычислить поворот и перемещение камеры относительно калибровочного шаблона. Обратите внимание, что extrinsics функция принимает, что искажения объектива нет. В этом случае imagePoints были обнаружены в изображении, которое уже не искажалось использованием undistortImage.

% Detect the checkerboard.
[imagePoints, boardSize] = detectCheckerboardPoints(im);

% Adjust the imagePoints so that they are expressed in the coordinate system
% used in the original image, before it was undistorted.  This adjustment
% makes it compatible with the cameraParameters object computed for the original image.
imagePoints = imagePoints + newOrigin; % adds newOrigin to every row of imagePoints

% Compute rotation and translation of the camera.
[R, t] = extrinsics(imagePoints, worldPoints, cameraParams);

Измерьте первую монету

Для измерения первой монеты преобразуем верхний левый и верхний правый углы ограничивающего прямоугольника в мировые координаты. Затем вычисляем евклидово расстояние между ними в миллиметрах. Обратите внимание, что фактический диаметр пенни США составляет 19,05 мм.

% Adjust upper left corners of bounding boxes for coordinate system shift 
% caused by undistortImage with output view of 'full'. This would not be
% needed if the output was 'same'. The adjustment makes the points compatible
% with the cameraParameters of the original image.
boxes = boxes + [newOrigin, 0, 0]; % zero padding is added for widht and height

% 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);
Measured diameter of one penny = 19.00 mm

Измерьте вторую монету

Измерьте вторую монету так же, как и первую.

% 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.85 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.
center1_world = [center1_world 0];

% Compute the distance to the camera.
[~, cameraLocation] = extrinsicsToCameraPose(R, t);
distanceToCamera = norm(center1_world - cameraLocation);
fprintf('Distance from the camera to the first penny = %0.2f mm\n', ...
    distanceToCamera);
Distance from the camera to the first penny = 719.52 mm

Сводные данные

Этот пример показал, как использовать калиброванную камеру для измерения плоских объектов. Обратите внимание, что измерения были точными в пределах 0,2 мм.

Ссылки

[1] З. Чжан. Гибкий новый техник калибровки фотоаппарата. Транзакции IEEE по Pattern Analysis and Machine Intelligence, 22 (11): 1330-1334, 2000.