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