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

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

Обзор

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

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

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