Automatische Kamera Kalibrierung
Autor: Madlen Bartnick
Betreuer: Prof. Schneider
Motivation
Kameras haben intrinsische und extrinsische Parameter, welche kalibriert werden müssen.
Ziel
Matlab hat bereits eine Kalibriertoolbox. Diese soll nun so automatisiert werden, dass bei fester Kameraposition die intrinsischen und extrinsischen Parameter automatisch kalibriert werden.
Anforderungen
- Machen Sie sich mit der Kalibriertoolbox von Matlab bekannt.
- Anhand eines Referenzmusters, welches vor der Kamera an verschiedene Positionen bewegt wird, sollen die Kameraparameter bestimmt werden.
- Transformieren Sie das Referenzmuster aus der Kameraperspektive in Weltkoordinaten.
- Stellen Sie die Objekte im Sichtfeld in 3D metrisch dar.
- Schätzen Sie die Genauigkeit Ihres Algorithmus ab.
- Zeigen Sie, dass Objekte Bekannter Größe mit Ihrer Kalibrierung metrisch vermessen werden können.
- Wissenschaftliche Dokumentation als HSHL-Wiki Artikel
- Softwareentwicklung nach SDE Standard in SVN
- Funktionsnachweis als YouTube-Video (vgl. Veranstaltungsregeln)
Lösungen
Automatische Kalibrierung anhand eines Referenzmusters
%% Eingabe der Daten
amountOfImages = 5; % Anzahl der zur Kalibrierung aufzunehmenden Bilder
delaytime = 5; % Verzögerung zwischen der Aufnahme der Kalibrierungsfotos
squareSize = 21; % Größe der Schachbrettquadrate in mm
%% Aufnehmen der Kalibrierungsbilder mittels Webcam
cam = webcam; % Einlesen der Webcam
cd('Kalibrierung') % Ordner zur Speicherung der Kalibrierungsbilder
for i= 1:amountOfImages
img = snapshot(cam); % Aufnahme des Webcam-Bildes
imagesc(img); % Ausgabe des Bildes
axis image; % Achsen an Größe des Bildes anpassen
axis off; % Skalierung der Achsen nicht anzeigen
char = int2str(i); % Umwandeln des Bildindex in Text
filename = (['image' char '.png']); % Zusammensetzen des Speichernamen des Bildes
imwrite (img,filename) % Speichern des Bildes
pause (delaytime); % Zeit bis zur Aufnahme des nächsten Webcam-Bildes
end
%% Kalibrieren der Webcam durch Erkennung des Schachbrettmusters in den Kalibrierungsbildern
images = imageDatastore(fullfile('/Users/madlen/Desktop/DSB/User/SoSe2018/Madlen Bartnick/Kalibrierung'));
imageFileNames = images.Files; % Einlesen der gespeicheten Kalibrierungsbilder
[imagePoints, boardSize,imagesUsed] = detectCheckerboardPoints(imageFileNames); % MATLAB Funktion zur automatischen Erkennung der Schachbrettecken in Pixelkoordinaten
% imagePoints -> Bildpunkte der Schachbrettecken
% boardSize -> Anzahl der Schachbrettquadrate in X- & Y-Richtung
worldPoints = generateCheckerboardPoints(boardSize,squareSize); % MATLAB Funktion zur Transformation der Schachbrettecken in Weltkoordinaten
imageSize = [size(images, 1), size(images, 2)]; % Berechnung der Bildgröße
cameraParams = estimateCameraParameters(imagePoints, worldPoints, ... % MATLAB Funktion zur Errechnung der Kameraparameter
'ImageSize', imageSize);
%% Ausgabe der Kalibrationsergebnisse
figure('units','normalized','outerposition',[0 0 1 1]); % Ausgabe auf dem gesamten Bildschirm
% Ausgabe eines zur Kalibrierung verwendeten Bildes
ax(1)= subplot(2,2,1);
imshow(imageFileNames{1});
title('Erstes Kalibrationsbild');
% Ausgabe eines Kalibrierungsbildes mit erkannten und reproduzierten Schachbildecken
ax(2)= subplot(2,2,2);
imshow(imageFileNames{1});
hold on
plot(imagePoints(:, 1, 1), imagePoints(:, 2, 1), 'go');
plot(cameraParams.ReprojectedPoints(:, 1, 1), cameraParams.ReprojectedPoints(:, 2, 1), 'r+');
legend('Detected Points', 'ReprojectedPoints');
hold off
title('Erkanntes Schachbrett')
imagePoints = zeros; % Zurücksetzen der Bildpunktmatrix
% Ausgabe der extrinsischen Kameraparameter
ax(3)= subplot(2,2,3);
showExtrinsics(cameraParams);
title('Extrinsische Kameraparameter')
drawnow;
% Ausgabe der errechneten Genauigkeit in Pixel
ax(4)= subplot(2,2,4);
showReprojectionErrors(cameraParams);
title('Fehler bei Schachbrettreproduktion');
Metrische Vermessung einer Münze neben dem Referenzmuster
%% Bearbeitung des Bildes zur Segmentierung einer Münze
% Eliminieren der Linsenverzerrung
image=imread(imageFileNames{1});
[correctedImage, newOrigin] = undistortImage(image, cameraParams, 'OutputView', 'full'); % MATLAB Funktion zur Beseitigung von Linsenverzerrung
% Umwandlung des Bildes vom RGB Farbraum in den HSV Farbraum
HSVImage= rgb2hsv(correctedImage);
% Umwandlung in ein Farbsättigungsbild
saturationImage = HSVImage (:, :, 2);
% Umwandlung in ein Binärbild mittels Schwellwertoperation
threshold = graythresh(saturationImage);
binaryImage = (saturationImage > threshold);
%% Erkennung der Münze im Bild
blobAnalysis = vision.BlobAnalysis('AreaOutputPort', true,... % MATLAB Funktion zur Erkennung von Segmenten
'CentroidOutputPort', false,...
'BoundingBoxOutputPort', true,...
'MinimumBlobArea', 200, 'ExcludeBorderBlobs', true);
[areas, positions] = step(blobAnalysis, binaryImage); % Fläche und Position der Segmente
[~, index] = sort(areas, 'Descend'); % Sortierung nach Größe der Fläche
positionOfCoin=positions(index(1:1),:); % Position des größten Elements ist Position der Münze
areaOfCoin= areas(index(1:1),:); % Fläche des größten Elements ist Fläche der Münze
coinImage = insertObjectAnnotation(correctedImage, 'rectangle', ... % Hinzufügen eines Labels für die erkannte Münze
positionOfCoin, 'Münze');
%% Vermessung der Münze
[imagePoints, boardSize] = detectCheckerboardPoints(image); % Erkennung der Schachbrettquadrate
[R, t] = extrinsics(imagePoints, worldPoints, cameraParams); % Ermittlung der extrinsischen Kameraparameter bei Aufnahme des Bildes
upperLeftCornerX = positionOfCoin(1);
upperLeftCornerY = positionOfCoin(2);
upperLeftCorner = [upperLeftCornerX,upperLeftCornerY];% Labelecke oben links in Pixel
upperRightCornerX = positionOfCoin(1)+positionOfCoin(3);
upperRightCornerY = positionOfCoin (2);
upperRightCorner = [upperRightCornerX, upperRightCornerY];% Labelecke oben rechts in Pixel
upperCornersInPixel = [upperLeftCorner;upperRightCorner]; % Obere Labelecken in Pixel
upperCornersInWorld = pointsToWorld(cameraParams, R, t, upperCornersInPixel); % Transformieren der Labelecken in Weltkoordinaten
diffWorld = upperCornersInWorld(2, :) - upperCornersInWorld(1, :); % Differenz zwischen oberen Labelecken in Weltkoordinaten
diameterInMillimeter = hypot(diffWorld(1), diffWorld(2)); % Euklidische Distanz zwischen oberen Labelecken entspricht dem Durchmesser der Münze in Weltkoordinaten (mm)
%% Ausgabe der Vermessungsergebnisse
figure('units','normalized','outerposition',[0 0 1 1]); % Ausgabe auf dem gesamten Bildschirm
ax(1)= subplot(2,2,1);
imshow(imageFileNames{1});
title('Original Bild')
ax(2)= subplot(2,2,2);
imshow(correctedImage);
title('Verzerrungsfreies Bild')
ax(3)= subplot(2,2,3);
imshow(binaryImage);
hold on;
title('Binärbild')
ax(4)= subplot(2,2,4);
imshow(coinImage);
title('Erkannte Münze')
fprintf('Tatsächlicher Durchmesser der Münze: 29 mm\n');
fprintf('Gemessener Durchmesser der Münze: %0.2f mm\n', diameterInMillimeter);
Weblinks
BSD-Lizenzbedingung BSD-Lizenz
Copyright (c) 2014, Hochschule Hamm-Lippstadt, Dep. Lip. 1, Prof. Schneider
Hochschule Hamm-Lippstadt. Alle Rechte vorbehalten.
→ zurück zum Hauptartikel: Digitale Signal- und Bildverarbeitung SoSe2018