def METHOD_NAME( self, image_data ):
    self.idx += 1
    print(f'detect image {self.idx}')
    output = DetectedObjectSet()
    # Convert image to PIL Image
    input_array = image_data.asarray().astype( 'uint8' )
    input_image = PIL.Image.fromarray(input_array)
    input_image_size = input_image.size
    # preprocess image
    fixed_size = 480
    I_new = input_image.resize((int(fixed_size), int(fixed_size)), PIL.Image.LANCZOS)
    I_resize, w, h, feat_w, feat_h = utils.resize_pil(I_new, self._patch_size)
    ToTensor = transforms.Compose([transforms.ToTensor(),
                                   transforms.Normalize(
                                   (0.485, 0.456, 0.406),
                                   (0.229, 0.224, 0.225)),])
    tensor = ToTensor(I_resize).unsqueeze(0)
    if not self._cpu: tensor = tensor.cuda()
    # maskcut
    bipartitions, eigvecs = [], []
    feat = self.backbone(tensor)[0]
    _, bipartition, eigvec = maskcut_forward(feat, [feat_h, feat_w], 
                                             [self._patch_size, self._patch_size], 
                                             [h,w], self._tau, N=self._N, cpu=self._cpu)
    bipartitions += bipartition
    eigvecs += eigvec
    for idx, bipartition in enumerate(bipartitions):
        # post-process pseudo-masks with CRF
        pseudo_mask = densecrf(np.array(I_new), bipartition)
        pseudo_mask = ndimage.binary_fill_holes(pseudo_mask>=0.5)
        # filter out the mask that have a very different pseudo-mask after the CRF
        mask1 = torch.from_numpy(bipartition)
        mask2 = torch.from_numpy(pseudo_mask)
        if not self._cpu: 
            mask1 = mask1.cuda()
            mask2 = mask2.cuda()
        if metric.IoU(mask1, mask2) < 0.5:
            pseudo_mask = pseudo_mask * -1
        # construct binary pseudo-masks
        pseudo_mask[pseudo_mask < 0] = 0
        # create coco-style annotation info
        annotation_info = create_annotation_info(
            idx, 0, category_info, 
            pseudo_mask.astype(np.uint8), input_image_size)
        if not annotation_info:
        	return output
        # Convert detections to kwiver format
        [tl_x, tl_y, w, h] = np.array(annotation_info["bbox"]).astype( np.int32 ) # xywh
        bounding_box = BoundingBoxD( tl_x, tl_y, tl_x + w, tl_y + h ) # tlbr
        label = "maskcut"
        class_confidence = 1
        detected_object_type = DetectedObjectType( label, class_confidence )
        detected_object = DetectedObject( bounding_box,
                                          class_confidence,
                                          detected_object_type )
        poly = kwimage.Mask(annotation_info['segmentation'], 'bytes_rle').to_multi_polygon()
        mask = Image(poly.to_relative_mask().numpy().data)
        detected_object.mask = ImageContainer(mask)
        output.add( detected_object )
    return output