Nous y travaillons encore.
Détection de vidéos similaires en Java et OpenCV rev.1 --Qiita
Détection de vidéos similaires en Java et OpenCV rev.2 --Qiita
En enregistrant le résultat pour le fichier qui a été traité une fois, le traitement d'image n'est pas effectué par OpenCV pour la deuxième fois.
Le tapis de l'image doit être enregistré en tant qu'image par imwrite, mais le résultat du calcul de l'histogramme, etc. n'a pas pu être enregistré par imwrite et lu par imread.
Il existe un moyen générique d'enregistrer Mat dans un fichier en C ++, mais il semble que vous deviez le créer vous-même car il n'y a rien d'encapsulé en Java.
Puisque Mat est une matrice, c'est-à-dire des données matricielles, elle peut être exprimée verticalement, horizontalement et sous forme de tableau de données. Dans le cas de Mat, en plus de cela, il aura un code de type qui représente le type de données.
À cette fin, la quantité de données n'est pas si grande, je vais donc la sauvegarder en tant que données json. J'ai utilisé la bibliothèque gson de google pour gérer json.
C'est la partie de sauvegarde.
/**
*Enregistrer le tapis dans un fichier
* @param filename
* @param mat
* @throws IOException
*/
public static void storeMat(String filename, Mat mat) throws IOException {
String jsondata = matToJson(mat);
PrintWriter writer = new PrintWriter(new BufferedWriter(new FileWriter(new File(filename))));
writer.write(jsondata);
writer.close();
}
/**
*Convertir Mat au format Json
* @param mat
* @return
*/
public static String matToJson(Mat mat) {
JsonObject obj = new JsonObject();
if (mat.isContinuous()) {
int cols = mat.cols();
int rows = mat.rows();
int elemSize = (int) mat.elemSize();
int type = mat.type();
String typeStr = CvType.typeToString(type);
int dataSize = cols * rows * elemSize;
if (rows == 0) {
dataSize = cols * elemSize;
}
String dataString = "";
if (typeStr.contains("32F")) {
float[] data = new float[dataSize];
String[] strData = new String[dataSize];
mat.get(0, 0, data);
for (int i = 0; i < data.length; i++) {
strData[i] = String.valueOf(data[i]);
}
dataString = String.join(",", strData);
} else if (typeStr.contains("8U")) {
byte[] data = new byte[dataSize];
String[] strData = new String[dataSize];
mat.get(0, 0, data);
for (int i = 0; i < data.length; i++) {
strData[i] = String.valueOf(data[i]);
}
dataString = String.join(",", strData);
}
obj.addProperty("rows", mat.rows());
obj.addProperty("cols", mat.cols());
obj.addProperty("type", mat.type());
obj.addProperty("data", dataString);
Gson gson = new Gson();
String json = gson.toJson(obj);
return json;
} else {
System.err.println("");
}
return "{}";
}
Ceci est la partie lecture.
/**
*Lire le tapis à partir d'un fichier
* @param filename
* @return
* @throws IOException
*/
public static Mat loadMat(String filename) throws IOException {
InputStream input = new FileInputStream(filename);
int size = input.available();
byte[] buffer = new byte[size];
input.read(buffer);
input.close();
return matFromJson(new String(buffer));
}
/**
*Créer un tapis à partir de Json
* @param json
* @return
*/
public static Mat matFromJson(String json) {
JsonParser parser = new JsonParser();
JsonObject JsonObject = parser.parse(json).getAsJsonObject();
int rows = JsonObject.get("rows").getAsInt();
int cols = JsonObject.get("cols").getAsInt();
int type = JsonObject.get("type").getAsInt();
String typeStr = CvType.typeToString(type);
String dataString = JsonObject.get("data").getAsString();
Mat mat = new Mat(rows, cols, type);
String[] splitedStr = dataString.split(",");
if (typeStr.contains("32F")) {
float[] data = new float[splitedStr.length];
for (int i = 0; i < data.length; i++) {
data[i] = Float.parseFloat(splitedStr[i]);
}
mat.put(0, 0, data);
} else if (typeStr.contains("8U")) {
byte[] data = new byte[splitedStr.length];
for (int i = 0; i < data.length; i++) {
data[i] = Byte.parseByte(splitedStr[i]);
}
mat.put(0, 0, data);
} else {
System.err.println("");
}
return mat;
}
Le type Mat est uniquement pour 8U et 32F, et c'est un peu exagéré pour un usage général. Si nécessaire, comme 64F → double, il est nécessaire d'ajouter pour chaque type.
Python (pandas) est supérieur dans la gestion des matrices et json ici.
Je l'ai enregistré en tant que fichier de propriétés à l'aide de java.util.Properties.
Properties videoProperty = new Properties();
videoProperty.setProperty("playtime", String.valueOf(time));
videoProperty.setProperty("width", String.valueOf(width));
videoProperty.setProperty("height", String.valueOf(height));
videoProperty.setProperty("fps", String.valueOf(fps));
videoProperty.setProperty("size", String.valueOf(fileSize));
videoProperty.store(new FileOutputStream(metadata.getMetaFilename()), "");
Au début, j'essayais de l'enregistrer en CSV, mais j'ai finalement décidé de l'enregistrer dans SQLite. J'ai abandonné le CSV car il y a plusieurs bibliothèques et je n'ai pas pu obtenir celle que j'ai choisie correctement.
La table créée.
CREATE TABLE IF NOT EXISTS compare_video (
key text PRIMARY KEY,
file1 text,
file2 text,
timediff integer,
hist real,
feature real,
skip integer
)
J'ai préparé un champ appelé "sauter" ici. Il s'agit d'un indicateur qui indique que ce résultat de comparaison est exclu du résultat et est défini lorsqu'il est jugé qu'il est différent lors de l'inspection visuelle, ou lorsque le temps de lecture est différent de 10% ou plus.
Ce qui suit a été ajouté pour faciliter l'utilisation.
--Afficher les métadonnées sur l'étiquette --Bouton pour déplacer la sélection de résultats de haut en bas --Bouton pour masquer le résultat du suivant --Bouton jouer
Pour la lecture, je souhaite le démarrer avec l'application associée, mais cela ne fonctionne pas ... Pour le moment, j'essaye de le démarrer avec une application fixe.
L'écran après le changement.
Le sens du design est délicat. ..
N'oubliez pas d'appeler fréquemment Mat # release lorsque vous traitez un grand nombre d'images. Surtout dans le cas de Java, les ressources de l'objet Mat qui semble alloué par JNI ne sont pas visibles, donc soyez particulièrement prudent.
La même chose est vraie pour la capture vidéo.
Lorsque je créais un grand nombre de fichiers, l'utilisation du processeur était élevée, mais la cause était un logiciel antivirus. Il semble préférable de le définir de manière à désactiver la recherche en temps réel du dossier cible.
OpenCV Mat object serialization in java - Stack Overflow
Recommended Posts