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.
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).
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>
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>
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
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.
J'expliquerai chacun un peu plus en détail.
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
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);
}
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
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 à.
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.
・ OpenCV --Comment effectuer l'étalonnage de l'appareil photo --Pynote ・ Calibrage de l'appareil photo (OpenCV 1.0) --OpenCV.jp
Recommended Posts