J'ai essayé d'utiliser OpenCV avec Java + Tomcat

Cet article est le deuxième jour de l'équipe Web Calendrier de l'Avent 2017. Hier était "Implémenter CRUD avec PlayFramework 2.6.7, play-slick 3.0.2 (Slick 3.2)" de @ kouares.

** Introduction **

@Hahegawa sera en charge de la deuxième journée. Je vous remercie.

Aperçu

«Dans mon travail, j'ai eu l'opportunité de vouloir détecter un objet à partir d'une image, j'ai donc essayé OpenCV. --En ce qui concerne OpenCV, il existe de nombreux exemples d'implémentation et explications en Python et C ++ dans les rues, mais compte tenu de la maintenance pour un usage professionnel, j'ai pensé que ce serait bien si cela pouvait être fait en Java, alors je l'ai essayé en Java.

** Supposition **

―― J'ai essayé la "détection de fonction" et la "correspondance de fonction".

environnement

C'est un peu vieux, mais je l'ai essayé dans l'environnement suivant. ・ Windows 10 ・ Oxygène Eclipse ・ OpenCV3.1 ・ Apache Tomcat 7.0

** Construction du projet **

    1. Installation d'Eclipse et création de projet Omis dans cet article
  1. Télécharger la bibliothèque OpenCV À partir de la page suivante, téléchargez et décompressez la bibliothèque Ver que vous souhaitez utiliser dans un emplacement approprié      https://opencv.org/releases.html アドベントカレンダー1-min.png

    1. Ajout de variables d'environnement système Windows Ajoutez le dossier sous "\ build \ java " dans le dossier décompressé dans Path アドベントカレンダー2-min.png

4. Faites un clic droit sur le projet Eclipse → Définir le chemin de construction dans Propriétés アドベントカレンダー3-min.png

  1. Ajouter une bibliothèque utilisateur Lors de l'ajout, définissez le même chemin que 3 vers l'emplacement de la bibliothèque native アドベントカレンダー4-min.png

6. Ajouter une configuration d'exécution Lors de l'exécution d'OpenCV en supposant une application Web, définissez 5 sur le chemin de classe de la configuration d'exécution. Ajouter la même bibliothèque utilisateur アドベントカレンダー5-min.png

  1. Création de code source En suivant la procédure de traitement suivante, des points caractéristiques ont été détectés et mis en correspondance à partir de l'image. (1) Lisez l'image et stockez-la dans la classe BufferedImage (2) Conversion de la classe BufferedImage en classe Mat → Lors du traitement d'une image avec la méthode de la bibliothèque OpenCV Fondamentalement en utilisant cette classe Mat (3) Génération de détecteur de fonction → Cette fois, utilisez AKAZE (4) Exécution de la détection des fonctionnalités + vérification croisée → La précision de détection sera plus élevée si le processus de contre-vérification est ajouté. Le temps de traitement et la charge augmenteront, c'est donc un sujet de préoccupation (5) Dessinez le résultat de la détection du point caractéristique

