[PYTHON] Utiliser le fichier d'étalonnage de la caméra avec OpenCvSharp4

introduction

Bonsoir J'ai calibré la caméra WEB en utilisant OpenCvSharp4, je vais donc la laisser en mémoire. Je ne comprends toujours pas la théorie et le raisonnement de l'étalonnage lui-même, donc le code a simplement fonctionné. .. ..

environnement

Caméra WEB: FullHD 1080P (caméra 2 millions de pixels) Création du fichier de calibrage: python (python-opencv) Calcul de la distorsion de l'objectif de l'appareil photo: C # (opencvsharp4.windows)

Création d'un fichier yaml d'étalonnage de caméra avec python

Je voulais vraiment faire des calculs d'étalonnage avec Opencvsharp Il est difficile de détourner les échantillons des 3 séries, et il était peu probable que je puisse rivaliser avec les 4 séries à mon niveau, donc je vais calmement calculer avec python avec des échantillons.

Alors, créez et exécutez le code suivant en vous référant à here. La majeure partie de la partie principale est une copie. .. .. Non, je l'apprécie vraiment.

CalcCalibration.py


import os
import sys
import numpy as np
import cv2
from time import sleep
from datetime import datetime

FILE_NAME = "calib.yml"
#Nombre d'images de référence
REFERENCE_IMG = 40
#La taille d'un côté du carré[cm]
SQUARE_SIZE = 2.0
#Nombre de points d'intersection
PATTERN_SIZE = (8, 13)


def main():
    """
Fonction principale
    :return:
    """
    calc_camera()  #Calculer la distorsion de la caméra


def calc_camera():
    """
Fonction pour calculer la distorsion de la caméra
    :return:
    """
    pattern_points = np.zeros((np.prod(PATTERN_SIZE), 3), np.float32)  #Poitrine (X,Y,Z) Spécification des coordonnées(Z=0)
    pattern_points[:, :2] = np.indices(PATTERN_SIZE).T.reshape(-1, 2)
    pattern_points *= SQUARE_SIZE
    obj_points = []
    img_points = []

    capture = cv2.VideoCapture(0)
    #Spécifiez la résolution
    #Réglez la largeur de l'image de la caméra sur 1920
    capture.set(cv2.CAP_PROP_FRAME_WIDTH, 1920)
    #Réglez la largeur verticale de l'image de la caméra sur 1080
    capture.set(cv2.CAP_PROP_FRAME_HEIGHT, 1080)

    while len(obj_points) < REFERENCE_IMG:
        #Obtenir une image
        ret, img = capture.read()
        height = img.shape[0]
        width = img.shape[1]

        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

        #Détecte les coins de l'échiquier
        ret, corner = cv2.findChessboardCorners(gray, PATTERN_SIZE)
        #S'il y a un coin
        if ret:
            print("detected coner!")
            print(str(len(obj_points) + 1) + "/" + str(REFERENCE_IMG))
            term = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_COUNT, 30, 0.1)
            cv2.cornerSubPix(gray, corner, (5, 5), (-1, -1), term)
            img_points.append(corner.reshape(-1, 2))  #append, méthode: ajoute un objet factor à la fin de la liste
            obj_points.append(pattern_points)

        cv2.imshow('image', img)
        #Attendez 200 ms car il est jugé à chaque fois. C'est ici pour être retardé
        if cv2.waitKey(200) & 0xFF == ord('q'):
            break

    print("calculating camera parameter...")
    #Calculer les paramètres internes
    rms, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(obj_points, img_points, gray.shape[::-1], None, None)

    #Afficher le résultat du calcul
    print("RMS = ", rms)
    print("mtx = \n", mtx)
    print("dist = ", dist.ravel())

    #Enregistrer dans yml
    f = cv2.FileStorage(FILE_NAME, flags=1)
    f.write('mtx', mtx)
    f.write('dist', dist)
    # f.write('translation', rvecs)
    # f.write('distortion', tvecs)
    f.release()


if __name__ == '__main__':
    main()

