-
Notifications
You must be signed in to change notification settings - Fork 52
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
cv.approxPolyDP maxContour. #25
Labels
bug
Something isn't working
Comments
Interesting, thanks for letting me know! Could you provide the image so I can test it? |
The original is lost, but have managed to recreate.
In the with and without images, the green dot is from cv.minAreaRect, and the blue is from averaging the corners:
function findCenterOfPoints(points) {
let sumX = 0;
let sumY = 0;
for (const point of points) {
sumX += point.x;
sumY += point.y;
}
const centerX = sumX / points.length;
const centerY = sumY / points.length;
return { x: centerX, y: centerY };
}
Also encountered raw2. This one is odd as getCornerPoints fails with the getApproxPoly on account of the bottom left being right of the center.
I suppose you could overcome this because if getApproxPoly manages to return 4 points, you can sort by X then swap on y. Something like:
if (contour.data32S.length === 8) {
let points = [];
for (let i = 0; i < 8; i+=2) {
points.push({ x: contour.data32S[i], y: contour.data32S[i+1] });
}
points.sort((a, b) => a.y - b.y); // Sort by y to separate top and bottom pairs
let topPoints = points.slice(0, 2).sort((a, b) => a.x - b.x); // Sort top pair by x
let bottomPoints = points.slice(2, 4).sort((a, b) => a.x - b.x); // Sort bottom pair by x
return {
topLeftCorner: topPoints[0],
topRightCorner: topPoints[1],
bottomLeftCorner: bottomPoints[0],
bottomRightCorner: bottomPoints[1],
};
}
Remember that before I switched to your script, I sometimes got more than 4 points out of getApproxPoly. Think this was down to my thresholding and lack of the blur, but this may be a more robust (but potentially slower) implementation to simplify the initial contour:
function simplifyContourToQuad(contour, epsilonStart = 0.1, epsilonAdjustment = 0.05, maxIterations = 10) {
if(contour.rows < 4)
return contour; // return original contour if less than 4 points (not a quadrilateral
let epsilon = epsilonStart;
let approx = new cv.Mat(contour);
let iterations = 0;
const peri = cv.arcLength(contour, true);
while (iterations < maxIterations) {
if (approx.rows == 4) {
// Found a quadrilateral
return approx;
}
cv.approxPolyDP(contour, approx, epsilon * peri, true);
// Not 100% sure on adjusting both ways, as not properly tested
// a small number of test runs have shown that decrementing seems to work
// but all cases were with epsilonStart at 0.2 and resulted in <4 points
if(approx.rows < 4)
epsilon -= epsilonAdjustment; // Decrement epsilon to simplify further
else
epsilon += epsilonAdjustment; // Increment epsilon to add more points
iterations++;
}
}
However 0.1 does seem to be fairly consistent at getting 4 points.
|
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
During testing, I encountered a case where the top-right of my page was incorrectly evaluated as being near the top-left, resulting in a near triangular poly from
getCornerPoints(contour)
. What seems to have happened is that there was a point in the contour that was just right of the centre, yet had a bigger distance than the right-hand corner of the page (although the page was at an almost 45 degree angle in the frame, which would be unusual).Recommend applying a cv.approxPolyDP to the
maxContour
prior togetCornerPoints(contour)
to reduce occurrences.The text was updated successfully, but these errors were encountered: