Détecter des vidéos similaires dans Java et OpenCV rev.1

introduction

J'ai eu la chance de découvrir comment «détecter des images similaires» pendant un moment, et dans le processus, je pensais aux vidéos.

  1. Extraire des images de vidéos
  2. Comparez les images

\(^o^)/

J'ai eu l'idée simple et j'ai décidé d'en faire un peu. ** En développement **

image d'écran image

environnement

Java (Java 9) est utilisé sous Windows et Eclipse est utilisé comme IDE. La création de l'interface graphique est Scene Builder ou JavaFX.

L'installation d'OpenCV crée des fichiers JAR et des DLL. Placez-les dans un endroit où ils peuvent être lus.

→ Copier dans Windows \ System32 \

→ Copier sous le chemin de classe, ajouter depuis Eclipse

De plus, en Java, il était nécessaire de décrire le processus de chargement dans une classe qui utilise OpenCV comme indiqué ci-dessous.

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

Extraire des images de vidéos

Extrayez certaines images de la vidéo sous forme d'images. Ici, j'ai décidé d'extraire 9 images. Il n'y a pas de base particulière, mais c'est un jugement qu'il semble bon lorsqu'il est arrangé en 3x3 avec GUI. Étant donné que la première et la dernière image sont susceptibles d'être assombries, enregistrez 9 images séparées par 10. -> Détection de différence FPS ...?

En outre, toutes les images extraites sont mises à l'échelle de manière à ce que la largeur soit de 200 pixels, puis enregistrées. -> Détection de différence de taille ...?

↓ Cela ressemble à ceci.

	static public VideoMetadata captureFrame(Config config, String videoFile) {
		// ------------------------------------------------------------------
		//Ouvrez la vidéo
		// ------------------------------------------------------------------
		System.out.println(videoFile);
		VideoCapture capture = new VideoCapture(videoFile);
		if (!capture.isOpened()) {
			System.out.println("file not opened.");
			return null;
		}

		String outputDir = config.getTempDir() + "/" + String.valueOf(videoFile.hashCode()).replace("-", "_");
		File dir = new File(outputDir);
		if (!dir.exists()) {
			dir.mkdir();
		}

		// ------------------------------------------------------------------
		//Acquisition d'informations vidéo
		// ------------------------------------------------------------------
		double fps = capture.get(Videoio.CV_CAP_PROP_FPS);
		int resizeHeight = (int) (config.getImageWidth() / capture.get(Videoio.CV_CAP_PROP_FRAME_WIDTH)
				* capture.get(Videoio.CV_CAP_PROP_FRAME_HEIGHT));
		double allFrameCnt = capture.get(Videoio.CV_CAP_PROP_FRAME_COUNT);
		int captureInterval = (int) (allFrameCnt / (config.getCaptureCount() + 1));
		long time = (long) (allFrameCnt / fps);

		// ------------------------------------------------------------------
		//Obtenez le nombre d'images spécifié dans les paramètres
		// ------------------------------------------------------------------
		for (int i = 1; i < config.getCaptureCount() + 1; i++) {
			int frameIndex = captureInterval * i;
			Mat orgFrame = new Mat();
			Mat resizedFrame = new Mat();
			capture.set(Videoio.CV_CAP_PROP_POS_FRAMES, frameIndex - 1);
			if (!capture.read(orgFrame)) {
				continue;
			}
			Imgproc.resize(orgFrame, resizedFrame, new Size(config.getImageWidth(), resizeHeight));
			Imgcodecs.imwrite(outputDir + "/" + i + ".jpg ", resizedFrame);

		}

		VideoMetadata metadata = new VideoMetadata();
		metadata.setFilename(videoFile);
		metadata.setFrameDirname(outputDir);
		metadata.setPlayTime(time);
		return metadata;
	}

Comparer des images

Dans la section précédente, nous avons fait 9 images par vidéo. Cette fois, nous comparerons cela.

Concernant la comparaison des images, j'ai décidé de comparer les histogrammes. Je pense qu'il y a beaucoup de place à considérer à cet égard.

La moyenne des résultats de comparaison de chacune des 9 images a été utilisée comme résultat de comparaison de la vidéo entière.

Le code est ci-dessous.

	static public VideoComparison compareImages(Config config, VideoMetadata video1, VideoMetadata video2) {

		List<Double> histList = new ArrayList<Double>();
		// ------------------------------------------------------------------
		//Comparer par image
		// ------------------------------------------------------------------
		for (int i = 1; i < config.getCaptureCount() + 1; i++) {
			String filename1 = video1.getFrameDirname() + "/" + i + ".jpg ";
			String filename2 = video2.getFrameDirname() + "/" + i + ".jpg ";
			File file1 = new File(filename1);
			File file2 = new File(filename2);
			if (!(file1.exists() && file2.exists())) {
				continue;
			}

			// ------------------------------------------------------------------
			//histogramme
			// ------------------------------------------------------------------
			Mat img1 = Imgcodecs.imread(filename1);
			List<Mat> src1 = new ArrayList<Mat>();
			src1.add(img1);
			Mat hist1 = new Mat();
			Imgproc.calcHist(src1, new MatOfInt(0), new Mat(), hist1, new MatOfInt(256), new MatOfFloat(0, 256));

			Mat img2 = Imgcodecs.imread(filename2);
			List<Mat> src2 = new ArrayList<Mat>();
			src2.add(img2);
			Mat hist2 = new Mat();
			Imgproc.calcHist(src2, new MatOfInt(0), new Mat(), hist2, new MatOfInt(256), new MatOfFloat(0, 256));

			histList.add(Imgproc.compareHist(hist1, hist2, 0));

		}

		VideoComparison videoComparison = new VideoComparison();
		videoComparison.setVideo1(video1);
		videoComparison.setVideo2(video2);
		videoComparison.setHist(calcAvg(histList));
		return videoComparison;
	}

