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

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

Обзор

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

Калибруйте камеру

Калибровка фотоаппарата является процессом оценки параметров линзы и формирователя изображения. Эти параметры необходимы, чтобы измерить объекты, полученные камерой. Этот пример показывает, как калибровать камеру программно. Также можно калибровать камеру с помощью приложения 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');

Оцените параметры камеры

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

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

Считайте изображение объектов, которые будут измерены

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

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

imOrig = imread(fullfile(matlabroot, 'toolbox', 'vision', 'visiondata', ...
        'calibration', 'slr', 'image9.jpg'));
figure; imshow(imOrig, 'InitialMagnification', magnification);
title('Input 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');

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

Монеты сегмента

В этом случае монеты красочны на белом фоне. Используйте компонент насыщения представления 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');

Обнаружьте монеты

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

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

Вычислите Extrinsics

Сопоставлять точки в изображении координирует к точкам в мировых координатах, мы должны вычислить вращение и перевод камеры относительно калибровочного шаблона. Обратите внимание на то, что функция 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 согласно Анализу Шаблона и Искусственному интеллекту, 22 (11):1330-1334, 2000.