Le nombre d'images de référence, la taille d'un côté du carré, le nombre de points d'intersection et les paramètres de résolution de la caméra Réglez en fonction de l'environnement. Cette fois, j'ai créé [ici](https://drive.google.com/file/d/1A56mjyobKN3cLkFkPgokO8qCoDXUdXIC/view?usp=sharing), je l'ai imprimé au format A4 et je l'ai utilisé sur un tableau en plastique. Étant donné qu'un côté du carré mesure 20 mm, il mesure 2,0 cm et les points d'intersection sont 8 dans la direction horizontale et 13 dans la direction verticale. Le calcul de la distorsion est effectué tout en se déplaçant uniformément comme indiqué dans ↓. ![img_20200401012008.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/168779/fe2471c8-f19c-d3da-44e6-82e2ab4cb49a.jpeg) ![img_20200401012013.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/168779/6abf5305-4be0-2c42-4ab7-7d3b7aa234b7.jpeg) ![img_20200401012017.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/168779/390faef9-27ed-1da9-1faf-8445a2821ff1.jpeg)

Si les coins de 40 échiquiers peuvent être détectés, la distorsion sera calculée. Vous pouvez vérifier le résultat comme indiqué ci-dessous. En même temps, vous pouvez voir que "calib.yml" est sorti. image.png

calib.yml


%YAML:1.0
---
mtx: !!opencv-matrix
   rows: 3
   cols: 3
   dt: d
   data: [ 7.7958988893525259e+02, 0., 9.8266449367809537e+02, 0.,
       7.7847873908657630e+02, 5.7636196300911377e+02, 0., 0., 1. ]
dist: !!opencv-matrix
   rows: 1
   cols: 5
   dt: d
   data: [ -1.8378651673412880e-01, 4.1014929211162864e-02,
       -1.2046811513395908e-03, -4.8516056956278577e-04,
       -4.8595996923656995e-03 ]

Lisez le fichier yaml avec OpenCvSharp4 et effectuez une correction de distorsion

Tout d'abord, installez opencvsharp. Pour une raison quelconque, OpenCvSharp4 sur la face supérieure a provoqué une erreur de chargement de DLL au moment de l'exécution. Installez OpenCvSharp4.WIndows.

image.png Une fois l'installation terminée, préparez "calib.yml" et une image pour vérification. Exécutez le code ci-dessous.

Program.cs


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenCvSharp;

namespace CameraCalibrationSample
{
    class Program
    {
        static void Main(string[] args)
        {
            const string ImagePath = @"./img/";
            const string YamlFilePath = @"calib.yml";

            // (1)Image d'étalonnage(Avant correction)Chargement
            string[] imagePaths = System.IO.Directory.EnumerateFiles(ImagePath, "*", System.IO.SearchOption.AllDirectories).ToArray();
            int imageNum = imagePaths.Length;

            Mat[] srcImg = new Mat[imageNum];
            for (int i = 0; i < imageNum; i++)
            {
                srcImg[i] = Cv2.ImRead(imagePaths[i], ImreadModes.Color);
                Mat src = Cv2.ImRead(imagePaths[i], ImreadModes.Color);

                //Lire le fichier yml et obtenir les paramètres de calcul
                using (var fs = new FileStorage(YamlFilePath, FileStorage.Mode.Read))
                {
                    var mtx = fs["mtx"].ReadMat();
                    var dist = fs["dist"].ReadMat();

                    Mat calib = new Mat();
                    Cv2.Undistort(src, calib, mtx, dist);
                    Cv2.ImShow("src", srcImg[i]);
                    Cv2.ImShow("calib", calib);
                    OpenCvSharp.Cv2.WaitKey(0);
                }
            }

            Cv2.DestroyAllWindows();
        }
    }
}

Si le calcul de la distorsion fonctionne bien, il ressemblera à ↓. ・ Avant correction image.png

· Après correction image.png

Vous pouvez voir que cela a été corrigé correctement. Tu l'as fait! (^ O ^)

À la fin

