docs: @Override
      protected ImageWritable doTransform(ImageWritable image, Random random) {
          if (image == null) {
              return null;
          }
  
          //Convert image to gray and blur
          Mat original = converter.convert(image.getFrame());
          Mat grayed = new Mat();
          cvtColor(original, grayed, CV_BGR2GRAY);
          if (blurWidth > 0 && blurHeight > 0)
              blur(grayed, grayed, new Size(blurWidth, blurHeight));
  
          //Get edges from Canny edge detector
          Mat edgeOut = new Mat();
          if (isCanny)
              Canny(grayed, edgeOut, lowerThresh, upperThresh);
          else
              threshold(grayed, edgeOut, lowerThresh, upperThresh, 0);
  
          double largestArea = 0;
          Rect boundingRect = new Rect();
          MatVector contours = new MatVector();
          Mat hierarchy = new Mat();
  
          findContours(edgeOut, contours, hierarchy, this.mode, this.method);
  
          for (int i = 0; i < contours.size(); i++) {
              //  Find the area of contour
              double area = contourArea(contours.get(i), false);
  
              if (area > largestArea) {
                  // Find the bounding rectangle for biggest contour
                  boundingRect = boundingRect(contours.get(i));
              }
          }
  
          //Apply crop and return result
          x = boundingRect.x();
          y = boundingRect.y();
          Mat result = original.apply(boundingRect);
  
          return new ImageWritable(converter.convert(result));
      }