Utilisez OpenCV_Contrib (ArUco) avec Java! (Partie 2-Programmation)

introduction

Cet article est une partie avant et arrière. Si vous n'avez pas construit la bibliothèque ArUco, Utilisez OpenCV_Contrib (ArUco) en Java! (Partie 1-Build).

De plus, le code source utilisé cette fois-ci est principalement dans OpenCV_ArucoTest [GitHub], donc j'apprécierais que vous y fassiez référence.

Cet article décrit le programme lors de l'utilisation de la bibliothèque ArUco en Java.

Je pensais l'écrire plus tôt, mais j'étais en retard. (J'ai commencé à écrire la veille du réveillon du Nouvel An ...) Pour le moment, je suis inscrit au Calendrier de l'Avent OpenCV 2018. (Qu'avez-vous dit après avoir posté dans la nouvelle année de 2019)

Préparation à l'utilisation d'ArUco avec Eclipse

Suivez la procédure d'importation d'un OpenCV existant avec le fichier jar inclus dans Contrib.

Génération d'image de marqueur

Pour vous assurer que la bibliothèque ArUco est correctement construite et configurée Générons une image Marker.

La fonction à utiliser est ・ Aruco.drawMarker (dictionnaire, markerID, sidePixels, markerImage) dictionnaire: détermine le type de marqueur. La taille, la résolution et le nombre de types de carrés sont différents. markerID: l'ID de marqueur défini dans le dictionnaire, chacun avec une forme différente. sidePixels: détermine la résolution.

Code source ci-dessous (Détails: createMarker [GitHub])

	public static void createMarker() {
		Dictionary dictionary = Aruco.getPredefinedDictionary(Aruco.DICT_4X4_50);

		final int markerID = 0;
		final int sidePixels = 200;
		Mat markerImage = new Mat();
		Aruco.drawMarker(dictionary, markerID, sidePixels, markerImage);

		Imgcodecs.imwrite("F:\\users\\smk7758\\Desktop\\marker_2018-12-01.png ", markerImage);
	}

marker_2018-12-01.png Vous devriez obtenir quelque chose comme ça.

Reconnaissance des marqueurs

Eh bien, c'est la production d'ici.

Les deux fonctions suivantes sont utilisées ・ Aruco.detectMarkers (inputImage, dictionnaire, coins, markerIds, paramètres); ・ Aruco.drawDetectedMarkers (inputImage, coins, markerIds); Eh bien, comme pour la fonction, detectMarkers reconnaît plusieurs marqueurs. Après cela, en utilisant les coins, drawDetectedMarkers fait quelque chose comme tracer les quatre coins de Marker. coins: renvoie les coordonnées à l'écran de Marker. (La raison pour laquelle List est parce qu'il reconnaît plusieurs marqueurs et que Mat est une matrice et peut stocker des coordonnées.)

(Les autres arguments sont omis)

Code source ci-dessous (Détails: detectMarker [GitHub])

	public static void detectMarker() {
		Dictionary dictionary = Aruco.getPredefinedDictionary(Aruco.DICT_4X4_50);

		Mat inputImage = Imgcodecs.imread("F:\\users\\smk7758\\Desktop\\marker_2018-12-01_test.png ");
		List<Mat> corners = new ArrayList<>();
		Mat markerIds = new Mat();
		DetectorParameters parameters = DetectorParameters.create();
		Aruco.detectMarkers(inputImage, dictionary, corners, markerIds, parameters);

		Aruco.drawDetectedMarkers(inputImage, corners, markerIds);

		Imgcodecs.imwrite("F:\\users\\smk7758\\Desktop\\marker_2018-12-01_detected.png ", inputImage);
	}

marker_2018-12-01_test.png Il a été transformé par GIMP, mais dans l'image ci-dessus,

marker_2018-12-01_detected.png Ça devrait ressembler à ça.

Reconnaissance des marqueurs en temps réel à l'aide d'une caméra

Honnêtement, quand je suis arrivé ici, c'était presque l'auto-satisfaction, mais j'ai ensuite combiné JavaFX et VideoCapture (OpenCV) pour effectuer une reconnaissance en temps réel.

La différence est qu'il s'exécute sur JavaFX, donc en utilisant ScheduledService, la valeur renvoyée est de type Image. ScheduledService est une classe utilisée lors du traitement multi-thread avec JavaFX, et il semble que Task puisse être automatiquement restauré. Consultez le JavaDoc officiel pour plus de détails. De plus, la raison du retour avec le type Image est que l'élément qui affiche l'image définie du côté de la classe Controller est l'argument Il s'agit de prendre une image. Pour celui qui convertit de Mat en Image, j'ai utilisé celui qui est sorti après des recherches appropriées.

Code source ci-dessous (Détails: [detectMarkerByCamera --MarkerDetectorService.java [GitHub]](https://github.com/smk7758/OpenCV_ArucoTest/blob/master/test-2018-12-01_OpenCV_Contrib_Aruco_3_BetectMarkcom/rcubith/smk7758/smk/smark/smarc /MarkerDetectorService.java)))

	@Override
	protected Task<Image> createTask() {
		return new Task<Image>() {
			@Override
			protected Image call() throws Exception {
				if (!vc.isOpened()) {
					System.err.println("VC is not opened.");
					this.cancel();
					return null;
				}

				Mat inputImage = new Mat();

				if (!vc.read(inputImage) || inputImage == null) {
					System.err.println("Cannot load camera image.");
					this.cancel();
					return null;
				}

				List<Mat> corners = new ArrayList<>();
				Mat markerIds = new Mat();
				// DetectorParameters parameters = DetectorParameters.create();
				Aruco.detectMarkers(inputImage, dictionary, corners, markerIds);

				Aruco.drawDetectedMarkers(inputImage, corners, markerIds);

				return convertMatToImage(inputImage);
			}
		};
	}

	private Image convertMatToImage(Mat inputImage) {
		MatOfByte byte_mat = new MatOfByte();
		Imgcodecs.imencode(".bmp", inputImage, byte_mat);

		return new Image(new ByteArrayInputStream(byte_mat.toArray()));
	}

SC_test_2018-12-2_21-37-9_No-00.png Ça devrait ressembler à ça.

De plus, [detectMarker (Center) CoordinatesByCamera [GitHub]](https://github.com/smk7758/OpenCV_ArucoTest/blob/master/test-2018-12-01_OpenCV_Contrib_Aruco_3_detectMarkerCoordinates/75kcom8g8githubith/75kcom7g Dans), la fonction côté OpenCV est utilisée pour trouver les coordonnées du centre (centre de gravité) à partir des points aux quatre coins de Marker et dessiner les points.

Estimation de la posture du marqueur en temps réel à l'aide d'une caméra

Enfin, je veux faire le plus, l'estimation de la posture.

Bon, j'aimerais le faire immédiatement, mais en fait il y a quelque chose à faire avant d'estimer la posture. C'est ce qu'on appelle l'étalonnage de la caméra. La fonction suivante ne peut pas être exécutée sans le Mat obtenu ici, donc reportez-vous à J'ai fait l'étalonnage de la caméra OpenCV (Calibrage de la caméra) avec Java. Je veux que tu le fasses. (En fait, il a fallu quelques semaines pour se développer à partir du chapitre précédent. C'est la cause du retard)

Commençons à nouveau par la fonction. ・ Aruco.estimatePoseSingleMarkers (coins, 0.05f, cameraMatrix, distorsionCoefficients, rotationMatrix, translationVectors); ・ Aruco.drawAxis (inputImage, cameraMatrix, distortionCoefficients, rotationMatrix, translationVectors, 0.1f);

Comme son nom l'indique, la fonction ci-dessus estime la posture de Marker et renvoie une matrice de rotation et un vecteur de mouvement parallèle. Et la fonction ci-dessous dessine l'axe, ou axe de coordonnées.

Code source ci-dessous (Détails: [detectMarkerPoseByCamera [GitHub]]]](https://github.com/smk7758/OpenCV_ArucoTest/blob/master/test-2018-12-01_OpenCV_Contrib_Aruco_4_detectMarkerPoseByCamera/sm8/subith/758kcom ))

	List<Mat> corners = new ArrayList<>();
	Mat markerIds = new Mat();
	// DetectorParameters parameters = DetectorParameters.create();
	Aruco.detectMarkers(inputImage, dictionary, corners, markerIds);

	Aruco.drawDetectedMarkers(inputImage, corners, markerIds);

	Mat rotationMatrix = new Mat(), translationVectors = new Mat(); //recevoir
	Aruco.estimatePoseSingleMarkers(corners, 0.05f, cameraMatrix, distortionCoefficients,rotationMatrix, translationVectors);

	for (int i = 0; i < markerIds.size().height; i++) { // TODO
		Aruco.drawAxis(inputImage, cameraMatrix, distortionCoefficients, rotationMatrix, translationVectors, 0.1f);
	}

SC_test_2018-12-31_0-36-22_No-00.png SC_test_2018-12-31_0-36-13_No-00.png SC_test_2018-12-31_0-35-37_No-00.png Ça devrait ressembler à ça.

en conclusion

Cela m'a pris du temps, mais cela a commencé à fonctionner pour le moment. Il était particulièrement difficile de comprendre le calibrage de la caméra ... Je souhaite continuer à me consacrer à la version Java d'OpenCV.

(Je l'ai apprécié à la fin de 2018) [Bien que l'article lui-même ait été écrit au début de 2019]

De plus, puisque cet article est écrit par un débutant, si vous avez des erreurs ou des points négatifs, nous vous serions reconnaissants si vous pouviez commenter ou commenter sur Twitter.

Lien de référence

La formule était la plus simple à comprendre.

Détection de marqueur ArUco (module aruco) --OpenCV officielDétection des marqueurs ArUco - Officiel OpenCVEstimation de pose avec Opencv Aruco Partie 1 - Mémorandum d'apprentissage machineEstimation de pose avec Opencv Aruco Part 2-Mémorandum d'apprentissage automatiqueOpenCV aruco marker - Note personnelle relative au programme ・ [Essayez d'utiliser le module aruco --atinfinity / lab (GitHub)](https://github.com/atinfinity/lab/wiki/aruco%E3%83%A2%E3%82%B8%E3%83%A5 % E3% 83% BC% E3% 83% AB% E3% 82% 92% E4% BD% BF% E3% 81% A3% E3% 81% A6% E3% 81% BF% E3% 82% 8B) ・ Estimation de la position et de l'orientation de la caméra à l'aide de marqueurs (OpenCV + ArUco) -Comment faire un robot volantEnquête sur ArUco, une bibliothèque RA légèrePour moi-même: calibrage de la caméra OpenCV3.4.3

Recommended Posts

Utilisez OpenCV_Contrib (ArUco) avec Java! (Partie 2-Programmation)
Utilisez OpenCV_Contrib (ArUco) avec Java! (Partie 1-Construire) (OpenCV-3.4.4)
Programmation par contraintes en Java
Utiliser OpenCV avec Java
Utiliser PreparedStatement en Java
[Java] Termes de base en programmation
Utilisons Twilio en Java! (Introduction)
[Java] N'utilisez pas "+" dans append!
Utilisez des clés composites dans Java Maps.
Comment utiliser les classes en Java?
Faire une analyse de phrase en Java 8 (partie 2)
Utilisez-vous Stream en Java?
Création d'une analyse de phrase dans Java 8 (partie 1)
Prise en charge multilingue de Java Comment utiliser les paramètres régionaux
[Java] Utiliser la technologie cryptographique avec les bibliothèques standard
Utilisez "Rhino" qui exécute JavaScript en Java
Création d'une classe de matrice dans Java Partie 1
Pensons à ce qu'est la programmation déclarative en Java et Elm (partie 1)
Partition en Java
L'histoire de l'apprentissage de Java dans la première programmation
bases de la programmation Java
Changements dans Java 11
[Java] Utilisation de final dans la déclaration de variable locale
Janken à Java
java pratique partie 1
Programmation générique java
Ce que j'ai appris en Java (partie 2) Que sont les variables?
[JAVA] [Spring] [MyBatis] Utiliser IN () avec SQL Builder
[Java] Utilisez Collectors.collectingAndThen
Taux circonférentiel à Java
FizzBuzz en Java
Programmation utilisant le type de somme directe en Java (news)
[LeJOS] Programmons mindstorm-EV3 avec Java [Construction de l'environnement partie 2]
Un examen rapide de Java appris en classe part4
Je veux aussi utiliser ES2015 avec Java! → (´ ・ ω ・ `)
Ce que j'ai appris en Java (partie 3) Déclaration d'exécution des instructions
Un examen rapide de Java appris en classe part3
Un examen rapide de Java appris en classe part2
[JAVA] [Spring] [MyBatis] Utiliser GROUP BY dans SQL Builder
Utilisation correcte de la classe abstraite et de l'interface en Java
~ J'ai essayé d'apprendre la programmation fonctionnelle avec Java maintenant ~
Remarques sur l'utilisation des expressions régulières en Java
Apprentissage rapide de Java "Introduction?" Partie 3 Parler de programmation
Lire JSON en Java
Implémentation de l'interpréteur par Java
Faites un blackjack avec Java
Application Janken en Java
Mettez java8 dans centos7
NVL-ish guy en Java
Joindre des tableaux en Java
"Hello World" en Java
Interface appelable en Java
Utilisez java.time avec Jackson
Commentaires dans la source Java
Fonctions Azure en Java
Formater XML en Java
Simple htmlspecialchars en Java
Implémentation Boyer-Moore en Java