PointTrackApp / src /stores /annotationStore.js
2nzi's picture
first commit
b4f9490 verified
// Dans un store Pinia (stores/annotationStore.js)
import { defineStore } from 'pinia'
import { v4 as uuidv4 } from 'uuid'
export const useAnnotationStore = defineStore('annotations', {
state: () => ({
// Session courante avec métadonnées vidéo
currentSession: {
id: 'session-1',
name: 'Session d\'annotation',
videoId: null,
video: null, // Nom du fichier vidéo
metadata: {
duration: 0,
width: 0,
height: 0,
fps: 30,
date: new Date().toISOString()
}
},
// Dictionnaire des objets
objects: {
// Format: "1": { id: "1", name: "Objet 1", color: "#4f056f" }
},
// Compteur pour les IDs d'objets
objectIdCounter: 1,
// Annotations par frame
frameAnnotations: {}, // Format: {
// "0": [
// {
// id: "uuid",
// objectId: "1",
// type: "mask",
// mask: "base64...",
// maskScore: 0.91,
// maskImageSize: { width: 1920, height: 1080 },
// points: [{ x: 1270, y: 405, type: "positive" }]
// },
// {
// id: "uuid",
// objectId: "2",
// type: "rectangle",
// x: 100,
// y: 100,
// width: 200,
// height: 150
// }
// ]
// }
selectedObjectId: null,
temporaryPoints: []
}),
getters: {
getTemporaryPointsForObject: (state) => (objectId) => {
return state.temporaryPoints.filter(point => point.objectId === objectId)
}
},
actions: {
// Sélectionner un objet
selectObject(objectId) {
this.selectedObjectId = objectId
console.log(`Objet sélectionné: ${objectId}`)
},
// Désélectionner l'objet actuel
deselectObject() {
this.selectedObjectId = null
},
// Mettre à jour les métadonnées de la vidéo
updateVideoMetadata(metadata) {
this.currentSession.metadata = {
...this.currentSession.metadata,
...metadata
}
},
// Ajouter une annotation pour l'objet sélectionné à la frame actuelle
addAnnotation(frameNumber, annotation) {
const id = uuidv4()
let newAnnotation
if (annotation.type === 'mask') {
newAnnotation = {
id,
objectId: this.selectedObjectId,
type: 'mask',
mask: annotation.mask || '',
maskScore: annotation.maskScore || 0,
maskImageSize: annotation.maskImageSize || {
width: this.currentSession.metadata.width,
height: this.currentSession.metadata.height
},
points: annotation.points || []
}
} else if (annotation.type === 'rectangle') {
newAnnotation = {
id,
objectId: this.selectedObjectId,
type: 'rectangle',
x: annotation.x,
y: annotation.y,
width: annotation.width,
height: annotation.height
}
} else if (annotation.type === 'point') {
newAnnotation = {
id,
objectId: this.selectedObjectId,
type: 'point',
x: annotation.x,
y: annotation.y,
pointType: annotation.pointType // 'positive' ou 'negative'
}
} else {
// Gestion par défaut pour les autres types
newAnnotation = {
id,
objectId: this.selectedObjectId,
...annotation
}
}
// Vérifier que newAnnotation a été créée
if (!newAnnotation) {
console.error('Erreur: impossible de créer l\'annotation', annotation)
return null
}
if (!this.frameAnnotations[frameNumber]) {
this.frameAnnotations[frameNumber] = []
}
this.frameAnnotations[frameNumber].push(newAnnotation)
console.log('Annotation ajoutée:', newAnnotation)
return id
},
updateAnnotation(frameNumber, annotationId, updates) {
if (!this.frameAnnotations[frameNumber]) return
const annotationIndex = this.frameAnnotations[frameNumber].findIndex(
a => a.id === annotationId
)
if (annotationIndex === -1) return
// Mettre à jour l'annotation avec les nouvelles propriétés
this.frameAnnotations[frameNumber][annotationIndex] = {
...this.frameAnnotations[frameNumber][annotationIndex],
...updates
}
},
// Ajouter un nouvel objet
addObject(objectData = {}) {
const objectId = `${this.objectIdCounter++}`
this.objects[objectId] = {
id: objectId,
name: objectData.name || `Objet ${this.objectIdCounter - 1}`,
color: objectData.color || this.getRandomColor(),
// Autres propriétés selon vos besoins
}
// Sélectionner automatiquement le nouvel objet
this.selectObject(objectId)
return objectId
},
// Récupérer les annotations pour une frame
getAnnotationsForFrame(frameNumber) {
return this.frameAnnotations[frameNumber.toString()] || []
},
// Supprimer une annotation
removeAnnotation(frameNumber, annotationId) {
const frameKey = frameNumber.toString()
if (this.frameAnnotations[frameKey]) {
this.frameAnnotations[frameKey] = this.frameAnnotations[frameKey]
.filter(a => a.id !== annotationId)
}
},
// Nouvelle méthode pour supprimer tous les masques d'un objet sur une frame
removeMasksForObject(frameNumber, objectId) {
const frameKey = frameNumber.toString()
if (this.frameAnnotations[frameKey]) {
this.frameAnnotations[frameKey] = this.frameAnnotations[frameKey]
.filter(a => !(a.objectId === objectId && a.type === 'mask'))
}
},
// Vérifier si un objet a encore des annotations sur une frame
hasAnnotationsForObject(frameNumber, objectId) {
const frameKey = frameNumber.toString()
if (!this.frameAnnotations[frameKey]) return false
return this.frameAnnotations[frameKey]
.some(a => a.objectId === objectId)
},
// Générer une couleur aléatoire
getRandomColor() {
return '#' + Math.floor(Math.random()*16777215).toString(16).padStart(6, '0')
},
// Sauvegarder les annotations dans le format demandé
saveAnnotations() {
const data = {
video: this.currentSession.video,
metadata: this.currentSession.metadata,
objects: this.objects,
annotations: this.frameAnnotations
}
localStorage.setItem('annotations', JSON.stringify(data))
},
// Charger les annotations depuis le format demandé
loadAnnotations() {
const saved = localStorage.getItem('annotations')
if (saved) {
const data = JSON.parse(saved)
this.currentSession.video = data.video
this.currentSession.metadata = data.metadata
this.objects = data.objects
this.frameAnnotations = data.annotations
}
},
getAnnotation(frameNumber, annotationId) {
if (!this.frameAnnotations[frameNumber]) return null
return this.frameAnnotations[frameNumber].find(a => a.id === annotationId) || null
},
addTemporaryPoint(point) {
// Ajouter un ID unique au point
const pointWithId = {
...point,
id: uuidv4()
}
this.temporaryPoints.push(pointWithId)
return pointWithId.id
},
removeTemporaryPoint(pointId) {
const index = this.temporaryPoints.findIndex(p => p.id === pointId)
if (index !== -1) {
this.temporaryPoints.splice(index, 1)
}
},
clearTemporaryPoints() {
this.temporaryPoints = []
},
// Supprimer un objet et toutes ses annotations
deleteObject(objectId) {
// Supprimer l'objet du dictionnaire
delete this.objects[objectId]
// Supprimer toutes les annotations associées à cet objet
Object.keys(this.frameAnnotations).forEach(frameKey => {
this.frameAnnotations[frameKey] = this.frameAnnotations[frameKey]
.filter(annotation => annotation.objectId !== objectId)
})
// Si l'objet supprimé était sélectionné, désélectionner
if (this.selectedObjectId === objectId) {
this.selectedObjectId = null
}
// Supprimer les points temporaires associés à cet objet
this.temporaryPoints = this.temporaryPoints.filter(point => point.objectId !== objectId)
}
}
})