Ich habe die OpenCV-Kamerakalibrierung in Java durchgeführt

Einführung

Ich brauchte etwas namens Kamerakalibrierung, also habe ich es versucht. Hinweis: Da ich Autodidakt bin, kann es zu ungenauen Aussagen kommen.

Was ist Kamerakalibrierung?

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

Interne Parameter sind "von der Kamera bestimmte Parameter". ・ Fokusentfernung f ・ Physikalischer Abstand der Pixel δu </ sub>, δv </ sub>

Externe Parameter

Externe Parameter sind "Parameter der Kameraposition und -ausrichtung in Bezug auf das Weltkoordinatensystem". ・ Rotationsmatrix R 3 </ sub> ・ Paralleler Bewegungsvektor t 3 </ sub>

Was ist Kamerakalibrierung?

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

Führen Sie eine Kamerakalibrierung mit OpenCV durch

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.

  1. Halten Sie das Brustbrett (Kalibrierungsziel) und machen Sie ein Bild, während Sie es bewegen.
  2. Bestimmen Sie die Koordinaten des Weltkoordinatensystems und der Gitterpunkte im Raum
  3. Finden Sie die Koordinaten der Brustbrettgitterpunkte auf dem Bild [mit Calib3d.findChessboardCorners ()]
  4. Führen Sie Calib3d.calibrateCamera () aus
  5. Speichern Sie die zurückgegebene Kameramatrix und den Objektivverzerrungskoeffizienten Der Umriss sieht so aus.

Ich werde jedes etwas detaillierter erklären.

Bestimmen Sie die Koordinaten des Weltkoordinatensystems und der Gitterpunkte im Raum

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

Finden Sie die Koordinaten der Brustbrettgitterpunkte auf dem Bild

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);
	}

Führen Sie Calib3d.calibrateCamera () aus

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

Speichern Sie die zurückgegebene Kameramatrix und den Objektivverzerrungskoeffizienten

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.

abschließend

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.

Referenzlink

OpenCV - So führen Sie eine Kamerakalibrierung durch --PynoteKamerakalibrierung (OpenCV 1.0) --OpenCV.jp

Recommended Posts

Ich habe die OpenCV-Kamerakalibrierung in Java durchgeführt
Verwenden Sie OpenCV mit Java
Ich habe ein Roulette in Java gemacht.
Ich habe versucht, Metaprogrammierung mit Java
Ich habe eine E-Mail in Java gesendet
Ich habe ein PDF mit Java erstellt.
Ich habe eine Anmerkung in Java gemacht.
Ich habe versucht, JWT in Java zu verwenden
Java + OpenCV 3.X mit IntelliJ IDEA
[java] Was ich getan habe, als ich Listen in meiner eigenen Klasse verglichen habe
Ich habe versucht, die Elasticsearch-API in Java zu verwenden
Ich habe das neue Yuan-Problem in Java ausprobiert
Ich habe versucht, OpenCV mit Java + Tomcat zu verwenden
[* Java *] Ich habe am JJUG CCC 2019 Spring teilgenommen
Ich habe ein Programm zur Beurteilung von Primzahlen in Java erstellt
Erkennen Sie ähnliche Videos in Java und OpenCV Version 2
Verwenden Sie OpenCV_Contrib (ArUco) mit Java! (Teil 1-Build) (OpenCV-3.4.4)
Partisierung in Java
Ich möchte eine E-Mail in Java senden.
Ich habe Java gemacht, um (a == 1 && a == 2 && a == 3) immer wahr zu machen
Änderungen in Java 11
Ich wollte (a == 1 && a == 2 && a == 3) in Java wahr machen
Ich habe ein Programm zur Beurteilung von Primzahlen in Java geschrieben
Ich habe ein Janken-Spiel in Java (CLI) gemacht.
rsync4j - Ich möchte rsync in Java berühren.
Erkennen Sie ähnliche Videos in Java und OpenCV Version 3
Was ich in Java gelernt habe (Teil 2) Was sind Variablen?
Ich habe versucht, neunundneunzig in Java auszugeben
Was ich getan habe, als ich Java zu Kotlin konvertiert habe
Erkennen Sie ähnliche Videos in Java und OpenCV Version 1
Ich habe versucht, Alexa-Fähigkeiten mit Java zu erstellen
Ich habe ein Primfaktorisierungsprogramm in Java geschrieben
Umfangsrate in Java
FizzBuzz in Java
Ich habe ein einfaches Berechnungsproblemspiel in Java gemacht
Versuchte Mastodons Toot- und Streaming-API in Java
Ich möchte so etwas wie "cls" in Java machen
Ich habe leicht verständlich über Java Downcast geschrieben
Ich möchte ES2015 auch in Java verwenden! → (´ ・ ω ・ `)
# 2 [Anmerkung] Ich habe versucht, neunundneunzig mit Java zu berechnen.
Ich habe versucht, eine Clova-Fähigkeit in Java zu erstellen
Ich habe versucht, eine Anmeldefunktion mit Java zu erstellen
Adressiert, da Azure-Funktionen in Java nicht mehr funktionieren
Ich habe versucht, die erweiterte for-Anweisung in Java zu verwenden
Ich habe versucht, Java Silver in 2 Wochen zu bestehen, ohne Java zu kennen
Ich habe versucht, die Methode der gegenseitigen Teilung von Eugrid in Java zu implementieren
~ Ich habe jetzt versucht, funktionale Programmierung mit Java zu lernen ~
Ich habe versucht herauszufinden, was sich in Java 9 geändert hat
Lesen Sie JSON in Java
Interpreter-Implementierung durch Java
Machen Sie einen Blackjack mit Java
Janken App in Java
Einschränkungsprogrammierung in Java
Setzen Sie Java8 in Centos7
NVL-artiger Typ in Java
Verbinden Sie Arrays in Java
Ich habe zuerst Java touched berührt