A utility class for saving detection data to a CSV file. This class is designed to
efficiently serialize detection objects into a CSV format, allowing for the
inclusion of bounding box coordinates and additional attributes like confidence,
class_id, and tracker_id.
Tip
CSVSink allow to pass custom data alongside the detection fields, providing
flexibility for logging various types of information.
classCSVSink:""" A utility class for saving detection data to a CSV file. This class is designed to efficiently serialize detection objects into a CSV format, allowing for the inclusion of bounding box coordinates and additional attributes like `confidence`, `class_id`, and `tracker_id`. !!! tip CSVSink allow to pass custom data alongside the detection fields, providing flexibility for logging various types of information. Args: file_name (str): The name of the CSV file where the detections will be stored. Defaults to 'output.csv'. Example: ```python import supervision as sv from ultralytics import YOLO model = YOLO(<SOURCE_MODEL_PATH>) csv_sink = sv.CSVSink(<RESULT_CSV_FILE_PATH>) frames_generator = sv.get_video_frames_generator(<SOURCE_VIDEO_PATH>) with csv_sink as sink: for frame in frames_generator: result = model(frame)[0] detections = sv.Detections.from_ultralytics(result) sink.append(detections, custom_data={'<CUSTOM_LABEL>':'<CUSTOM_DATA>'}) ``` """def__init__(self,file_name:str="output.csv")->None:""" Initialize the CSVSink instance. Args: file_name (str): The name of the CSV file. Returns: None """self.file_name=file_nameself.file:Optional[open]=Noneself.writer:Optional[csv.writer]=Noneself.header_written=Falseself.field_names=[]def__enter__(self)->CSVSink:self.open()returnselfdef__exit__(self,exc_type:Optional[type],exc_val:Optional[Exception],exc_tb:Optional[Any],)->None:self.close()defopen(self)->None:""" Open the CSV file for writing. Returns: None """parent_directory=os.path.dirname(self.file_name)ifparent_directoryandnotos.path.exists(parent_directory):os.makedirs(parent_directory)self.file=open(self.file_name,"w",newline="")self.writer=csv.writer(self.file)defclose(self)->None:""" Close the CSV file. Returns: None """ifself.file:self.file.close()@staticmethoddefparse_detection_data(detections:Detections,custom_data:Optional[Dict[str,Any]]=None)->List[Dict[str,Any]]:parsed_rows=[]foriinrange(len(detections.xyxy)):row={"x_min":detections.xyxy[i][0],"y_min":detections.xyxy[i][1],"x_max":detections.xyxy[i][2],"y_max":detections.xyxy[i][3],"class_id":""ifdetections.class_idisNoneelsestr(detections.class_id[i]),"confidence":""ifdetections.confidenceisNoneelsestr(detections.confidence[i]),"tracker_id":""ifdetections.tracker_idisNoneelsestr(detections.tracker_id[i]),}ifhasattr(detections,"data"):forkey,valueindetections.data.items():ifvalue.ndim==0:row[key]=valueelse:row[key]=value[i]ifcustom_data:row.update(custom_data)parsed_rows.append(row)returnparsed_rowsdefappend(self,detections:Detections,custom_data:Optional[Dict[str,Any]]=None)->None:""" Append detection data to the CSV file. Args: detections (Detections): The detection data. custom_data (Dict[str, Any]): Custom data to include. Returns: None """ifnotself.writer:raiseException(f"Cannot append to CSV: The file '{self.file_name}' is not open.")field_names=CSVSink.parse_field_names(detections,custom_data)ifnotself.header_written:self.field_names=field_namesself.writer.writerow(field_names)self.header_written=Trueiffield_names!=self.field_names:print(f"Field names do not match the header. "f"Expected: {self.field_names}, given: {field_names}")parsed_rows=CSVSink.parse_detection_data(detections,custom_data)forrowinparsed_rows:self.writer.writerow([row.get(field_name,"")forfield_nameinself.field_names])@staticmethoddefparse_field_names(detections:Detections,custom_data:Dict[str,Any])->List[str]:dynamic_header=sorted(set(custom_data.keys())|set(getattr(detections,"data",{}).keys()))returnBASE_HEADER+dynamic_header
def__init__(self,file_name:str="output.csv")->None:""" Initialize the CSVSink instance. Args: file_name (str): The name of the CSV file. Returns: None """self.file_name=file_nameself.file:Optional[open]=Noneself.writer:Optional[csv.writer]=Noneself.header_written=Falseself.field_names=[]
defappend(self,detections:Detections,custom_data:Optional[Dict[str,Any]]=None)->None:""" Append detection data to the CSV file. Args: detections (Detections): The detection data. custom_data (Dict[str, Any]): Custom data to include. Returns: None """ifnotself.writer:raiseException(f"Cannot append to CSV: The file '{self.file_name}' is not open.")field_names=CSVSink.parse_field_names(detections,custom_data)ifnotself.header_written:self.field_names=field_namesself.writer.writerow(field_names)self.header_written=Trueiffield_names!=self.field_names:print(f"Field names do not match the header. "f"Expected: {self.field_names}, given: {field_names}")parsed_rows=CSVSink.parse_detection_data(detections,custom_data)forrowinparsed_rows:self.writer.writerow([row.get(field_name,"")forfield_nameinself.field_names])
defopen(self)->None:""" Open the CSV file for writing. Returns: None """parent_directory=os.path.dirname(self.file_name)ifparent_directoryandnotos.path.exists(parent_directory):os.makedirs(parent_directory)self.file=open(self.file_name,"w",newline="")self.writer=csv.writer(self.file)
JSON Sink
A utility class for saving detection data to a JSON file. This class is designed to
efficiently serialize detection objects into a JSON format, allowing for the
inclusion of bounding box coordinates and additional attributes like confidence,
class_id, and tracker_id.
Tip
JSONsink allow to pass custom data alongside the detection fields, providing
flexibility for logging various types of information.
classJSONSink:""" A utility class for saving detection data to a JSON file. This class is designed to efficiently serialize detection objects into a JSON format, allowing for the inclusion of bounding box coordinates and additional attributes like `confidence`, `class_id`, and `tracker_id`. !!! tip JSONsink allow to pass custom data alongside the detection fields, providing flexibility for logging various types of information. Args: file_name (str): The name of the JSON file where the detections will be stored. Defaults to 'output.json'. Example: ```python import supervision as sv from ultralytics import YOLO model = YOLO(<SOURCE_MODEL_PATH>) json_sink = sv.JSONSink(<RESULT_JSON_FILE_PATH>) frames_generator = sv.get_video_frames_generator(<SOURCE_VIDEO_PATH>) with json_sink as sink: for frame in frames_generator: result = model(frame)[0] detections = sv.Detections.from_ultralytics(result) sink.append(detections, custom_data={'<CUSTOM_LABEL>':'<CUSTOM_DATA>'}) ``` """def__init__(self,file_name:str="output.json")->None:""" Initialize the JSONSink instance. Args: file_name (str): The name of the JSON file. Returns: None """self.file_name=file_nameself.file:Optional[open]=Noneself.data:List[Dict[str,Any]]=[]def__enter__(self)->JSONSink:self.open()returnselfdef__exit__(self,exc_type:Optional[type],exc_val:Optional[Exception],exc_tb:Optional[Any],)->None:self.write_and_close()defopen(self)->None:""" Open the JSON file for writing. Returns: None """parent_directory=os.path.dirname(self.file_name)ifparent_directoryandnotos.path.exists(parent_directory):os.makedirs(parent_directory)self.file=open(self.file_name,"w")defwrite_and_close(self)->None:""" Write and close the JSON file. Returns: None """ifself.file:json.dump(self.data,self.file,indent=4)self.file.close()@staticmethoddefparse_detection_data(detections:Detections,custom_data:Optional[Dict[str,Any]]=None)->List[Dict[str,Any]]:parsed_rows=[]foriinrange(len(detections.xyxy)):row={"x_min":float(detections.xyxy[i][0]),"y_min":float(detections.xyxy[i][1]),"x_max":float(detections.xyxy[i][2]),"y_max":float(detections.xyxy[i][3]),"class_id":""ifdetections.class_idisNoneelseint(detections.class_id[i]),"confidence":""ifdetections.confidenceisNoneelsefloat(detections.confidence[i]),"tracker_id":""ifdetections.tracker_idisNoneelseint(detections.tracker_id[i]),}ifhasattr(detections,"data"):forkey,valueindetections.data.items():row[key]=(str(value[i])ifhasattr(value,"__getitem__")andvalue.ndim!=0elsestr(value))ifcustom_data:row.update(custom_data)parsed_rows.append(row)returnparsed_rowsdefappend(self,detections:Detections,custom_data:Optional[Dict[str,Any]]=None)->None:""" Append detection data to the JSON file. Args: detections (Detections): The detection data. custom_data (Dict[str, Any]): Custom data to include. Returns: None """parsed_rows=JSONSink.parse_detection_data(detections,custom_data)self.data.extend(parsed_rows)
def__init__(self,file_name:str="output.json")->None:""" Initialize the JSONSink instance. Args: file_name (str): The name of the JSON file. Returns: None """self.file_name=file_nameself.file:Optional[open]=Noneself.data:List[Dict[str,Any]]=[]
defappend(self,detections:Detections,custom_data:Optional[Dict[str,Any]]=None)->None:""" Append detection data to the JSON file. Args: detections (Detections): The detection data. custom_data (Dict[str, Any]): Custom data to include. Returns: None """parsed_rows=JSONSink.parse_detection_data(detections,custom_data)self.data.extend(parsed_rows)
defopen(self)->None:""" Open the JSON file for writing. Returns: None """parent_directory=os.path.dirname(self.file_name)ifparent_directoryandnotos.path.exists(parent_directory):os.makedirs(parent_directory)self.file=open(self.file_name,"w")
defwrite_and_close(self)->None:""" Write and close the JSON file. Returns: None """ifself.file:json.dump(self.data,self.file,indent=4)self.file.close()