From 580b5b8aa36dfa8f68b34df32d7288b378f97806 Mon Sep 17 00:00:00 2001 From: sumona-banerjeee Date: Mon, 16 Feb 2026 13:05:59 +0530 Subject: [PATCH] Dynamically increasing counts of defected pothole and signboards --- components/video-player-section.tsx | 226 +++++++++++++++++++++++----- lib/types.ts | 7 + 2 files changed, 193 insertions(+), 40 deletions(-) diff --git a/components/video-player-section.tsx b/components/video-player-section.tsx index ebcd771..08447f0 100644 --- a/components/video-player-section.tsx +++ b/components/video-player-section.tsx @@ -411,9 +411,18 @@ export default function VideoPlayerSection({ data, videoId, videoFile, detection const [videoError, setVideoError] = useState(null) const [lastDetectedLat, setLastDetectedLat] = useState(null) const [lastDetectedLng, setLastDetectedLng] = useState(null) + const [currentFrameCounts, setCurrentFrameCounts] = useState>({ + defected_sign_board: 0, + pothole: 0, + road_crack: 0, + damaged_road_marking: 0, + good_sign_board: 0 + }) const frameDetectionMap = useRef>(new Map()) const lastProcessedFrame = useRef(-1) const loggedFrames = useRef>(new Set()) + const cumulativeCountsMap = useRef>>(new Map()) + const sortedFrameIndices = useRef([]) const MAX_LOGS = 50 const isCombined = detectionType === "pot-sign-detection" @@ -423,30 +432,30 @@ export default function VideoPlayerSection({ data, videoId, videoFile, detection // Create GPS coordinate map from signboard_list or pothole_list const gpsMap = useRef>(new Map()) - // Build GPS map from signboard_list or pothole_list + // Build GPS map from all available detection lists useEffect(() => { const map = new Map() - if (isPothole && data.pothole_list) { - data.pothole_list.forEach(item => { - const id = (item as any).pothole_id ?? (item as any).detection_id - if (item.lat !== undefined && item.lng !== undefined && id !== undefined) { - map.set(id, { lat: item.lat, lng: item.lng }) - } - }) - } - if (isSignboard && data.signboard_list) { - data.signboard_list.forEach(item => { - const id = (item as any).signboard_id ?? (item as any).detection_id + const addItemsToMap = (list?: any[]) => { + if (!list || !Array.isArray(list)) return + list.forEach(item => { + const id = (item as any).pothole_id ?? (item as any).signboard_id ?? (item as any).detection_id if (item.lat !== undefined && item.lng !== undefined && id !== undefined) { map.set(id, { lat: item.lat, lng: item.lng }) } }) } + addItemsToMap(data.pothole_list) + addItemsToMap(data.signboard_list) + addItemsToMap(data.defected_sign_board_list) + addItemsToMap(data.road_crack_list) + addItemsToMap(data.damaged_road_marking_list) + addItemsToMap(data.good_sign_board_list) + gpsMap.current = map - console.log(`[VideoPlayer] GPS map built with ${map.size} entries`) - }, [data, isPothole, isSignboard]) + console.log(`[VideoPlayer] GPS map built with ${map.size} entries mapping to IDs`) + }, [data]) // Helper function to format video time from frame number const formatVideoTime = useCallback((frame: number, fps: number): string => { @@ -514,8 +523,113 @@ export default function VideoPlayerSection({ data, videoId, videoFile, detection } frameDetectionMap.current = map + console.log(`[VideoPlayer] Frame map built: ${map.size} frames with detections`) }, [data, isPothole, isSignboard]) + // Build cumulative counts map (Sticky Counts) + useEffect(() => { + const map = new Map>() + let lastCounts = { + defected_sign_board: 0, + pothole: 0, + road_crack: 0, + damaged_road_marking: 0, + good_sign_board: 0 + } + + if (data.frames && Array.isArray(data.frames)) { + // Sort frames by ID to ensure we process them in order + const sortedFrames = [...data.frames].sort((a, b) => (a.frame_id || 0) - (b.frame_id || 0)) + const indices: number[] = [] + + sortedFrames.forEach((frameData) => { + const frameId = frameData.frame_id + indices.push(frameId) + const detections = (frameData as any).detections + + if (detections && detections.length > 0) { + const det0 = detections[0] + let frameCounts: Record + + if (det0.count) { + frameCounts = { ...det0.count } + } else { + // Manual count if missing + frameCounts = { + defected_sign_board: 0, + pothole: 0, + road_crack: 0, + damaged_road_marking: 0, + good_sign_board: 0 + } + detections.forEach((d: any) => { + const type = (d.type || '').split(' ')[0].toLowerCase() // Handle potential spaces + if (frameCounts.hasOwnProperty(type)) { + frameCounts[type]++ + } else if (type === 'pothole') { + frameCounts.pothole++ + } else if (type.includes('defected')) { + frameCounts.defected_sign_board++ + } + }) + } + + // Carry over and update max (Sticky logic) + lastCounts = { + defected_sign_board: Math.max(lastCounts.defected_sign_board, frameCounts.defected_sign_board || 0), + pothole: Math.max(lastCounts.pothole, frameCounts.pothole || 0), + road_crack: Math.max(lastCounts.road_crack, frameCounts.road_crack || 0), + damaged_road_marking: Math.max(lastCounts.damaged_road_marking, frameCounts.damaged_road_marking || 0), + good_sign_board: Math.max(lastCounts.good_sign_board, frameCounts.good_sign_board || 0), + } + } + + map.set(frameId, { ...lastCounts }) + }) + sortedFrameIndices.current = indices + } + + cumulativeCountsMap.current = map + console.log(`[VideoPlayer] Sticky cumulative counts map built for ${map.size} frames`) + }, [data.frames]) + + // Helper to get sticky counts for any frame + const getStickyCounts = useCallback((frame: number) => { + // Find the largest frame index in our map that is <= current frame + const indices = sortedFrameIndices.current + let targetIndex = -1 + + // Quick binary search for the latest frame with detection data + let low = 0, high = indices.length - 1 + while (low <= high) { + let mid = Math.floor((low + high) / 2) + if (indices[mid] <= frame) { + targetIndex = indices[mid] + low = mid + 1 + } else { + high = mid - 1 + } + } + + if (targetIndex !== -1) { + return cumulativeCountsMap.current.get(targetIndex) || { + defected_sign_board: 0, + pothole: 0, + road_crack: 0, + damaged_road_marking: 0, + good_sign_board: 0 + } + } + + return { + defected_sign_board: 0, + pothole: 0, + road_crack: 0, + damaged_road_marking: 0, + good_sign_board: 0 + } + }, []) + // Function to draw bounding boxes on canvas const drawBoundingBoxes = useCallback((detections: any[]) => { const canvas = canvasRef.current @@ -740,6 +854,9 @@ export default function VideoPlayerSection({ data, videoId, videoFile, detection // Draw bounding boxes for current frame drawBoundingBoxes(detections || []) + // Update counts using sticky logic + setCurrentFrameCounts(getStickyCounts(frame)) + if (detections && detections.length > 0) { addDetectionLog(frame, detections) } @@ -811,7 +928,9 @@ export default function VideoPlayerSection({ data, videoId, videoFile, detection const detections = frameDetectionMap.current.get(frame) setDetectionsCount(detections?.length || 0) - // Update GPS coordinates immediately on seek + // Update sticky counts immediately on seek + setCurrentFrameCounts(getStickyCounts(frame)) + if (detections && detections.length > 0) { const det0 = detections[0] const isDetPothole = det0._detType === 'pothole' || det0.type === 'pothole' || (det0.pothole_id !== undefined && !det0.signboard_id) @@ -902,32 +1021,55 @@ export default function VideoPlayerSection({ data, videoId, videoFile, detection /> - {/* Video Info */} -
-
- Current Frame: - {currentFrame} +
+ {/* Detection Counts - Single line Flexbox */} +
+
+ Pothole: + {currentFrameCounts.pothole} +
+
+ Defect Sign Board: + {currentFrameCounts.defected_sign_board} +
+
+ Damage Road Mark: + {currentFrameCounts.damaged_road_marking} +
+
+ RoadCrack: + {currentFrameCounts.road_crack} +
+ {/*
+ Good Sign Board: + {currentFrameCounts.good_sign_board} +
*/}
-
- FPS: - {data.video_info.fps.toFixed(1)} + +
+ +
+
+ FRAME: + {currentFrame} +
+ {lastDetectedLat !== null && lastDetectedLng !== null && ( + <> +
+ LAT: + + {lastDetectedLat} + +
+
+ LNG: + + {lastDetectedLng} + +
+ + )}
- {lastDetectedLat !== null && lastDetectedLng !== null && ( - <> -
- Lat: - - {lastDetectedLat} - -
-
- Lng: - - {lastDetectedLng} - -
- - )}
@@ -975,10 +1117,14 @@ export default function VideoPlayerSection({ data, videoId, videoFile, detection
Coordinates: ({Math.round(det.bbox.x1)}, {Math.round(det.bbox.y1)}) → ({Math.round(det.bbox.x2)}, {Math.round(det.bbox.y2)})
- {det.latitude !== undefined && det.longitude !== undefined && ( + {det.latitude !== undefined && det.longitude !== undefined ? (
GPS: {det.latitude}, {det.longitude}
+ ) : ( +
+ GPS: Data Unavail. +
)}
))} diff --git a/lib/types.ts b/lib/types.ts index 2855d42..2e70b46 100644 --- a/lib/types.ts +++ b/lib/types.ts @@ -63,6 +63,13 @@ export type DetectionData = { bbox: { x1: number; y1: number; x2: number; y2: number } center?: { x: number; y: number } area?: number + count?: { + defected_sign_board: number + pothole: number + road_crack: number + damaged_road_marking: number + good_sign_board: number + } }> }> }