diff --git a/src/components/AnnotationControls/AnnotationControls.css b/src/components/AnnotationControls/AnnotationControls.css index d09d26b..8da947c 100644 --- a/src/components/AnnotationControls/AnnotationControls.css +++ b/src/components/AnnotationControls/AnnotationControls.css @@ -1,61 +1,47 @@ +.controls { + margin-top: 4px; +} + .input-group { display: flex; flex-direction: row; - padding: 0 4px; + background: #222531; + padding: 0 20px; + border-radius: 4px; +} + +.time { + color: #fff; } .video-slider { - width: 100%; - margin: 12px 20px; + margin: 12px 26px; +} + +.MuiSlider-root { + color: #fff !important; } .buttons-group { display: flex; - justify-content: center; - position: relative; - z-index: 1; - padding: 10px; - background: #f5f5f5; - border-radius: 4px; - margin-top: 10px; + flex-direction: row; + gap: 10px; + margin-top: 6px; } .control-btn { + width: 40px; + height: 40px; display: flex; + justify-content: center; align-items: center; - gap: 4px; - padding: 10px 20px; - font-size: 16px; - margin: 0 5px; - border: 1px solid #ccc; + background: #222531; + padding: 4px; + border: 0; border-radius: 4px; cursor: pointer; } -.play-btn { - background: #8aff8a; -} - -.pause-btn { - background: #ff8a8a; -} - -.arrow-btn { - background: #e0e0e0; -} - -.stop-btn { - background: #e8a1a5; -} - -.save-btn { - background: #8ad4ff; -} - -.delete-btn { - background: #ffb38a; -} - -.clean-btn{ - background: #ff8a8a; +.control-btn:hover { + background: #535b77; } \ No newline at end of file diff --git a/src/components/AnnotationControls/AnnotationControls.js b/src/components/AnnotationControls/AnnotationControls.js index 40f5b46..4e5363c 100644 --- a/src/components/AnnotationControls/AnnotationControls.js +++ b/src/components/AnnotationControls/AnnotationControls.js @@ -1,7 +1,13 @@ import { Slider } from '@mui/material'; -import { FaStop } from "react-icons/fa"; -import { MdCleaningServices } from "react-icons/md"; import './AnnotationControls.css'; +import PreviousIcon from '../../icons/PreviousIcon'; +import PlayIcon from '../../icons/PlayIcon'; +import PauseIcon from '../../icons/PauseIcon'; +import NextIcon from '../../icons/NextIcon'; +import StopIcon from '../../icons/StopIcon'; +import SaveIcon from '../../icons/SaveIcon'; +import CleanIcon from '../../icons/CleanIcon'; +import DeleteIcon from '../../icons/DeleteIcon'; function AnnotationControls({ videoRef, @@ -32,7 +38,7 @@ function AnnotationControls({ return (
{formatDuration(currentTime)}
+{formatDuration(currentTime)}
{formatDuration(videoRef.current.duration - currentTime)}
- :{formatDuration(0)}
+ ?{formatDuration(videoRef.current.duration - currentTime)}
+ :{formatDuration(0)}
}Drop here
) : ( diff --git a/src/constants/detectionTypes.js b/src/constants/detectionTypes.js new file mode 100644 index 0000000..f5625c5 --- /dev/null +++ b/src/constants/detectionTypes.js @@ -0,0 +1,5 @@ +export const detectionTypes = { + day: 'day', + night: 'night', + winter: 'winter' +} \ No newline at end of file diff --git a/src/icons/CleanIcon.js b/src/icons/CleanIcon.js new file mode 100644 index 0000000..05e34ec --- /dev/null +++ b/src/icons/CleanIcon.js @@ -0,0 +1,7 @@ +const CleanIcon = ({ width = 32, height = 32 }) => ( + +); + +export default CleanIcon; \ No newline at end of file diff --git a/src/icons/DeleteIcon.js b/src/icons/DeleteIcon.js new file mode 100644 index 0000000..a78d67a --- /dev/null +++ b/src/icons/DeleteIcon.js @@ -0,0 +1,8 @@ +const DeleteIcon = ({ width = 32, height = 32 }) => ( + +); + +export default DeleteIcon; \ No newline at end of file diff --git a/src/icons/NextIcon.js b/src/icons/NextIcon.js new file mode 100644 index 0000000..4c1aa02 --- /dev/null +++ b/src/icons/NextIcon.js @@ -0,0 +1,8 @@ +const NextIcon = ({ width = 32, height = 32 }) => ( + +); + +export default NextIcon; \ No newline at end of file diff --git a/src/icons/PauseIcon.js b/src/icons/PauseIcon.js new file mode 100644 index 0000000..7d8bd7d --- /dev/null +++ b/src/icons/PauseIcon.js @@ -0,0 +1,8 @@ +const PauseIcon = ({ width = 32, height = 32 }) => ( + +); + +export default PauseIcon; \ No newline at end of file diff --git a/src/icons/PlayIcon.js b/src/icons/PlayIcon.js new file mode 100644 index 0000000..cf9e9b5 --- /dev/null +++ b/src/icons/PlayIcon.js @@ -0,0 +1,7 @@ +const PlayIcon = ({ width = 32, height = 32 }) => ( + +); + +export default PlayIcon; \ No newline at end of file diff --git a/src/icons/PreviousIcon.js b/src/icons/PreviousIcon.js new file mode 100644 index 0000000..b1a1a29 --- /dev/null +++ b/src/icons/PreviousIcon.js @@ -0,0 +1,8 @@ +const PreviousIcon = ({ width = 32, height = 32 }) => ( + +); + +export default PreviousIcon; \ No newline at end of file diff --git a/src/icons/SaveIcon.js b/src/icons/SaveIcon.js new file mode 100644 index 0000000..7726492 --- /dev/null +++ b/src/icons/SaveIcon.js @@ -0,0 +1,7 @@ +const SaveIcon = ({ width = 32, height = 32 }) => ( + +); + +export default SaveIcon; \ No newline at end of file diff --git a/src/icons/StopIcon.js b/src/icons/StopIcon.js new file mode 100644 index 0000000..ab4884c --- /dev/null +++ b/src/icons/StopIcon.js @@ -0,0 +1,7 @@ +const StopIcon = ({ width = 32, height = 32 }) => ( + +); + +export default StopIcon; \ No newline at end of file diff --git a/src/index.css b/src/index.css index ec2585e..4551eb2 100644 --- a/src/index.css +++ b/src/index.css @@ -7,6 +7,10 @@ body { -moz-osx-font-smoothing: grayscale; } +* { + box-sizing: border-box; +} + code { font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace; diff --git a/src/services/AnnotationService.js b/src/services/AnnotationService.js index 594205e..0a6c90d 100644 --- a/src/services/AnnotationService.js +++ b/src/services/AnnotationService.js @@ -1,3 +1,5 @@ +import { detectionTypes } from "../constants/detectionTypes"; + export const calculateRelativeCoordinates = (e, containerRef) => { if (!containerRef.current) return { x: 0, y: 0 }; const containerRect = containerRef.current.getBoundingClientRect(); @@ -13,7 +15,7 @@ export const isMouseOverDetection = (x, y, detection, containerRef) => { return relativeX >= detection.x1 && relativeX <= detection.x2 && relativeY >= detection.y1 && relativeY <= detection.y2; }; -export const createAnnotationImage = (videoRef, detections, containerRef) => { +export const createAnnotationImage = (videoRef, detections, containerRef, detectionType) => { if (!videoRef?.current || !containerRef?.current) { console.warn("Missing video or container reference"); return null; @@ -39,17 +41,12 @@ export const createAnnotationImage = (videoRef, detections, containerRef) => { detections.forEach(detection => { if (!detection?.class) return; - // Ensure proper opacity for background - consistently using 0.4 opacity - const bgColor = detection.class.Color?.startsWith('rgba') - ? detection.class.Color.replace(/rgba\((\d+),\s*(\d+),\s*(\d+),\s*[\d.]+\)/, 'rgba($1, $2, $3, 0.4)') - : detection.class.Color?.replace(/rgb\((\d+),\s*(\d+),\s*(\d+)\)/, 'rgba($1, $2, $3, 0.4)') || 'rgba(255, 0, 0, 0.4)'; - // Ensure full opacity for border const borderColor = detection.class.Color?.startsWith('rgba') ? detection.class.Color.replace(/rgba\((\d+),\s*(\d+),\s*(\d+),\s*[\d.]+\)/, 'rgba($1, $2, $3, 1)') : detection.class.Color || 'rgba(255, 0, 0, 1)'; - ctx.fillStyle = bgColor; + ctx.fillStyle = 'rgba(255, 255, 255, 0)'; ctx.strokeStyle = borderColor; const x = Math.max(0, detection.x1 || 0) * detection.kw; @@ -63,7 +60,11 @@ export const createAnnotationImage = (videoRef, detections, containerRef) => { ctx.fillStyle = 'white'; ctx.font = '12px Arial'; - ctx.fillText(detection.class.Name || 'Unknown', x, y - 5); + if (detectionType === detectionTypes.day){ + ctx.fillText(detection.class.Name || 'Unknown', x, y - 5); + } else { + ctx.fillText(`${detection.class.Name} (${detectionType}) `|| 'Unknown', x, y - 5); + } }); }