Ich brauchte etwas namens Kamerakalibrierung, also habe ich es versucht. Hinweis: Da ich Autodidakt bin, kann es zu ungenauen Aussagen kommen.
Es gibt Formeln, die zwischen räumlicher Position und Position auf dem Bild konvertieren können, dies erfordert jedoch Kameraparameter. Es gibt verschiedene Arten von Kameraparametern, die grob in interne und externe Parameter unterteilt werden können. Ich weiß auch nicht, ob es in den internen Parametern enthalten ist, aber es gibt auch einen Linsenverzerrungskoeffizienten (Verzerrung).
Interne Parameter sind "von der Kamera bestimmte Parameter". ・ Fokusentfernung f ・ Physikalischer Abstand der Pixel δu </ sub>, δv </ sub>
Externe Parameter sind "Parameter der Kameraposition und -ausrichtung in Bezug auf das Weltkoordinatensystem". ・ Rotationsmatrix R 3 </ sub> ・ Paralleler Bewegungsvektor t 3 </ sub>
Bei der Kamerakalibrierung werden nun die Parameter dieser Kamera ermittelt. Die zu diesem Zeitpunkt erhaltenen internen und externen Parameter werden zusammen als Kameramatrix oder perspektivische Projektionsmatrix bezeichnet. Bestimmen Sie die Parameter, indem Sie die räumlichen Punkte, deren Positionen im Voraus bekannt sind, und die Projektionspunkte (dh die Koordinaten auf dem Bild) auf das Bild auf die Formel der Matrix anwenden.
Nehmen Sie insbesondere ein Bild auf, während Sie das Kalibrierungsziel (z. B. ein Schachbrett) bewegen. Da die Länge des Schachbrettgitters bekannt ist, ist der Abstand zwischen den Gitterpunkten bekannt und seine Position im Raum wird bestimmt. (Umgekehrt bestimmt es das Weltkoordinatensystem) Es werden auch die Koordinaten der Gitterpunkte auf dem Bild abgerufen. (Erfassung von Bildkoordinaten) Nehmen Sie mehrere Bilder auf und verwenden Sie die Methode der kleinsten Quadrate, um die Parameter zu ermitteln.
Referenz (Referenz) Quelle: "Digitale Bildverarbeitung [überarbeitete neue Ausgabe]", der Ausdruck wurde der Einfachheit halber geändert. Referenz: Kamerakalibrierung und 3D-Rekonstruktion - OpenCV.jp
Dieses Mal habe ich die Kamera mit dem Brustbrett kalibriert, was meiner Meinung nach nach dem folgenden groben Verfahren relativ einfach ist.
Den Code finden Sie unter OpenCV_CameraCalibration --GitHub. Bitte.
Ich werde jedes etwas detaillierter erklären.
Stellen Sie das Weltkoordinatensystem beliebig so ein, dass die Ebene des flachen Kalibrierungsziels (Brustbrett) Z = 0 ist. Messen Sie zu diesem Zeitpunkt den Abstand zwischen den Gitterpunkten und stellen Sie die Punkte in mm ein. Ich rufe hier an.
List<Mat> objectPoints = getObjectPoints(outputFindChessboardCorners.size(), patternSize); //Dreidimensionale Koordinaten der Ecke des Schachbretts(z=0), Für die Anzahl der aufgenommenen Bilder.
OpenCV_CameraCalibration_L68 - GitHub
Der Inhalt von getObjectPoints () lautet wie folgt.
public List<Mat> getObjectPoints(int size, Size patternSize) {
List<Mat> objectPoints = new ArrayList<>();
for (int i = 0; i < size; i++) {
objectPoints.add(getObjectPoint(patternSize));
}
return objectPoints;
}
public MatOfPoint3f getObjectPoint(Size patternSize) {
MatOfPoint3f objectPoint = new MatOfPoint3f();
List<Point3> objectPoint_ = new ArrayList<>();
// final Size patternSize = new Size(6, 9); //Anzahl der zu erforschenden Ecken
for (int row = 0; row < patternSize.height; row++) {
for (int col = 0; col < patternSize.width; col++) {
objectPoint_.add(getPoint(row, col));
}
}
objectPoint.fromList(objectPoint_);
return objectPoint;
}
public Point3 getPoint(int row, int col) {
final double REAL_HEIGHT = 20.0, REAL_WIDTH = 20.0;
return new Point3(col * REAL_WIDTH, row * REAL_HEIGHT, 0.0); //Vielleicht x, y,z sieht so aus.
}
OpenCV_CameraCalibration_L96 - GitHub
Ich habe eine Methode namens findChessboardCorners () geschrieben. Der Anruf sieht folgendermaßen aus:
List<Mat> outputFindChessboardCorners = new ArrayList<>();
try (DirectoryStream<Path> ds = Files.newDirectoryStream(picFolderPath)) {
for (Path path : ds) {
System.out.println(path.toString());
final Optional<Mat> outputMat = findChessboardCorners(path.toString(), imagePoints, patternSize);
if (outputMat.isPresent()) {
outputFindChessboardCorners.add(outputMat.get());
System.out.println("successful to find corners.");
} else {
System.err.println("unsuccessful to find corners.");
}
}
} catch (IOException ex) {
ex.printStackTrace();
}
OpenCV_CameraCalibration_L50 - GitHub
Der Inhalt von findChessboardCorners () lautet wie folgt. Ich habe eine Methode namens Calib3d.findChessboardCorners () verwendet. Darüber hinaus enthält die zurückgegebene Mat ein Image, das Calib3d.findChessboardCorners () normal ausführen konnte.
public Optional<Mat> findChessboardCorners(String picPathString, List<Mat> imagePoints, Size patternSize) {
Mat inputMat = Imgcodecs.imread(picPathString);
Mat mat = inputMat.clone();
// final Size patternSize = new Size(6, 9); //Anzahl der zu erforschenden Ecken
MatOfPoint2f corners = new MatOfPoint2f(); // in,Empfängt einen Vektor zweidimensionaler Koordinaten der erkannten Ecke.
Imgproc.cvtColor(inputMat, inputMat, Imgproc.COLOR_BGR2GRAY);
final boolean canFindChessboard = Calib3d.findChessboardCorners(inputMat, patternSize, corners);
if (!canFindChessboard) {
System.err.println("Cannot find Chessboard Corners.");
return Optional.empty();
}
imagePoints.add(corners);
Calib3d.drawChessboardCorners(mat, patternSize, corners, true);
Path picPath = Paths.get(picPathString);
Path folderPath = Paths.get("S:\\CameraCaliblation\\2018-12-31_output");
Path path = Paths.get(folderPath.toString(), picPath.getFileName().toString());
if (!Files.exists(folderPath) || !Files.isDirectory(folderPath)) {
try {
System.out.println("There was no folder, so it is createing a folder. : " + folderPath.toString());
Files.createDirectory(folderPath);
} catch (IOException ex) {
ex.printStackTrace();
}
}
Imgcodecs.imwrite(path.toString(), mat);
return Optional.of(inputMat);
}
Calib3d.calibrateCamera () mit den Koordinaten der Gitterpunkte in dem zuvor vorbereiteten Raum und den Koordinaten der Gitterpunkte des Brustbretts auf dem Bild, die zuvor als Argumente erhalten wurden. /camera_calibration_and_3d_reconstruction.html#cv-calibratecamera). Außerdem gibt diese Methode die Werte der Kameramatrix und des Objektivverzerrungskoeffizienten zurück. Erstellen Sie daher eine Variable, um sie zu speichern.
//Was zu erhalten
Mat cameraMatrix = new Mat(), distortionCoefficients = new Mat();
List<Mat> rotationMatrixs = new ArrayList<>(), translationVectors = new ArrayList<>();
Calib3d.calibrateCamera(objectPoints, imagePoints, imageSize,
cameraMatrix, distortionCoefficients, rotationMatrixs, translationVectors);
OpenCV_CameraCalibration_L81 - GitHub
Ich konnte die Kameramatrix und den Objektivverzerrungskoeffizienten ermitteln, aber es ist mühsam und verschwenderisch, dies jedes Mal zu tun. Speichern wir also die Matrixwerte. Im Fall von C und Python gibt es etwas, das den Mat-Wert auf der OpenCV-Seite eingibt und ausgibt. Da es sich jedoch nicht um die Java-Version handelt, habe ich ihn diesmal selbst erstellt. Ich habe die XML-Eingabe / Ausgabe in der Java-Standardbibliothek verwendet.
Map<String, Mat> exportMats = new HashMap<>();
exportMats.put("CameraMatrix", cameraMatrix);
exportMats.put("DistortionCoefficients", distortionCoefficients);
final Path exportFilePath = Paths.get("S:\\CameraCaliblation\\CameraCalibration_2018-12-31.xml");
MatIO.exportMat(exportMats, exportFilePath);
OpenCV_CameraCalibration_L87 - GitHub
Der Inhalt von MatIO ist OpenCV_CameraCalibration_MatIO.java --GitHub Bitte beziehen Sie sich auf.
Verwenden Sie vorerst [ArUco AR Marker Haltungsschätzung](https://qiita.com/smk7758/items/1ca1370f78cad1233d02#%E3%82%AB%E3%83%A1%E3%83%A9% E3% 82% 92% E7% 94% A8% E3% 81% 84% E3% 81% 9F% E3% 83% AA% E3% 82% A2% E3% 83% AB% E3% 82% BF% E3% 82% A4% E3% 83% A0marker% E5% A7% BF% E5% 8B% A2% E6% 8E% A8% E5% AE% 9A) und es hat gut funktioniert. Ich bin froh, dass auch die Junioren unserer Informationsgruppe es verstanden und ausgeführt haben und es geschafft haben.
・ OpenCV - So führen Sie eine Kamerakalibrierung durch --Pynote ・ Kamerakalibrierung (OpenCV 1.0) --OpenCV.jp
Recommended Posts