Il y a pas mal de différences dans le code entre la 3ème et la 4ème série, et même si j'essayais de réécrire l'échantillon de l'ancienne version avec 4, le seuil était élevé. .. .. Il existe des exemples de sources de C ++ et de python sur le site officiel de l'OpenCV original, mais il m'est assez difficile de les remplacer par C #. Cette fois, j'ai renoncé à écrire la partie calcul en C # et j'ai décidé de l'écrire en C # uniquement là où les paramètres de correction sont utilisés. Même ainsi, cela a pris beaucoup de temps car la façon d'écrire le stockage de fichiers était assez différente entre les séries 3 et 4. Si vous regardez Wiki correctement, vous pouvez le voir immédiatement, mais il a fallu beaucoup de temps pour le remarquer car je ne chassais que 3 échantillons de la série. J'aurais dû enquêter correctement.

Source de référence

Merci pour l'URL ci-dessus. https://qiita.com/ReoNagai/items/5da95dea149c66ddbbdd https://github.com/shimat/opencvsharp/wiki/FileStorage https://stackoverrun.com/ja/q/11850575 http://hima-tubusi.blogspot.com/2016/02/opencvsharp_3.html https://qiita.com/Kazuhito/items/cc6b8a0bd75cf9689bf9 https://www.learnopencv.com/camera-calibration-using-opencv/

Recommended Posts

Utiliser le fichier d'étalonnage de la caméra avec OpenCvSharp4
Utiliser la caméra Point Grey avec Python (PyCapture2)
Calibrage de la caméra
Calibrage et utilisation de la caméra avec opencv-python [méthode chang]
Utilisez mecab-ipadic-neologd avec igo-python
Utiliser ansible avec cygwin
Utiliser pipdeptree avec virtualenv
[Python] Utiliser JSON avec Python
Utilisez Mock avec pytest
Utiliser l'indicateur avec pd.merge
Opération de fichier avec open - "../"
Utiliser Gentelella avec Django
Utiliser mecab avec Python 3
Utiliser tensorboard avec Chainer
Utiliser DynamoDB avec Python
Utiliser pip avec MSYS2
Utilisez Python 3.8 avec Anaconda
Utiliser les droits d'auteur avec Spacemacs
Téléchargement de fichiers avec django
Utiliser python avec docker
Utiliser TypeScript avec django-compresseur
Utilisez LESS avec Django
Utiliser MySQL avec Django
[Windows] [Python] Calibrage de la caméra de l'objectif fisheye avec OpenCV
Comprendre visuellement l'étalonnage de la caméra
Utiliser Enum avec SQLAlchemy
Utiliser tensorboard avec NNabla
Utiliser le GPS avec Edison
Utilisez nim avec Jupyter
Utiliser l'API Trello avec python
Utiliser la mémoire partagée avec une bibliothèque partagée
Utiliser des balises personnalisées avec PyYAML
Utiliser des graphiques directionnels avec networkx
Utiliser TensorFlow avec Intellij IDEA
Utiliser l'API Twitter avec Python
Utiliser pip avec Jupyter Notebook
Capture de caméra avec Python + OpenCV
Dessiner un fichier netCDF avec python
Utiliser DATE_FORMAT avec le filtre SQLAlchemy
Utiliser TUN / TAP avec Python
Transfert de fichiers rapide avec tissu
Utiliser SSL avec Celery + Redis
Utiliser Cython avec Jupyter Notebook
Utilisez Maxout + CNN avec Pylearn2
Utilisez WDC-433SU2M2 avec Manjaro Linux
Utilisez OpenBLAS avec numpy, scipy
Utiliser l'API subsonique avec python3
Téléchargement de fichiers avec Flask + jQuery
Utilisation de Sonicwall NetExtener avec Systemd
Télécharger le fichier csv avec python
Utilisez prefetch_related commodément avec Django
Créer un fichier xlsx avec XlsxWriter
Utiliser l'interpréteur AWS avec Pycharm
Utilisation de Bokeh avec IPython Notebook
Utiliser une plage de type Python avec Rust