def to_detection(self, frame_size): """Returns a :class:`fiftyone.core.labels.Detection` representation of the box. Args: frame_size: the ``(width, height)`` of the image Returns: a :class:`fiftyone.core.labels.Detection` """ label = self.label width, height = frame_size bounding_box = [ self.xtl / width, self.ytl / height, (self.xbr - self.xtl) / width, (self.ybr - self.ytl) / height, ] attributes = {a.name: a.to_attribute() for a in self.attributes} if self.occluded is not None: attributes["occluded"] = fol.BooleanAttribute(value=self.occluded) return fol.Detection( label=label, bounding_box=bounding_box, attributes=attributes, )
def to_detection(self, frame_size): """Returns a :class:`fiftyone.core.labels.Detection` representation of the object. Args: frame_size: the ``(width, height)`` of the image Returns: a :class:`fiftyone.core.labels.Detection` """ label = self.name bounding_box = self.bndbox.to_detection_format(frame_size) detection = fol.Detection(label=label, bounding_box=bounding_box) if self.pose is not None: # pylint: disable=unsupported-assignment-operation detection.attributes["pose"] = fol.CategoricalAttribute( value=self.pose) if self.truncated is not None: # pylint: disable=unsupported-assignment-operation detection.attributes["truncated"] = fol.CategoricalAttribute( value=self.truncated) if self.difficult is not None: # pylint: disable=unsupported-assignment-operation detection.attributes["difficult"] = fol.CategoricalAttribute( value=self.difficult) if self.occluded is not None: # pylint: disable=unsupported-assignment-operation detection.attributes["occluded"] = fol.CategoricalAttribute( value=self.occluded) return detection
def to_detection(self, frame_size): """Returns a :class:`fiftyone.core.labels.Detection` representation of the box. Args: frame_size: the ``(width, height)`` of the image Returns: a :class:`fiftyone.core.labels.Detection` """ label = self.label width, height = frame_size bounding_box = [ self.xtl / width, self.ytl / height, (self.xbr - self.xtl) / width, (self.ybr - self.ytl) / height, ] attributes = { a.name: fol.CategoricalAttribute(value=a.value) for a in self.attributes } return fol.Detection( label=label, bounding_box=bounding_box, attributes=attributes, )
def _parse_kitti_detection_row(row, frame_size): attributes = {} label = row[0] attributes["truncated"] = fol.NumericAttribute(value=float(row[1])) attributes["occluded"] = fol.NumericAttribute(value=int(row[2])) attributes["alpha"] = fol.NumericAttribute(value=float(row[3])) width, height = frame_size xtl, ytl, xbr, ybr = map(float, row[4:8]) bounding_box = [ xtl / width, ytl / height, (xbr - xtl) / width, (ybr - ytl) / height, ] try: attributes["dimensions"] = fol.VectorAttribute( value=np.asarray(map(float, row[8:11])) ) except IndexError: pass try: attributes["location"] = fol.VectorAttribute( value=np.asarray(map(float, row[11:14])) ) except IndexError: pass try: attributes["rotation_y"] = fol.NumericAttribute(value=float(row[14])) except IndexError: pass try: confidence = float(row[15]) except IndexError: confidence = None return fol.Detection( label=label, bounding_box=bounding_box, confidence=confidence, attributes=attributes, )
def _parse_yolo_row(row, classes): target, xc, yc, w, h = row.split() try: label = classes[int(target)] except: label = str(target) bounding_box = [ (float(xc) - 0.5 * float(w)), (float(yc) - 0.5 * float(h)), float(w), float(h), ] return fol.Detection(label=label, bounding_box=bounding_box)
def to_detection(self, frame_size, classes=None, supercategory_map=None): """Returns a :class:`fiftyone.core.labels.Detection` representation of the object. Args: frame_size: the ``(width, height)`` of the image classes (None): the list of classes supercategory_map (None): a dict mapping class names to supercategories Returns: a :class:`fiftyone.core.labels.Detection` """ if classes: label = classes[self.category_id] else: label = str(self.category_id) width, height = frame_size x, y, w, h = self.bbox bounding_box = [x / width, y / height, w / width, h / height] detection = fol.Detection(label=label, bounding_box=bounding_box) if supercategory_map is not None: supercategory = supercategory_map.get(label, None) else: supercategory = None if supercategory is not None: # pylint: disable=unsupported-assignment-operation detection.attributes["supercategory"] = fol.CategoricalAttribute( value=supercategory) if self.area is not None: # pylint: disable=unsupported-assignment-operation detection.attributes["area"] = fol.NumericAttribute( value=self.area) if self.iscrowd is not None: # pylint: disable=unsupported-assignment-operation detection.attributes["iscrowd"] = fol.NumericAttribute( value=self.iscrowd) # @todo parse `segmentation` return detection
def df2detections(df): """Converts a pandas DataFrame to a :class:`fiftyone.core.labels.Detections` instance. Args: df: a pandas.DataFrame Required columns: LabelName - the label MID Confidence - float [0, 1] XMin - float [0, 1] XMax - float [0, 1] YMin - float [0, 1] YMax - float [0, 1] Optional Columns: Source - 'freeform', 'verification', ... IsOccluded - boolean (or castable) IsTruncated - boolean (or castable) IsGroupOf - boolean (or castable) IsDepiction - boolean (or castable) IsInside - boolean (or castable) Returns: a :class:`fiftyone.core.labels.Detections` instance """ supplemental_columns = [fn for fn in DETECTION_COLUMNS if fn in df] return fol.Detections( detections=[ fol.Detection( label=row.LabelName, confidence=row.Confidence, # [<top-left-x>, <top-right-y>, <width>, <height>] bounding_box=[ row.XMin, row.YMin, row.XMax - row.XMin, row.YMax - row.YMin, ], **{sc: row[sc] for sc in supplemental_columns}, ) for _, row in df.iterrows() ] )
def _parse_label(self, features): xmins = features["image/object/bbox/xmin"].numpy() xmaxs = features["image/object/bbox/xmax"].numpy() ymins = features["image/object/bbox/ymin"].numpy() ymaxs = features["image/object/bbox/ymax"].numpy() texts = features["image/object/class/text"].numpy() detections = [] for xmin, xmax, ymin, ymax, text in zip( xmins, xmaxs, ymins, ymaxs, texts ): label = text.decode() detections.append( fol.Detection( label=label, bounding_box=[xmin, ymin, xmax - xmin, ymax - ymin], ) ) return fol.Detections(detections=detections)
def _parse_detection(self, obj, img=None): label = obj[self.label_field] try: label = self.classes[label] except: label = str(label) tlx, tly, w, h = self._parse_bbox(obj) if not self.normalized: height, width = img.shape[:2] tlx /= width tly /= height w /= width h /= height bounding_box = [tlx, tly, w, h] if self.confidence_field: confidence = obj.get(self.confidence_field, None) else: confidence = None if self.attributes_field: _attrs = obj.get(self.attributes_field, {}) attributes = { k: self._parse_attribute(v) for k, v in _attrs.items() } else: attributes = None detection = fol.Detection( label=label, bounding_box=bounding_box, confidence=confidence, attributes=attributes, ) return detection
def _write_image_dataset(dataset_exporter, samples, sample_parser, num_samples): labeled_images = isinstance(dataset_exporter, LabeledImageDatasetExporter) with fou.ProgressBar(total=num_samples) as pb: with dataset_exporter: if isinstance(samples, foc.SampleCollection): dataset_exporter.log_collection(samples) for sample in pb(samples): sample_parser.with_sample(sample) # Parse image if sample_parser.has_image_path: try: image_or_path = sample_parser.get_image_path() except: image_or_path = sample_parser.get_image() else: image_or_path = sample_parser.get_image() # Parse metadata if dataset_exporter.requires_image_metadata: if sample_parser.has_image_metadata: metadata = sample_parser.get_image_metadata() else: metadata = None if metadata is None: metadata = fom.ImageMetadata.build_for(image_or_path) else: metadata = None if labeled_images: # Parse label label = sample_parser.get_label() # # SPECIAL CASE # # Convert `Classification` labels to `Detections` format, # if necessary # if (dataset_exporter.label_cls is fol.Detections and isinstance(label, fol.Classification)): msg = ("Dataset exporter expects labels in %s format, " "but found %s. Converting labels to detections " "whose bounding boxes span the entire image" % (fol.Detections, label.__class__)) warnings.warn(msg) label = fol.Detections(detections=[ fol.Detection( label=label.label, bounding_box=[0, 0, 1, 1], # entire image confidence=label.confidence, ) ]) # Export sample dataset_exporter.export_sample(image_or_path, label, metadata=metadata) else: # Export sample dataset_exporter.export_sample(image_or_path, metadata=metadata)
def convert_classification_field_to_detections( dataset, classification_field, detections_field=None, keep_classification_field=False, ): """Converts the :class:`fiftyone.core.labels.Classification` field of the dataset into a :class:`fiftyone.core.labels.Detections` field containing the classification label. The detections are given bounding boxes that span the entire image. Args: dataset: a :class:`fiftyone.core.dataset.Dataset` classification_field: the name of the :class:`fiftyone.core.labels.Classification` field to convert to detections detections_field (None): the name of the :class:`fiftyone.core.labels.Detections` field to create. By default, ``classification_field`` is overwritten keep_classification_field (False): whether to keep ``classification_field`` after the conversion is completed. By default, the field is deleted from the dataset. If ``classification_field`` is being overwritten, this flag has no effect """ dataset.validate_field_type( classification_field, fof.EmbeddedDocumentField, embedded_doc_type=fol.Classification, ) if detections_field is None: detections_field = classification_field overwrite = detections_field == classification_field if overwrite: logger.info( "Converting Classification field '%s' to Detections format", classification_field, ) keep_classification_field = False detections_field = dataset.make_unique_field_name( root=classification_field) else: logger.info( "Converting Classification field '%s' to Detections format in " "field '%s'", classification_field, detections_field, ) with fou.ProgressBar() as pb: for sample in pb(dataset): label = sample[classification_field] if label is None: continue detection = fol.Detection( label=label.label, bounding_box=[0, 0, 1, 1], # entire image confidence=label.confidence, ) sample[detections_field] = fol.Detections(detections=[detection]) if not keep_classification_field: sample.clear_field(classification_field) sample.save() if not keep_classification_field: dataset.delete_sample_field(classification_field) if overwrite: dataset.rename_field(detections_field, classification_field)