diff --git a/src/components/AnnotationMain/AnnotationMain.js b/src/components/AnnotationMain/AnnotationMain.js
index c4cb491..fa310e4 100644
--- a/src/components/AnnotationMain/AnnotationMain.js
+++ b/src/components/AnnotationMain/AnnotationMain.js
@@ -8,6 +8,7 @@ import * as AnnotationService from '../../services/AnnotationService';
import AnnotationControls from '../AnnotationControls/AnnotationControls';
import saveAnnotation from '../../services/DataHandler';
import './AnnotationMain.css';
+import { detectionTypes } from '../../constants/detectionTypes';
function AnnotationMain() {
const [files, setFiles] = useState([]);
@@ -21,6 +22,7 @@ function AnnotationMain() {
const [videoWidth, setVideoWidth] = useState(640);
const [videoHeight, setVideoHeight] = useState(480);
const [errorMessage, setErrorMessage] = useState("");
+ const [detectionType, setDetectionType] = useState(detectionTypes.day)
const videoRef = useRef(null);
const containerRef = useRef(null);
@@ -71,7 +73,8 @@ function AnnotationMain() {
const imageData = AnnotationService.createAnnotationImage(
videoRef,
detections,
- safeContainerRef
+ safeContainerRef,
+ detectionType
);
if (imageData) {
@@ -186,7 +189,11 @@ function AnnotationMain() {
onDropNewFiles={handleDropNewFiles}
/>
-
+
@@ -214,6 +221,7 @@ function AnnotationMain() {
onDetectionsChange={handleDetectionsChange}
onSelectionChange={handleSelectionChange}
detectionClass={selectedClass}
+ detectionType={detectionType}
/>
diff --git a/src/components/CanvasEditor/CanvasEditor.js b/src/components/CanvasEditor/CanvasEditor.js
index 6f02cc9..d7527fc 100644
--- a/src/components/CanvasEditor/CanvasEditor.js
+++ b/src/components/CanvasEditor/CanvasEditor.js
@@ -12,7 +12,8 @@ function CanvasEditor({
onDetectionsChange,
onSelectionChange,
children,
- detectionClass
+ detectionClass,
+ detectionType
}) {
const containerRef = useRef(null);
const [currentDetection, setCurrentDetection] = useState(initialCurrentDetection);
@@ -258,6 +259,7 @@ function CanvasEditor({
onDetectionMouseDown={handleDetectionMouseDown}
currentDetection={currentDetection}
onResize={handleResize}
+ detectionType={detectionType}
/>
diff --git a/src/components/Detection.js b/src/components/Detection.js
index eb98433..c1e0f1f 100644
--- a/src/components/Detection.js
+++ b/src/components/Detection.js
@@ -1,6 +1,7 @@
import React from 'react';
+import { detectionTypes } from '../constants/detectionTypes';
-function Detection({ detection, isSelected, onDetectionMouseDown, onResize }) {
+function Detection({ detection, isSelected, onDetectionMouseDown, onResize, detectionType }) {
if (!detection || !detection.class) {
return null;
}
@@ -13,10 +14,6 @@ function Detection({ detection, isSelected, onDetectionMouseDown, onResize }) {
}
// Use startsWith to correctly handle RGBA and hex colors
- const backgroundColor = color.startsWith('rgba')
- ? color.replace(/rgba\((\d+),\s*(\d+),\s*(\d+),\s*[\d.]+\)/, 'rgba($1, $2, $3, 0.4)')
- : color.replace(/rgb\((\d+),\s*(\d+),\s*(\d+)\)/, 'rgba($1, $2, $3, 0.4)');
-
const borderColor = color.startsWith('rgba')
? color.replace(/rgba\((\d+),\s*(\d+),\s*(\d+),\s*[\d.]+\)/, 'rgba($1, $2, $3, 1)')
: color;
@@ -40,7 +37,6 @@ function Detection({ detection, isSelected, onDetectionMouseDown, onResize }) {
top: `${detection.y1}px`,
width: `${detection.x2 - detection.x1}px`,
height: `${detection.y2 - detection.y1}px`,
- backgroundColor: backgroundColor,
border: `2px solid ${borderColor}`,
boxSizing: 'border-box',
cursor: isSelected ? 'move' : 'default',
@@ -50,7 +46,7 @@ function Detection({ detection, isSelected, onDetectionMouseDown, onResize }) {
if (isSelected) {
style.border = `3px solid black`;
- style.boxShadow = `0 0 4px 2px ${borderColor}`;
+ style.boxShadow = `0 0 4px 4px ${borderColor}`;
}
const handleMouseDown = (e) => {
@@ -92,7 +88,7 @@ function Detection({ detection, isSelected, onDetectionMouseDown, onResize }) {
textShadow: '1px 1px 2px black',
pointerEvents: 'none'
}}>
- {detection.class.Name}
+ {detection.class.Name} {detectionType !== detectionTypes.day && '(' + detectionType + ')'}
);
diff --git a/src/components/DetectionClassList/DetectionClassList.css b/src/components/DetectionClassList/DetectionClassList.css
index 562f708..6d0320c 100644
--- a/src/components/DetectionClassList/DetectionClassList.css
+++ b/src/components/DetectionClassList/DetectionClassList.css
@@ -21,4 +21,36 @@
font-weight: 500;
margin-bottom: 2px;
border-radius: 4px;
+}
+
+.detection-type-group {
+ display: flex;
+ flex-direction: row;
+ justify-content: center;
+ gap: 5%;
+ padding: 10px 12px;
+}
+
+.detection-type-btn {
+ width: 25%;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ font-size: 18px;
+ padding: 4px 10px;
+ border-radius: 4px;
+}
+
+.detection-type-btn:hover {
+ background: #d6eed5;
+}
+
+.active-type {
+ color: white;
+ background: black;
+}
+
+.active-type:hover {
+ cursor: default;
+ background: black;
}
\ No newline at end of file
diff --git a/src/components/DetectionClassList/DetectionClassList.js b/src/components/DetectionClassList/DetectionClassList.js
index a56dd54..c45cabd 100644
--- a/src/components/DetectionClassList/DetectionClassList.js
+++ b/src/components/DetectionClassList/DetectionClassList.js
@@ -1,8 +1,11 @@
import React, { useEffect, useState } from 'react';
import DetectionClass from '../../models/DetectionClass';
import './DetectionClassList.css';
+import { MdOutlineNightlightRound, MdOutlineWbSunny } from "react-icons/md";
+import { FaRegSnowflake } from 'react-icons/fa';
+import { detectionTypes } from '../../constants/detectionTypes';
-function DetectionClassList({ onClassSelect }) {
+function DetectionClassList({ onClassSelect, detectionType, setDetectionType }) {
const [detectionClasses, setDetectionClasses] = useState([]);
const [selectedClass, setSelectedClass] = useState(null);
@@ -83,6 +86,10 @@ function DetectionClassList({ onClassSelect }) {
onClassSelect && onClassSelect(cls);
};
+ const handleTypeClick = (type) => {
+ setDetectionType(type);
+ }
+
return (
Classes
@@ -107,6 +114,29 @@ function DetectionClassList({ onClassSelect }) {
);
})}
+
+
+
+
+
+
+
+
);
}
diff --git a/src/components/DetectionContainer.js b/src/components/DetectionContainer.js
index 8d20b82..1c64e1c 100644
--- a/src/components/DetectionContainer.js
+++ b/src/components/DetectionContainer.js
@@ -2,7 +2,7 @@
import React from 'react';
import Detection from './Detection';
-function DetectionContainer({ detections, selectedDetectionIndices, onDetectionMouseDown, currentDetection, onResize }) {
+function DetectionContainer({ detections, selectedDetectionIndices, onDetectionMouseDown, currentDetection, onResize, detectionType }) {
return (
<>
@@ -13,6 +13,7 @@ function DetectionContainer({ detections, selectedDetectionIndices, onDetectionM
isSelected={selectedDetectionIndices.includes(index)}
onDetectionMouseDown={(e) => onDetectionMouseDown(e, index)}
onResize={(e, position) => onResize(e, index, position)}
+ detectionType={detectionType}
/>
))}
{currentDetection && (
@@ -21,6 +22,7 @@ function DetectionContainer({ detections, selectedDetectionIndices, onDetectionM
isSelected={false}
onDetectionMouseDown={() => {}} // No-op handler for the current detection
onResize={() => {}} // No-op handler for the current detection
+ detectionType={detectionType}
/>
)}
>
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/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);
+ }
});
}