From 32b2c3c6ab7fad475c3e00cbdb6f288d759c5bd0 Mon Sep 17 00:00:00 2001 From: "santasri.pachhal" Date: Thu, 19 Mar 2026 13:12:02 +0530 Subject: [PATCH] feat: implement drain issue --- src/app/(modules)/upload/[videoId]/page.tsx | 8 ++- src/components/dashboard/dashboard-map.tsx | 65 +++++++-------------- src/components/video/detection-logs.tsx | 44 ++++++++------ src/constants/detectionModeConfig.ts | 35 ++++++++++- src/hooks/use-frame-detection-map.ts | 48 +++++++-------- src/types/analysis.ts | 3 + src/types/detection.ts | 8 ++- src/types/video.ts | 1 + 8 files changed, 122 insertions(+), 90 deletions(-) diff --git a/src/app/(modules)/upload/[videoId]/page.tsx b/src/app/(modules)/upload/[videoId]/page.tsx index 6fd44f4..549e744 100644 --- a/src/app/(modules)/upload/[videoId]/page.tsx +++ b/src/app/(modules)/upload/[videoId]/page.tsx @@ -41,7 +41,13 @@ export default function VideoProcessingPage() { setProgress(data.progress || 0); let message = data.message || 'Processing...'; const uniqueCount = - data.unique_potholes ?? data.unique_signboards ?? data.unique_culverts; + data.unique_potholes ?? + data.unique_pothole ?? + data.unique_signboards ?? + data.unique_signboard ?? + data.unique_culverts ?? + data.unique_culvert ?? + data.unique_drain_issue; if (uniqueCount !== undefined) { message += ` | Unique: ${uniqueCount} | Total: ${data.total_detections || 0}`; } diff --git a/src/components/dashboard/dashboard-map.tsx b/src/components/dashboard/dashboard-map.tsx index 2f586fc..3d377e2 100644 --- a/src/components/dashboard/dashboard-map.tsx +++ b/src/components/dashboard/dashboard-map.tsx @@ -5,6 +5,7 @@ import dynamic from 'next/dynamic'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Loader2, Milestone } from 'lucide-react'; import { Detection } from '@/types'; +import { DETECTION_TYPES } from '@/constants/detectionModeConfig'; // Dynamically import the map to avoid SSR issues with Leaflet const DashboardMapContent = dynamic(() => import('./dashboard-map-content'), { @@ -78,20 +79,6 @@ export function DashboardMap({ // Filter detections with valid GPS coordinates const validDetections = detections.filter((d) => d.latitude && d.longitude); - // Count detections by category - const counts = { - defected_sign_board: validDetections.filter( - (d) => d.type?.toLowerCase() === 'defected_sign_board', - ).length, - pothole: validDetections.filter((d) => d.type?.toLowerCase() === 'pothole').length, - road_crack: validDetections.filter((d) => d.type?.toLowerCase() === 'road_crack').length, - damaged_road_marking: validDetections.filter( - (d) => d.type?.toLowerCase() === 'damaged_road_marking', - ).length, - good_sign_board: validDetections.filter((d) => d.type?.toLowerCase() === 'good_sign_board') - .length, - }; - return ( @@ -104,42 +91,30 @@ export function DashboardMap({ Detection Map

{isLoading - ? 'Loading...' - : `${validDetections.length} detections with GPS coordinates`} + ? 'Loading...' + : `${validDetections.length} detections with GPS coordinates`}

- {/* Compact Color Legend */} + {/* Dynamic Color Legend */}
-
-
- Potholes ({counts.pothole}) -
-
-
- - Defected Signs ({counts.defected_sign_board}) - -
-
-
- - Cracks ({counts.road_crack}) - -
-
-
- - Markings ({counts.damaged_road_marking}) - -
-
-
- - Good Signs ({counts.good_sign_board}) - -
+ {Object.values(DETECTION_TYPES).map((type) => { + const count = validDetections.filter( + (d) => (d.type || d.class || '').toLowerCase() === type.id.toLowerCase() + ).length; + + if (count === 0 && (type.id.includes('culvert') || type.id === 'drain_issue')) return null; + + return ( +
+
+ + {type.label} ({count}) + +
+ ); + })}
diff --git a/src/components/video/detection-logs.tsx b/src/components/video/detection-logs.tsx index 01844eb..e9f5093 100644 --- a/src/components/video/detection-logs.tsx +++ b/src/components/video/detection-logs.tsx @@ -4,6 +4,7 @@ import { Activity, Film } from 'lucide-react'; import { Badge } from '@/components/ui/badge'; import { ScrollArea } from '@/components/ui/scroll-area'; import { DetectionLogEntry } from '@/types'; +import { DETECTION_TYPES } from '@/constants/detectionModeConfig'; interface DetectionLogsProps { logs: DetectionLogEntry[]; @@ -41,26 +42,31 @@ const DetectionLogs = ({ logs, onSeek }: DetectionLogsProps) => { {log.videoTime}
- {log.detections.map((d, j) => ( -
-
- {(d.type || '').replace(/ /g, '_')} ID: {d.id} | Confidence:{' '} - {(d.confidence * 100).toFixed(1)}% + {log.detections.map((d, j) => { + const typeId = (d.type || '').toLowerCase(); + const typeConfig = DETECTION_TYPES[typeId]; + const label = typeConfig ? typeConfig.label : typeId.replace(/_/g, ' '); + + return ( +
+
+ {label} ID: {d.id} | Confidence: {(d.confidence * 100).toFixed(1)}% +
+ {d.bbox && ( +
+ Coordinates: ({Math.round(d.bbox.x1)}, {Math.round(d.bbox.y1)}){' '} + ( + {Math.round(d.bbox.x2)}, {Math.round(d.bbox.y2)}) +
+ )} + {d.latitude && ( +
+ GPS: {d.latitude.toFixed(8)}, {d.longitude?.toFixed(8)} +
+ )}
- {d.bbox && ( -
- Coordinates: ({Math.round(d.bbox.x1)}, {Math.round(d.bbox.y1)}){' '} - ( - {Math.round(d.bbox.x2)}, {Math.round(d.bbox.y2)}) -
- )} - {d.latitude && ( -
- GPS: {d.latitude.toFixed(8)}, {d.longitude?.toFixed(8)} -
- )} -
- ))} + ); + })}
)) diff --git a/src/constants/detectionModeConfig.ts b/src/constants/detectionModeConfig.ts index 6736fe0..4b363e8 100644 --- a/src/constants/detectionModeConfig.ts +++ b/src/constants/detectionModeConfig.ts @@ -58,6 +58,14 @@ export const DETECTION_TYPES: Record = { listKey: 'good_sign_board_list', frameCountKey: 'good_sign_board', }, + drain_issue: { + id: 'drain_issue', + label: 'Drain Issue', + color: '#a855f7', + countKey: 'unique_drain_issue', + listKey: 'drain_issue_list', + frameCountKey: 'drain_issue', + }, good_culvert: { id: 'good_culvert', label: 'Good Culvert', @@ -77,10 +85,34 @@ export const DETECTION_TYPES: Record = { }; export const DETECTION_MODES: Record = { + yolo: { + id: 'yolo', + label: 'YOLO Detection', + enabledTypes: [ + 'pothole', + 'defected_sign_board', + 'road_crack', + 'damaged_road_marking', + 'good_sign_board', + 'drain_issue', + ], + }, + yolo_vl: { + id: 'yolo_vl', + label: 'YOLO-VL Detection', + enabledTypes: [ + 'pothole', + 'defected_sign_board', + 'road_crack', + 'damaged_road_marking', + 'good_sign_board', + 'drain_issue', + ], + }, 'pothole-detection': { id: 'pothole-detection', label: 'Pothole Detection', - enabledTypes: ['pothole', 'road_crack', 'damaged_road_marking'], + enabledTypes: ['pothole', 'road_crack', 'damaged_road_marking', 'drain_issue'], }, 'sign-board-detection': { id: 'sign-board-detection', @@ -96,6 +128,7 @@ export const DETECTION_MODES: Record = { 'road_crack', 'damaged_road_marking', 'good_sign_board', + 'drain_issue', ], }, culvert_detection: { diff --git a/src/hooks/use-frame-detection-map.ts b/src/hooks/use-frame-detection-map.ts index fe7a065..410f328 100644 --- a/src/hooks/use-frame-detection-map.ts +++ b/src/hooks/use-frame-detection-map.ts @@ -23,10 +23,8 @@ export const useFrameDetectionMap = (data: DetectionData, detectionType: string) .map((d: any) => ({ ...d, _detType: (d.type || '').toLowerCase(), - // Map old ID fields for backward compatibility in UI components - pothole_id: d.type === 'pothole' ? d.detection_id : undefined, - signboard_id: d.type.includes('sign') ? d.detection_id : undefined, - culvert_id: d.type.includes('culvert') ? d.detection_id : undefined, + // Map old ID fields and new ID fields dynamically for backward compatibility + [`${(d.type || '').toLowerCase()}_id`]: d.detection_id, })); if (filteredDetections.length > 0) { @@ -37,26 +35,30 @@ export const useFrameDetectionMap = (data: DetectionData, detectionType: string) let detections: any[] = []; enabledTypes.forEach((type) => { - const listKey = - type.id === 'pothole' - ? 'potholes' - : type.id.includes('sign') - ? 'signboards' - : type.id === 'good_culvert' - ? 'good_culverts' - : type.id === 'defective_culvert' - ? 'defective_culverts' - : null; + // Try common plural naming conventions for legacy support + const possibleKeys = [ + `${type.id}s`, + type.id.endsWith('y') ? `${type.id.slice(0, -1)}ies` : `${type.id}s`, + type.listKey.replace('_list', 's'), + type.listKey, + ]; - if (listKey && (frameData as any)[listKey]) { - detections = [ - ...detections, - ...(frameData as any)[listKey].map((item: any) => ({ - ...item, - _detType: type.id, - type: type.id, - })), - ]; + for (const listKey of possibleKeys) { + if ((frameData as any)[listKey]) { + detections = [ + ...detections, + ...(frameData as any)[listKey].map((item: any) => ({ + ...item, + _detType: type.id, + type: type.id, + [`${type.id.toLowerCase()}_id`]: + (item as any).detection_id ?? + (item as any)[`${type.id.toLowerCase()}_id`] ?? + item.id, + })), + ]; + break; + } } }); diff --git a/src/types/analysis.ts b/src/types/analysis.ts index 609b34f..0fc053e 100644 --- a/src/types/analysis.ts +++ b/src/types/analysis.ts @@ -19,6 +19,7 @@ export type DetectionData = { unique_road_crack?: number; unique_damaged_road_marking?: number; unique_good_sign_board?: number; + unique_drain_issue?: number; unique_good_culvert?: number; unique_defective_culvert?: number; total_road_damage?: number; @@ -31,6 +32,7 @@ export type DetectionData = { road_crack_list?: Array; damaged_road_marking_list?: Array; good_sign_board_list?: Array; + drain_issue_list?: Array; good_culvert_list?: Array; defective_culvert_list?: Array; signboard_list?: Array; // Keeping for backward compatibility @@ -64,6 +66,7 @@ export type DetectionData = { road_crack: number; damaged_road_marking: number; good_sign_board: number; + drain_issue: number; }; }>; }>; diff --git a/src/types/detection.ts b/src/types/detection.ts index 62dc5d4..73c1771 100644 --- a/src/types/detection.ts +++ b/src/types/detection.ts @@ -17,7 +17,12 @@ export type DetectionType = | 'pothole-detection' | 'sign-board-detection' | 'pot-sign-detection' - | 'culvert_detection'; + | 'culvert_detection' + | 'yolo' + | 'yolo_vl' + | 'sam3' + | 'yoloe' + | 'yoloe_trained_vl'; export interface DetectionListItem { detection_id?: number; @@ -38,6 +43,7 @@ export interface DetectionCounts { road_crack: number; damaged_road_marking: number; good_sign_board: number; + drain_issue: number; good_culvert?: number; defective_culvert?: number; } diff --git a/src/types/video.ts b/src/types/video.ts index be6294c..07cde62 100644 --- a/src/types/video.ts +++ b/src/types/video.ts @@ -11,6 +11,7 @@ export interface Video { unique_road_crack?: number; unique_damaged_road_marking?: number; unique_good_sign_board?: number; + unique_drain_issue?: number; total_road_damage?: number; total_detections?: number; created_at: string;