docs: def _make_shred(self, c, name, feature_extractors, sheet_name):
          """Creates a Shred instances from a given contour.
  
          Args:
              c: cv2 contour object.
              name: string shred name within a sheet.
              feature_extractors: iterable of AbstractShredFeature instances.
  
          Returns:
              A new Shred instance or None on failure.
          """
          height, width, channels = self.orig_img.shape
  
          # bounding rect of currrent contour
          r_x, r_y, r_w, r_h = cv2.boundingRect(c)
  
          # Generating simplified contour to use it in html
          epsilon = 0.01 * cv2.arcLength(c, True)
          simplified_contour = cv2.approxPolyDP(c, epsilon, True)
  
          # filter out too small fragments
          if self.px_to_mm(r_w) <= 3 or self.px_to_mm(r_h) <= 3:
              print("Skipping piece #%s as too small (%spx x %s px)" % (
                  name, r_w, r_h))
              return None
  
          if self.px_to_mm(r_w) >= 100 and self.px_to_mm(r_h) >= 100:
              print("Skipping piece #%s as too big (%spx x %s px)" % (
                  name, r_w, r_h))
              return None
  
          # position of rect of min area.
          # this will provide us angle to straighten image
          box_center, bbox, angle = cv2.minAreaRect(c)
  
          # We want our pieces to be "vertical"
          if bbox[0] > bbox[1]:
              angle += 90
              bbox = (bbox[1], bbox[0])
  
          if bbox[1] / float(bbox[0]) > 70:
              print("Skipping piece #%s as too too long and narrow" % name)
              return None
  
          # Coords of region of interest using which we should crop piece after
          # rotation
          y1 = math.floor(box_center[1] - bbox[1] / 2)
          x1 = math.floor(box_center[0] - bbox[0] / 2)
          bbox = tuple(map(int, map(math.ceil, bbox)))
  
          # A mask we use to show only piece we are currently working on
          piece_mask = np.zeros([height, width, 1], dtype=np.uint8)
          cv2.drawContours(piece_mask, [c], -1, 255, cv2.FILLED)
  
          # apply mask to original image
          img_crp = self.orig_img[r_y:r_y + r_h, r_x:r_x + r_w]
          piece_in_context = self.save_image(
              "pieces/%s_ctx" % name,
              self.orig_img[max(r_y - 10, 0):r_y + r_h + 10,
                            max(r_x - 10, 0):r_x + r_w + 10])
  
          mask = piece_mask[r_y:r_y + r_h, r_x:r_x + r_w]
          img_roi = cv2.bitwise_and(img_crp, img_crp, mask=mask)
  
          # Add alpha layer and set it to the mask
          img_roi = cv2.cvtColor(img_roi, cv2.COLOR_BGR2BGRA)
          img_roi[:, :, 3] = mask[:, :, 0]
  
          # Straighten it
          # Because we crop original image before rotation we save us some memory
          # and a lot of time but we need to adjust coords of the center of
          # new min area rect
          M = cv2.getRotationMatrix2D((box_center[0] - r_x,
                                       box_center[1] - r_y), angle, 1)
  
          # And translate an image a bit to make it fit to the bbox again.
          # This is done with direct editing of the transform matrix.
          # (Wooohoo, I know matrix-fu)
          M[0][2] += r_x - x1
          M[1][2] += r_y - y1
  
          # Apply rotation/transform/crop
          img_roi = cv2.warpAffine(img_roi, M, bbox)
          piece_fname = self.save_image("pieces/%s" % name, img_roi, "png")
  
          # FEATURES MAGIC BELOW
          #
          # Get our mask/contour back after the trasnform
          _, _, _, mask = cv2.split(img_roi)
  
          _, contours, _ = cv2.findContours(mask.copy(), cv2.RETR_TREE,
                                            cv2.CHAIN_APPROX_SIMPLE)
  
          if len(contours) != 1:
              print("Piece #%s has strange contours after transform" % name)
  
          cnt = contours[0]
  
          features_fname = self.save_image("pieces/%s_mask" % name, mask, "png")
  
          base_features = {
              # On_sheet_* features describe the min counding box on the sheet.
              "on_sheet_x": r_x,
              "on_sheet_y": r_y,
              "on_sheet_width": r_w,
              "on_sheet_height": r_h,
              "on_sheet_angle": angle,
              "width": img_roi.shape[1],
              "height": img_roi.shape[0],
          }
  
          tags_suggestions = []
          for feat in feature_extractors:
              fts, tags = feat.get_info(img_roi, cnt, name)
              base_features.update(fts)
              tags_suggestions += tags
  
          if tags_suggestions:
              print(name, tags_suggestions)
  
          return Shred(
              contour=c,
              features=base_features,
              features_fname=features_fname,
              img_roi=img_roi,
              name=name,
              piece_fname=piece_fname,
              piece_in_context_fname=piece_in_context,
              sheet=sheet_name,
              simplified_contour=simplified_contour,
              tags_suggestions=tags_suggestions,
          )