Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- export async function contourBasedCrop(inputCanvas: HTMLCanvasElement): Promise<void> {
- if (inputCanvas.width === 0 || inputCanvas.height === 0) {
- console.warn("Canvas is empty, skipping processing.");
- return;
- }
- const canvas = inputCanvas;
- const cv = await getOpenCv();
- const src = cv.imread(canvas);
- const gray = new cv.Mat();
- const binary = new cv.Mat();
- const contours = new cv.MatVector();
- const hierarchy = new cv.Mat();
- let largestContour = null;
- try {
- // Convert to grayscale
- cv.cvtColor(src, gray, cv.COLOR_RGBA2GRAY);
- // Create binary image to detect contours
- cv.adaptiveThreshold(
- gray,
- binary,
- 255,
- cv.ADAPTIVE_THRESH_GAUSSIAN_C,
- cv.THRESH_BINARY_INV,
- 15,
- 2
- );
- const kernel = cv.Mat.ones(3, 3, cv.CV_8U);
- cv.erode(binary, binary, kernel);
- cv.dilate(binary, binary, kernel);
- kernel.delete();
- // Find contours
- cv.findContours(binary, contours, hierarchy, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE);
- let maxArea = 0;
- for (let i = 0; i < contours.size(); i++) {
- const c = contours.get(i);
- const area = cv.contourArea(c);
- if (area > maxArea && area > 1000) {
- maxArea = area;
- if (largestContour) largestContour.delete();
- largestContour = c.clone();
- }
- }
- if (!largestContour) return;
- // Get rotation matrix
- const rotatedRect = cv.minAreaRect(largestContour);
- let { angle } = rotatedRect;
- if (rotatedRect.size.width < rotatedRect.size.height) angle += 90;
- const center = new cv.Point(rotatedRect.center.x, rotatedRect.center.y);
- const M = cv.getRotationMatrix2D(center, angle, 1);
- const rotated = new cv.Mat();
- cv.warpAffine(
- src,
- rotated,
- M,
- src.size(),
- cv.INTER_LINEAR,
- cv.BORDER_CONSTANT,
- new cv.Scalar()
- );
- // Crop the region of interest
- const x = Math.max(0, Math.floor(rotatedRect.center.x - rotatedRect.size.width / 2));
- const y = Math.max(0, Math.floor(rotatedRect.center.y - rotatedRect.size.height / 2));
- const width = Math.floor(rotatedRect.size.width);
- const height = Math.floor(rotatedRect.size.height);
- const safeWidth = Math.min(width, rotated.cols - x);
- const safeHeight = Math.min(height, rotated.rows - y);
- if (safeWidth <= 0 || safeHeight <= 0) return;
- const safeRect = new cv.Rect(x, y, safeWidth, safeHeight);
- const cropped = rotated.roi(safeRect);
- // Apply Otsu binarization after cropping
- const croppedGray = new cv.Mat();
- const croppedBinary = new cv.Mat();
- cv.cvtColor(cropped, croppedGray, cv.COLOR_RGBA2GRAY);
- cv.threshold(croppedGray, croppedBinary, 0, 255, cv.THRESH_BINARY + cv.THRESH_OTSU);
- cv.bitwise_not(croppedBinary, croppedBinary);
- canvas.width = croppedBinary.cols;
- canvas.height = croppedBinary.rows;
- cv.imshow(canvas, croppedBinary);
- cropped.delete();
- croppedGray.delete();
- croppedBinary.delete();
- M.delete();
- rotated.delete();
- } finally {
- gray.delete();
- binary.delete();
- contours.delete();
- hierarchy.delete();
- if (largestContour) largestContour.delete();
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement