J'ai fait l'étalonnage de la caméra OpenCV en Java

introduction

J'avais besoin de quelque chose appelé calibrage de la caméra, alors je l'ai essayé. Remarque: comme je suis autodidacte, il peut contenir des déclarations inexactes.

Qu'est-ce que l'étalonnage de la caméra?

Il existe des formules qui peuvent convertir entre la position spatiale et la position sur l'image, mais cela nécessite des paramètres de caméra. Il existe différents types de paramètres de caméra, qui peuvent être largement divisés en paramètres internes et paramètres externes. De plus, je ne sais pas s'il est inclus dans les paramètres internes, mais il y a aussi un coefficient de distorsion de l'objectif (distorsion).

Paramètres internes

Les paramètres internes sont des "paramètres déterminés par la caméra". ・ Distance de mise au point f ・ Espacement physique des pixels δ u </ sub>, δ v </ sub> -Centre de l'image en coordonnées de l'image par rapport aux coordonnées normalisées c u </ sub>, c v </ sub>

Paramètres externes

Les paramètres externes sont des "paramètres de position et d'orientation de la caméra par rapport au système de coordonnées mondial". ・ Matrice de rotation R 3 </ sub> ・ Vecteur de mouvement parallèle t 3 </ sub>

Qu'est-ce que l'étalonnage de la caméra?

Maintenant, l'étalonnage de la caméra consiste à trouver les paramètres de cette caméra. Les paramètres internes et externes obtenus à ce moment sont appelés collectivement matrice de caméra ou matrice de projection en perspective. Déterminez les paramètres en appliquant les points spatiaux dont les positions sont connues à l'avance et les points de projection (c'est-à-dire les coordonnées sur l'image) sur l'image à la formule de la matrice.

Plus précisément, prenez une photo tout en déplaçant la cible d'étalonnage (comme un échiquier). Puisque la longueur de la grille de l'échiquier est connue, la distance entre les points de la grille est connue et sa position dans l'espace est déterminée. (Inversement, il détermine le système de coordonnées du monde) Il obtient également les coordonnées des points de la grille sur l'image. (Acquisition des coordonnées de l'image) Prenez plusieurs images et utilisez la méthode des moindres carrés pour trouver les paramètres.

Référence (référence) Source: "Traitement d'images numériques [nouvelle édition révisée]", l'expression a été modifiée par commodité. Référence: Calibrage de la caméra et reconstruction 3D --OpenCV.jp

Effectuer l'étalonnage de la caméra avec OpenCV

Cette fois, j'ai calibré la caméra avec la planche de poitrine, ce qui, à mon avis, est relativement facile, selon la procédure approximative suivante.

Pour le code, voir OpenCV_CameraCalibration --GitHub S'il vous plaît.

  1. Tenez le plastron (cible d'étalonnage) et prenez une photo tout en le déplaçant.
  2. Déterminez les coordonnées du système de coordonnées mondial et les points de grille dans l'espace
  3. Trouvez les coordonnées des points de grille de la poitrine sur l'image [en utilisant Calib3d.findChessboardCorners ()]
  4. Exécutez Calib3d.calibrateCamera ()
  5. Enregistrez la matrice de caméra retournée et le coefficient de distorsion de l'objectif Le contour ressemble à ceci.

J'expliquerai chacun un peu plus en détail.

Déterminez les coordonnées du système de coordonnées mondial et les points de grille dans l'espace

Réglez arbitrairement le système de coordonnées du monde de sorte que le plan de la cible d'étalonnage plate (planche de poitrine) soit Z = 0. À ce stade, mesurez l'espacement entre les points de la grille et définissez les points en mm. J'appelle ici.

List<Mat> objectPoints = getObjectPoints(outputFindChessboardCorners.size(), patternSize); //Coordonnées tridimensionnelles du coin de l'échiquier(z=0), Pour le nombre d'images capturées.

OpenCV_CameraCalibration_L68 - GitHub

Le contenu de getObjectPoints () est le suivant.

	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); //Nombre de coins à explorer
		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); //Peut-être x, y,z ressemble à ceci.
	}

OpenCV_CameraCalibration_L96 - GitHub

Trouvez les coordonnées des points de la grille de la poitrine sur l'image

J'ai écrit une méthode appelée findChessboardCorners (). L'appel ressemble à ceci:

		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

Le contenu de findChessboardCorners () est le suivant. J'ai utilisé une méthode appelée Calib3d.findChessboardCorners (). De plus, le Mat retourné contient une image que Calib3d.findChessboardCorners () a pu exécuter normalement.

	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); //Nombre de coins à explorer
		MatOfPoint2f corners = new MatOfPoint2f(); // in,Reçoit un vecteur de coordonnées bidimensionnelles du coin détecté.

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

Exécutez Calib3d.calibrateCamera ()

Calib3d.calibrateCamera () avec les coordonnées des points de la grille dans l'espace préparé précédemment et les coordonnées des points de la grille de la poitrine sur l'image obtenue précédemment comme arguments /camera_calibration_and_3d_reconstruction.html#cv-calibratecamera). En outre, cette méthode renvoie les valeurs de la matrice de la caméra et du coefficient de distorsion de l'objectif, créez donc une variable pour les stocker.

		//Que recevoir
		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

Enregistrez la matrice de caméra et le coefficient de distorsion de l'objectif

J'ai la matrice de la caméra et le coefficient de distorsion de l'objectif, mais c'est fastidieux et inutile de le faire à chaque fois, alors sauvegardons les valeurs de la matrice. Dans le cas de C et Python, il y a quelque chose qui entre et sort la valeur Mat du côté OpenCV, mais comme ce n'est pas la version Java, je l'ai fait moi-même cette fois. J'ai utilisé l'entrée / sortie XML trouvée dans la bibliothèque standard Java.

		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

Le contenu de MatIO est OpenCV_CameraCalibration_MatIO.java --GitHub Prière de se référer à.

en conclusion

Pour le moment, en utilisant ceci, [ArUco AR marker posture estimation](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) et cela a bien fonctionné. Je suis heureux que les juniors de notre groupe d'information l'aient également compris et exécuté et y aient réussi.

Lien de référence

OpenCV --Comment effectuer l'étalonnage de l'appareil photo --PynoteCalibrage de l'appareil photo (OpenCV 1.0) --OpenCV.jp

Recommended Posts

J'ai fait l'étalonnage de la caméra OpenCV en Java
Utiliser OpenCV avec Java
J'ai fait une roulette à Java.
J'ai essayé la métaprogrammation avec Java
J'ai envoyé un e-mail en Java
J'ai créé un PDF avec Java.
J'ai fait une annotation en Java.
J'ai essayé d'utiliser JWT en Java
Java + OpenCV 3.X avec IntelliJ IDEA
[java] Ce que j'ai fait en comparant des listes dans ma propre classe
J'ai essayé d'utiliser l'API Elasticsearch en Java
J'ai essayé le nouveau yuan à Java
J'ai essayé d'utiliser OpenCV avec Java + Tomcat
[* Java *] J'ai participé au JJUG CCC 2019 Spring
J'ai créé un programme de jugement des nombres premiers en Java
Détecter des vidéos similaires dans Java et OpenCV rev.2
Utilisez OpenCV_Contrib (ArUco) avec Java! (Partie 1-Construire) (OpenCV-3.4.4)
Partition en Java
Je souhaite envoyer un e-mail en Java.
Je l'ai fait en Java pour toujours rendre (a == 1 && a == 2 && a == 3) vrai
Changements dans Java 11
Je voulais que (a == 1 && a == 2 && a == 3) vrai en Java
J'ai écrit un programme de jugement des nombres premiers en Java
J'ai créé un jeu Janken en Java (CLI)
rsync4j --Je veux toucher rsync en Java.
Détecter des vidéos similaires dans Java et OpenCV rev.3
Ce que j'ai appris en Java (partie 2) Que sont les variables?
J'ai essayé de sortir quatre-vingt-dix-neuf en Java
Ce que j'ai fait lorsque j'ai converti Java en Kotlin
Détecter des vidéos similaires dans Java et OpenCV rev.1
J'ai essayé de créer une compétence Alexa avec Java
J'ai écrit un programme de factorisation prime en Java
Taux circonférentiel à Java
FizzBuzz en Java
J'ai fait un jeu de problèmes de calcul simple en Java
Essayé l'API Toot et Streaming de Mastodon en Java
Je veux faire quelque chose comme "cls" en Java
J'ai écrit sur Java downcast d'une manière facile à comprendre
Je veux aussi utiliser ES2015 avec Java! → (´ ・ ω ・ `)
# 2 [Note] J'ai essayé de calculer quatre-vingt-dix-neuf avec Java.
J'ai essayé de créer une compétence Clova en Java
J'ai essayé de créer une fonction de connexion avec Java
Résolution du problème lorsque Azure Functions a cessé de fonctionner en Java
J'ai essayé d'utiliser l'instruction Extended for en Java
J'ai essayé de passer Java Silver en 2 semaines sans connaître Java
J'ai essayé d'implémenter la méthode de division mutuelle d'Eugrid en Java
~ J'ai essayé d'apprendre la programmation fonctionnelle avec Java maintenant ~
J'ai essayé de découvrir ce qui avait changé dans Java 9
Lire JSON en Java
Implémentation de l'interpréteur par Java
Faites un blackjack avec Java
Application Janken en Java
Programmation par contraintes en Java
Mettez java8 dans centos7
NVL-ish guy en Java
Joindre des tableaux en Java
J'ai d'abord touché Java ②