Essayez de le faire GUI

Je veux en faire une interface graphique car elle gère les images. J'étais inquiet, mais j'ai décidé de le faire avec JavaFX pour commémorer la sortie de Java9. (JavaFX est 8 ...)

Dans JavaFX, la mise en page de conception peut être décrite en XML (fxml) et Scene Builder peut la modifier graphiquement. La liaison XML et le code se fait avec l'attribut fx: id en XML et l'annotation @FMXL en .java.

Par exemple, si la commande du bouton d'exécution est organisée comme suit,

<Button fx:id="executeBtn" layoutX="214.0" layoutY="31.0" mnemonicParsing="false" onAction="#doExecuteAction" prefHeight="38.0" prefWidth="115.0" text="execute" />

Du côté du code Java, procédez comme suit:

	@FXML
	void doExecuteAction(ActionEvent event) {
        // ...
    }

Vous pouvez maintenant joindre le processus qui sera exécuté lorsque vous appuyez sur le bouton.

Les commandes et actions utilisées cette fois sont les suivantes.

--Exécuter

finalement

J'ai écrit le code en Java pour la première fois depuis longtemps, mais il y a de nombreux aspects ennuyeux dans l'utilisation personnelle. En fait, je l'ai écrit en Python au début, mais je voulais en faire une interface graphique, que dois-je faire avec les threads et ainsi de suite ... → OpenCV peut aussi être fait avec Java. Alors je l'ai fait Java.

J'ai l'impression que je n'ai pas fait d'interface graphique en Java depuis AWT, mais JavaFX était meilleur que ce à quoi je m'attendais.

Le reste est autour de ce qui suit.

--Visualisation de l'état du traitement

--Mise en place de la barre de progression

--Afficher le journal d'état du traitement

--Comparaison par quantité de fonctionnalités.

--Autre ...?

La programmation des fêtes était amusante. fin.

référence

OpenCV: OpenCV modules

Client Technology: Java Platform, Standard Edition (Java SE) 8 Release 8

JavaFX Scene Builder 1.x Archive

Développement de JavaFX 8 avec Eclipse à l'aide de Designer-Qiita

bitWalk's: JavaFX: ListView avec CheckBox

Recommended Posts

Détecter des vidéos similaires dans Java et OpenCV rev.2
Détecter des vidéos similaires dans Java et OpenCV rev.3
Détecter des vidéos similaires dans Java et OpenCV rev.1
Utiliser OpenCV avec Java
Exemple d'encodage et de décodage en Java
Classe StringBuffer et StringBuilder en Java
Java + OpenCV 3.X avec IntelliJ IDEA
Bonjour tout le monde en Java et Gradle
Différence entre final et immuable en Java
J'ai fait l'étalonnage de la caméra OpenCV en Java
Différence entre les listes d'arry et les listes liées en Java
Programmer les en-têtes et pieds de page PDF en Java
Apprenez les modèles Flyweight et ConcurrentHashMap en Java
La direction de Java dans "C ++ Design and Evolution"
De Java à C et de C à Java dans Android Studio
Lire et écrire des fichiers gzip en Java
Différence entre int et Integer en Java
Discrimination d'énum dans Java 7 et supérieur
Concernant les modificateurs transitoires et la sérialisation en Java
Utilisez OpenCV_Contrib (ArUco) avec Java! (Partie 1-Construire) (OpenCV-3.4.4)
Traitement parallèle et parallèle dans divers langages (édition Java)
Différence entre next () et nextLine () dans Java Scanner
Différences dans l'écriture des classes Java, C # et Javascript
Capture et sauvegarde de l'installation de sélénium en Java
Ajouter, lire et supprimer des commentaires Excel à l'aide de Java
Vérifier le comportement statique et public dans les méthodes Java
[Java] Comprenez en 10 minutes! Tableau associatif et HashMap
Distinguer les nombres positifs et négatifs en Java
Java ajoute et supprime les filigranes dans les documents Word
Représente le «jour suivant» et le «jour précédent» en Java / Android
Questions sur la gestion des exceptions Java throw et try-catch
Télécharger et télécharger des notes en java sur S3
Crypter / décrypter avec AES256 en PHP et Java
Générer OffsetDateTime à partir de Clock et LocalDateTime en Java
Changements dans Java 11
Janken à Java
Java et JavaScript
XXE et Java
Taux circonférentiel à Java
FizzBuzz en Java
[Android / Java] Transition d'écran et traitement de retour par fragments
Convertir JSON et YAML en Java (en utilisant Jackson et SnakeYAML)
Écrivez ABNF en Java et transmettez l'adresse e-mail
Organiser les builds dans des combinaisons C ++ / Java et Win / Linux
Vectoriser et imager les données d'images numériques manuscrites MNIST avec Java
Ecrire une classe en Kotlin et l'appeler en Java
Classes et instances Java comprises dans la figure
Jonction Java et division des cellules de tableau dans un document Word
Ceci et cela pour éditer ini en Java. : inieditor-java
Soustraire les constantes Enum des chaînes et des valeurs en Java
Utilisation correcte de la classe abstraite et de l'interface en Java