(2)~(5)Code source


  //Conversion de tapis de l'image envoyée depuis l'écran
  Mat src = new Mat(bufImg.getHeight(), bufImg.getWidth(), CvType.CV_8UC3);
  byte[] bufImgBinary = ((DataBufferByte)bufImg.getRaster().getDataBuffer()).getData();
  src.put(0, 0, bufImgBinary);

  //Conversion de tapis de l'image modèle utilisée pour la détection des caractéristiques
  Mat tempSrc = new Mat(tmpImg.getHeight(), tmpImg.getWidth(), CvType.CV_8UC3);
  byte[] tempImgBinary = ((DataBufferByte)tmpImg.getRaster().getDataBuffer()).getData();
  tempSrc.put(0, 0, tempImgBinary);

  //Conversion de l'échelle de gris pour la détection des caractéristiques
  Mat srcGray = new Mat(bufImg.getHeight(), bufImg.getWidth(), CvType.CV_8UC1);
  Imgproc.cvtColor(src, srcGray, Imgproc.COLOR_BGR2GRAY);
  Core.normalize(srcGray, srcGray, 0, 255, Core.NORM_MINMAX);
  Mat tempSrcGray = new Mat(tmpImg.getHeight(), tmpImg.getWidth(), CvType.CV_8UC1);
  Imgproc.cvtColor(tempSrc, tempSrcGray, Imgproc.COLOR_BGR2GRAY);
  Core.normalize(tempSrcGray, tempSrcGray, 0, 255, Core.NORM_MINMAX);

  MatOfKeyPoint keyPointSrc = new MatOfKeyPoint();
  MatOfKeyPoint keyPointTemp = new MatOfKeyPoint();
  Mat descriptersSrc = new Mat(src.rows(), src.cols(), src.type());
  Mat descriptersBase = new Mat(tempSrc.rows(), tempSrc.cols(), tempSrc.type());

  //Détecteur de caractéristiques génération 1
  FeatureDetector akazeDetector = FeatureDetector.create(FeatureDetector.AKAZE);
  DescriptorExtractor akazeExtractor = DescriptorExtractor.create(DescriptorExtractor.AKAZE);
  akazeDetector.detect(srcGray, keyPointSrc);  
  akazeDetector.detect(tempSrcGray, keyPointTemp);
  akazeExtractor.compute(srcGray, keyPointSrc, descriptersSrc);  
  akazeExtractor.compute(tempSrcGray, keyPointTemp, descriptersBase);

  //Détecteur de caractéristiques génération 2
  DescriptorMatcher matcher = DescriptorMatcher.create(DescriptorMatcher.BRUTEFORCE);

  MatOfDMatch matche = new MatOfDMatch();
  List<MatOfDMatch> matches = new ArrayList<MatOfDMatch>();
  List<DMatch> dmatch = new ArrayList<DMatch>();

  //Caractéristiques Vérification croisée disponible
  if(CROSS_CHECK_FLG){

    MatOfDMatch srcToBase = new MatOfDMatch();
    MatOfDMatch baseToSrc = new MatOfDMatch();
    
    matcher.match(descriptersSrc, descriptersBase, srcToBase);
    matcher.match(descriptersBase, descriptersSrc, baseToSrc);

    List<DMatch> ldm_srcToBase = srcToBase.toList();
    List<DMatch> ldm_baseToSrc = baseToSrc.toList();

    for(int i=0; i<ldm_srcToBase.size(); i++) {

      DMatch forward = ldm_srcToBase.get(i);
      DMatch backward = ldm_baseToSrc.get(forward.trainIdx);

      if(backward.trainIdx == forward.queryIdx){
        dmatch.add(forward);
      }

    }

    matche.fromList(dmatch);

  }
  //Aucune vérification croisée
  else{

    System.out.println("Caractéristiques Exécution de contrôle normal");
    matcher.match(descriptersSrc, descriptersBase, matche);

  }

  Mat matchResult = new Mat(src.rows()*2, src.cols()*2, src.type());
  Features2d.drawMatches(src, keyPointSrc, tempSrc, keyPointTemp, matche, matchResult);
  //↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ Sortie d'image de vérification ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
  BufferedImage image = ImageConverter.convertMToBI(matchResult);
  File ouptut = new File("C:\\testlog\\sample_20171202.jpg ");
  ImageIO.write(image, "jpg", ouptut);

Chargement de la bibliothèque OpenCV


  static{
    System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
  }

** Résultat d'exécution **

Bien qu'une mauvaise reconnaissance ait été constatée, les caractéristiques ont pu être détectées. 6-min

** Ce que j'ai pensé faire **

――Il m'a fallu beaucoup de temps pour écrire le code car il était lent, mais si vous êtes rapide à trouver ou à écrire le code, vous pouvez facilement traiter l'image si vous comprenez les bases et les explications des différentes méthodes décrites dans cet article. J'ai senti que je pouvais le faire. ――Lors de la planification de votre entreprise, ce que vous voulez vraiment utiliser est "ce qu'il faut faire avant la détection des fonctionnalités", alors lisez cet article et concentrez-vous sur le traitement que vous voulez vraiment mettre en œuvre sans effort supplémentaire. J'apprécierais si vous le pouviez.

