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