diff --git a/.gitignore b/.gitignore index 499bd98..61ced85 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,6 @@ pnpm-debug.log* *.njsproj *.sln *.sw? + +# Firebase config (local only) +src/firebase.js diff --git a/src/App.vue b/src/App.vue index 23c43a1..fff870f 100644 --- a/src/App.vue +++ b/src/App.vue @@ -12,3 +12,24 @@ export default { name: 'App', }; + + diff --git a/src/main.js b/src/main.js index 219cc2f..6e76c95 100644 --- a/src/main.js +++ b/src/main.js @@ -2,7 +2,7 @@ import Vue from 'vue' import App from './App.vue' import router from './router' import store from './store' -import vuetify from './plugins/vuetify'; +import vuetify from './plugins/vuetify' import './services/axios' import firebase from 'firebase/app' import 'firebase/firestore' diff --git a/src/store/calibration.js b/src/store/calibration.js index beb8026..153daef 100644 --- a/src/store/calibration.js +++ b/src/store/calibration.js @@ -23,6 +23,9 @@ export default { threshold: 200, calibrations: [], fromDashboard: false, + // New single-point calibration features + calibrationMode: 'multi-point', // 'multi-point' | 'single-point' + singlePointPosition: null, // Will be calculated as screen center runtime: { circleIrisPoints: [], calibPredictionPoints: [], @@ -119,6 +122,22 @@ export default { setFromDashboard(state, newFromDashboard) { state.fromDashboard = newFromDashboard; }, + + // New single-point calibration mutations + setCalibrationMode(state, mode) { + state.calibrationMode = mode; + // If switching to single-point, set pointNumber to 1 + if (mode === 'single-point') { + state.pointNumber = 1; + } else { + state.pointNumber = 9; // Default multi-point + } + }, + + setSinglePointPosition(state, position) { + state.singlePointPosition = position; + }, + setRuntimeData(state, payload) { state.runtime.circleIrisPoints = payload.circleIrisPoints; state.runtime.calibPredictionPoints = payload.calibPredictionPoints; @@ -155,6 +174,9 @@ export default { state.threshold = 200; state.calibrations = []; state.fromDashboard = false; + // Reset single-point calibration properties + state.calibrationMode = 'multi-point'; + state.singlePointPosition = null; }, }, actions: { @@ -180,20 +202,36 @@ export default { return positions; }, - async saveCalib(context) { - const state = context.state; - const db = firebase.firestore(); - const calibrationData = { ...state }; - delete calibrationData.calibrations; +<<<<<<< HEAD + async saveCalib({ state, dispatch }) { try { - const calibrationsCollection = db.collection("calibrations"); - await calibrationsCollection.add(calibrationData); - console.log("Data successfully saved to calibrations collection!"); - context.dispatch("getAllCalibs"); - } catch (error) { - console.error("Error saving data to calibrations collection:", error); + const data = { ...state }; + delete data.calibrations; +======= + + // Generate single-point calibration pattern (center of screen) + generateSinglePointPattern({ commit }, { width, height }) { + const centerPoint = { + x: width / 2, + y: height / 2, + }; + + commit('setSinglePointPosition', centerPoint); + return [centerPoint]; + }, + async saveCalib({ state, dispatch }) { + try { + const data = { ...state }; + delete data.calibrations; +>>>>>>> 5886ed7 (feat: implement single-point calibration mode (#99)) + + await firebase.firestore().collection("calibrations").add(data); + dispatch("getAllCalibs"); + } catch (e) { + console.error("Save failed:", e); } }, + async finishCalibration({ state, dispatch }) { console.log("[Calibration] finishCalibration started"); @@ -217,7 +255,7 @@ export default { state.runtime.usedPattern.forEach((p) => { const data = predictions[p.x.toString().split(".")[0]][ - p.y.toString().split(".")[0] + p.y.toString().split(".")[0] ]; p.precision = Number(data.PrecisionSD).toFixed(2); @@ -252,44 +290,59 @@ export default { }, async getAllCalibs({ commit }) { try { - const db = firebase.firestore(); - const calibrationsCollection = await db + const snapshot = await firebase + .firestore() .collection("calibrations") .get(); const calibrations = []; - calibrationsCollection.forEach((doc) => { - var averageAccuracy = 0; - var averagePrecision = 0; - var data = doc.data(); - data.pattern.forEach((element) => { - averageAccuracy += Number(element.accuracy); - averagePrecision += Number(element.precision); - }); - data.averageAccuracy = averageAccuracy / data.pattern.length; - data.averagePrecision = averagePrecision / data.pattern.length; + + snapshot.forEach((doc) => { + const data = doc.data(); + + let averageAccuracy = 0; + let averagePrecision = 0; + + if (data.runtime?.usedPattern?.length) { + const total = data.runtime.usedPattern.length; + + averageAccuracy = + data.runtime.usedPattern.reduce( + (sum, p) => sum + Number(p.accuracy || 0), + 0 + ) / total; + + averagePrecision = + data.runtime.usedPattern.reduce( + (sum, p) => sum + Number(p.precision || 0), + 0 + ) / total; + } + calibrations.push({ id: doc.id, - model: doc.data().models, ...data, + averageAccuracy: Number(averageAccuracy.toFixed(2)), + averagePrecision: Number(averagePrecision.toFixed(2)), }); }); commit("setCalibrations", calibrations); - } catch (error) { - console.error("Error getting calibrations:", error); - throw error; + } catch (err) { + console.error("Error getting calibrations:", err); } }, async deleteCalib({ dispatch }, calib) { try { - const db = firebase.firestore(); - const calibrationsCollection = db.collection("calibrations"); - await calibrationsCollection.doc(calib.id).delete(); + await firebase + .firestore() + .collection("calibrations") + .doc(calib.id) + .delete(); + dispatch("getAllCalibs"); - } catch (error) { - console.error("Error deleting calibration:", error); - return { success: false, message: "Failed to delete calibration" }; + } catch (e) { + console.error("Delete failed:", e); } }, async sendData(context, data) { diff --git a/src/views/CameraConfiguration.vue b/src/views/CameraConfiguration.vue index bd395db..cee9de9 100644 --- a/src/views/CameraConfiguration.vue +++ b/src/views/CameraConfiguration.vue @@ -198,6 +198,7 @@ mdi-arrow-left Back +<<<<<<< HEAD +======= + + + + + + + + + + + Camera Setup + + + + Preview & Calibration + + + + + + + + + + mdi-camera-iris + + + What will happen: + + + The system will request camera permission + Your webcam image will appear with a face guide + Position your face inside the mask overlay + Make sure both eyes are clearly visible + + + + + Important: Please allow camera access when prompted. + + + + + + mdi-arrow-right + Continue + + + + + + + + + + + + mdi-target + Calibration Mode + + + + + + + Multi-point (High Accuracy) + + 9 points across screen - Best accuracy for precise tracking + + + + + + + + Single-point (Quick Setup) + + Center point only - Faster setup, lower accuracy + + + + + + + + + + + + + + + + + + + mdi-help-circle + Camera Help + + + + + + + + + + + Loading face detection model... + + + + + + mdi-arrow-left + Back + + + mdi-play + Start Calibration + + + + + + + + + + +>>>>>>> 5886ed7 (feat: implement single-point calibration mode (#99))