Closed thasneem077 closed 1 month ago
This is how I did it (and it seems to be working ok). In jscanify.js...
Change this:
extractPaper(image, resultWidth, resultHeight, cornerPoints) {
To this:
extractPaper(image, maxSize, cornerPoints) {
Then after this:
let warpedDst = new cv.Mat();
Insert this:
// Calculate "width" and "height" of the quadrilateral
const widthTop = Math.sqrt(Math.pow(topRightCorner.x - topLeftCorner.x, 2) + Math.pow(topRightCorner.y - topLeftCorner.y, 2));
const widthBottom = Math.sqrt(Math.pow(bottomRightCorner.x - bottomLeftCorner.x, 2) + Math.pow(bottomRightCorner.y - bottomLeftCorner.y, 2));
const heightLeft = Math.sqrt(Math.pow(topLeftCorner.x - bottomLeftCorner.x, 2) + Math.pow(topLeftCorner.y - bottomLeftCorner.y, 2));
const heightRight = Math.sqrt(Math.pow(topRightCorner.x - bottomRightCorner.x, 2) + Math.pow(topRightCorner.y - bottomRightCorner.y, 2));
// Average the widths and heights to account for potential skew
const avgWidth = (widthTop + widthBottom) / 2;
const avgHeight = (heightLeft + heightRight) / 2;
// Determine aspect ratio
const aspectRatio = avgWidth / avgHeight;
// Calculate output dimensions based on aspect ratio and max size
let resultWidth, resultHeight;
if (aspectRatio > 1) { // Landscape
resultWidth = maxSize;
resultHeight = Math.round(maxSize / aspectRatio);
} else { // Portrait or square
resultWidth = Math.round(maxSize * aspectRatio);
resultHeight = maxSize;
}
Before this:
let dsize = new cv.Size(resultWidth, resultHeight);
You would then use scanner.extractPaper(image, maxSize)
, where maxSize
is the largest side of your desired scanned image.
ps. ChatGPT generated it 🤣
Yep, this solution looks like it might work too. If you want to avoid unnecessary complexity though, you could simply show your users a dialog, asking them "what paper size would you like the scan to be?"
This would be very useful when scanning a variety of papers with unknown size - such as notes a customer gives you as a stack of random paper
Really it would be most useful to me if the image was extracted and returned at its real dimensions. It can be scaled to a different size later as long as the result could be queried for true dimensions.
Adding how you can achieve it since I ended up here in my initial search.
Here is how you determine capture the width & height to use for your ratio:
const img = cv.imread(imageEl);
const contour = scanner.findPaperContour(img);
console.log(contour);
const cornerPoints = scanner.getCornerPoints(contour);
console.log(cornerPoints);
const topWidth = cornerPoints.topRightCorner.x - cornerPoints.topLeftCorner.x;
const bottomWidth = cornerPoints.bottomRightCorner.x - cornerPoints.bottomLeftCorner.x;
const leftHeight = cornerPoints.bottomLeftCorner.y - cornerPoints.topLeftCorner.y;
const rightHeight = cornerPoints.bottomRightCorner.y - cornerPoints.topRightCorner.y;
console.log(topWidth);
console.log(bottomWidth);
console.log(leftHeight);
console.log(rightHeight);
const width = Math.max(topWidth, bottomWidth);
const height = Math.max(leftHeight, rightHeight);
console.log(width);
console.log(height);
const resultCanvas = scanner.extractPaper(imageEl, width, height);
The final width and height is at the ratio to scale
This feature is not easy to implement, and IMO is out of the scope of this library. If you'd like, here's an answer on StackOverflow with a solution using Python. You can get the corner points with the getCornerPoints
method and go from there.
how to set auto height or width to maintain the ratio of the image size instead of fixed width and height?
scanner.extractPaper(image, paperWidth, paperHeight)