exponenta event banner

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

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

Обзор

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

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

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

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

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

% 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.