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

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

Обзор

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

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

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