Demain, c'est @wc_moriyama. Je vous remercie.

Recommended Posts

J'ai essayé d'utiliser OpenCV avec Java + Tomcat
J'ai essayé d'utiliser Java REPL
J'ai essayé d'utiliser JOOQ avec Gradle
J'ai essayé d'interagir avec Java
J'ai essayé la communication UDP avec Java
J'ai essayé d'utiliser l'API Java8 Stream
J'ai essayé d'utiliser JWT en Java
J'ai essayé d'utiliser le mémo Java LocalDate
J'ai essayé d'utiliser Google HttpClient de Java
[Java] J'ai essayé de me connecter en utilisant le pool de connexion avec Servlet (tomcat) & MySQL & Java
J'ai essayé d'utiliser la bibliothèque CameraX avec Android Java Fragment
J'ai essayé d'utiliser l'API Elasticsearch en Java
J'ai essayé d'utiliser Realm avec Swift UI
J'ai essayé d'utiliser Scalar DL avec Docker
J'ai essayé d'utiliser OnlineConverter avec SpringBoot + JODConverter
J'ai essayé d'utiliser Gson
J'ai essayé d'utiliser TestNG
J'ai essayé d'utiliser Galasa
J'ai essayé de faire une authentification de base avec Java
J'ai essayé de casser le bloc avec java (1)
J'ai essayé DI avec Ruby
J'ai essayé d'implémenter TCP / IP + BIO avec JAVA
[Java 11] J'ai essayé d'exécuter Java sans compiler avec javac
J'ai essayé de faire fonctionner SQS en utilisant AWS Java SDK
J'ai essayé d'utiliser azure cloud-init
J'ai essayé Drools (Java, InputStream)
J'ai essayé d'utiliser Log4j2 sur un serveur Java EE
J'ai essayé d'utiliser Apache Wicket
J'ai essayé OCR de traiter un fichier PDF avec Java
Utilisation de Mapper avec Java (Spring)
J'ai essayé d'implémenter Sterling Sort avec Java Collector
J'ai essayé d'utiliser l'instruction Extended for en Java
J'ai essayé UPSERT avec PostgreSQL.
J'ai essayé BIND avec Docker
J'ai essayé de gratter un graphique boursier en utilisant Java (Jsoup)
J'ai essayé la métaprogrammation avec Java
J'ai essayé de créer un environnement de développement java8 avec Chocolatey
J'ai essayé de moderniser une application Java EE avec OpenShift.
J'ai essayé d'utiliser Dapr en Java pour faciliter le développement de microservices
J'ai essayé OCR de traiter un fichier PDF avec Java part2
J'ai essayé de démarrer avec Swagger en utilisant Spring Boot
J'ai essayé d'utiliser anakia + Jing maintenant
Installez Java et Tomcat avec Ansible
J'ai essayé d'utiliser Spring + Mybatis + DbUnit
J'ai essayé l'analyse morphologique avec MeCab
Essayez d'utiliser Redis avec Java (jar)
Activez OpenCV avec java8. (Pour moi-même)
J'ai essayé le framework Java "Quarkus"
Utilisation de Java avec AWS Lambda-Eclipse Préparation
Ce que j'ai appris avec Java Gold
Développement HTML5 par Java avec TeaVM
J'ai essayé GraphQL avec Spring Boot
J'ai essayé de résumer l'apprentissage Java (1)
[Android] J'ai essayé d'utiliser la disposition du coordinateur.
J'ai essayé Flyway avec Spring Boot
J'ai essayé d'utiliser le conteneur Pari gp
Ce que j'ai appris avec Java Silver
J'ai essayé d'utiliser WebAssembly Stadio (version 2018/4/17)
J'ai essayé de résumer Java 8 maintenant
Utilisation du service proxy avec l'exploration Java