/**
   * detection_contours, détecte les contours, les affiches et gères le traitement
   * d'authentification
   *
   * @param inmat : la matrice qui arrive pour la detection de contour
   * @param outmat : la matrice qui sort après les comptours
   */
  public void detection_contours(Mat inmat, Mat outmat) {
    Mat v = new Mat();
    Mat vv = outmat.clone();

    List<MatOfPoint> contours = new ArrayList(); // Tous les contours
    int key; // Plus gros contours
    MatOfInt hullI = new MatOfInt();
    List<MatOfPoint> hullP = new ArrayList<MatOfPoint>();
    Rect r; // Rectangle du plus gros contours

    // Trouve tous les contours
    Imgproc.findContours(vv, contours, v, Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_SIMPLE);
    // Calcul l'indice du plus gros contours
    key = findBiggestContour(contours);
    // S'il y a au moins un contours et le
    if (key != 0) {
      Imgproc.drawContours(inmat, contours, key, new Scalar(0, 0, 255));
      r = Imgproc.boundingRect(contours.get(key));
      Core.rectangle(currentFrame, r.br(), r.tl(), new Scalar(0, 255, 0), 1);
    }

    // Calcul les points convexes de la main
    Imgproc.convexHull(contours.get(key), hullI, false);

    // S'il y a des points de convexion
    if (hullI != null) {
      // Reinitialise les points de convexion
      hullP.clear();

      // On calcule le nombres de points de convexion
      for (int i = 0; contours.size() >= i; i++) hullP.add(new MatOfPoint());

      int[] cId = hullI.toArray();

      // On récupère dans un tableau de points, les points du contours
      Point[] contourPts = contours.get(key).toArray();

      // Réinitialisation des points de recherche dans les tableau
      int findRectA = 0;
      int findRectB = 0;
      int findRectC = 0;
      int findRectD = 0;

      // Pour chaque point de convexion
      for (int i = 0; i < cId.length; i++) {
        // Dessin du point de convexion sur la matrice
        Core.circle(inmat, contourPts[cId[i]], 2, new Scalar(241, 247, 45), -3);

        // Si le point de convexion se trouve dans un des carrés
        //     on incrémente le compteur associé
        if (isInRectangle(rectA, contourPts[cId[i]])) findRectA++;
        else if (isInRectangle(rectB, contourPts[cId[i]])) findRectB++;
        else if (isInRectangle(rectC, contourPts[cId[i]])) findRectC++;
        else if (isInRectangle(rectD, contourPts[cId[i]])) findRectD++;
      }

      // Si on a trouvé la main dans le rectangle A
      if (findRectA >= 5) {
        if (cptRect == 0) {
          numeroRect[cptRect] = 1;
          cptRect++;
          System.out.println("Haut gauche");
        } else {
          if (numeroRect[cptRect - 1] != 1) {
            numeroRect[cptRect] = 1;
            if (cptRect == 3) cptRect = 0;
            else cptRect++;
            System.out.println("Haut gauche");
          }
        }
      }

      // Si on a trouvé la main dans le rectangle B
      if (findRectB >= 5) {
        if (cptRect == 0) {
          numeroRect[cptRect] = 2;
          cptRect++;
          System.out.println("Bas gauche");
        } else {
          if (numeroRect[cptRect - 1] != 2) {
            numeroRect[cptRect] = 2;
            if (cptRect == 3) cptRect = 0;
            else cptRect++;
            System.out.println("Bas gauche");
          }
        }
      }

      // Si on a trouvé la main dans le rectangle C
      if (findRectC >= 5) {
        if (cptRect == 0) {
          numeroRect[cptRect] = 3;
          if (cptRect == 3) cptRect = 0;
          else cptRect++;
          System.out.println("Haut droite");
        } else {
          if (numeroRect[cptRect - 1] != 3) {
            numeroRect[cptRect] = 3;
            if (cptRect == 3) cptRect = 0;
            else cptRect++;
            System.out.println("Haut droite");
          }
        }
      }

      // Si on a trouvé la main dans le rectangle D
      if (findRectD >= 5) {
        if (cptRect == 0) {
          numeroRect[cptRect] = 4;
          cptRect++;
          System.out.println("Bas droite");
        } else {
          if (numeroRect[cptRect - 1] != 4) {
            numeroRect[cptRect] = 4;
            if (cptRect == 3) cptRect = 0;
            else cptRect++;

            System.out.println("Bas droite");
          }
        }
      }

      // Si on a sélectionné 3 fenètres et que cela correspond au mot de passe
      //      MOT DE PASSE : Haut Gauche - Bas Droite - Bas Gauche
      if (cptRect == 3) {
        if ((numeroRect[0] == 1) && (numeroRect[1] == 4) && (numeroRect[2] == 2))
          this.jTextField2.setText("Authenticated");
        // Réinitilisation du compteur
        cptRect = 0;
      }
    }
  }
  public static int identify_R_U(Mat binary) {
    // 0: hull points identified < 2
    // 1: R
    // 2: U
    List<MatOfPoint> contours = new ArrayList<MatOfPoint>();
    List<MatOfPoint> hullPoints = new ArrayList<MatOfPoint>();
    List<Point> hullPointList = new ArrayList<Point>();
    List<Point> filteredPointList = new ArrayList<Point>();
    MatOfPoint hullPointMat = new MatOfPoint();
    MatOfInt hull = new MatOfInt();
    Mat hierarchy = new Mat();

    // Find contour
    Imgproc.findContours(
        binary, contours, hierarchy, Imgproc.RETR_TREE, Imgproc.CHAIN_APPROX_SIMPLE);

    // Find convex hull
    for (int k = 0; k < contours.size(); k++) {
      Imgproc.convexHull(contours.get(k), hull);

      for (int j = 0; j < hull.toList().size(); j++) {
        hullPointList.add(contours.get(k).toList().get(hull.toList().get(j)));
      }

      hullPointMat.fromList(hullPointList);
      hullPoints.add(hullPointMat);
    }

    // Filter hull points. Only hull points relevant to hull classification
    // will remain.
    // Also, count the number of filtered hull points in left and right.
    for (int l = 0; l < hullPointList.size(); l++) {

      if (hullPointList.get(l).y < binary.rows() * 0.25) {

        if (l != hullPointList.size() - 1) {

          if (Math.hypot(
                      hullPointList.get(l).x - hullPointList.get(l + 1).x,
                      hullPointList.get(l).y - hullPointList.get(l + 1).y)
                  / binary.cols()
              > 0.08) {

            filteredPointList.add(hullPointList.get(l));
            // Core.circle(rgb,
            // new Point(UL.x + hullPointList.get(l).x, UL.y
            // + hullPointList.get(l).y), 5,
            // new Scalar(0, 255, 0));
          }
        }
      }
    }

    // Sort points by x axis, increasing
    if (filteredPointList.size() > 1) {
      if (filteredPointList.get(0).x > filteredPointList.get(1).x) {
        Point temp = filteredPointList.get(0);
        filteredPointList.set(0, filteredPointList.get(1));
        filteredPointList.set(1, temp);
      }

      if (filteredPointList.get(0).y > filteredPointList.get(1).y) return 1; // R
      else return 2; // U
    }

    return 0;
  }