我看不到输出,也没有错误..。我试着从图像中检测出矩形的形状,并将其切割并用opencv.js保存。
onFilePicked() {
let imgElement = document.getElementById('imageSrc');
const files = event.target.files;
imgElement.src = URL.createObjectURL(files[0]);
var app = this
imgElement.onload = function () {
let mat = cv.imread(imgElement)
let dst = new cv.Mat();
cv.cvtColor(mat, mat, cv.COLOR_RGB2GRAY);
// gray = cv.bilateralFilter(gray, 11, 17, 17)
cv.Canny(mat, dst, 30, 200, 3, false);
let contours = new cv.MatVector();
let hierarchy = new cv.Mat();
var transformed = null
cv.findContours(dst, contours, hierarchy, cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE)
var sortableContours = []
for (let i = 0; i < contours.size(); i++) {
let cnt = contours.get(i);
let area = cv.contourArea(cnt, false);
let perim = cv.arcLength(cnt, false);
sortableContours.push({
areaSize: area,
perimiterSize: perim,
contour: cnt
});
let color = new cv.Scalar(255, 0, 0, 255);
let hierarchy2 = new cv.Mat();
cv.drawContours(mat, contours, -1, (0, 255, 0), 3);
}
cv.imshow('canvasOutput', mat);
let foundContour = null;
for (let sortableContour of sortableContours) {
let peri = cv.arcLength(sortableContour.contour, true);
let approx = new cv.Mat();
cv.approxPolyDP(sortableContour.contour, approx, 0.1 * peri, true);
if (approx.rows == 4) {
foundContour = approx
transformed = app.perspective_transform(mat, foundContour)
break;
} else {
approx.delete();
}
}
let rotate = app.rotate_image(transformed, 90)
cv.imshow('canvasOutput', rotate)
};
},
变换
perspective_transform(image, foundContour) {
let corner1 = new cv.Point(foundContour.data32S[0], foundContour.data32S[1]);
let corner2 = new cv.Point(foundContour.data32S[2], foundContour.data32S[3]);
let corner3 = new cv.Point(foundContour.data32S[4], foundContour.data32S[5]);
let corner4 = new cv.Point(foundContour.data32S[6], foundContour.data32S[7]);
//Order the corners
let cornerArray = [{
corner: corner1
}, {
corner: corner2
}, {
corner: corner3
}, {
corner: corner4
}];
//Sort by Y position (to get top-down)
cornerArray.sort((item1, item2) => {
return (item1.corner.y < item2.corner.y) ? -1 : (item1.corner.y > item2.corner.y) ? 1 : 0;
}).slice(0, 5);
//Determine left/right based on x position of top and bottom 2
let tl = cornerArray[0].corner.x < cornerArray[1].corner.x ? cornerArray[0] : cornerArray[1];
let tr = cornerArray[0].corner.x > cornerArray[1].corner.x ? cornerArray[0] : cornerArray[1];
let bl = cornerArray[2].corner.x < cornerArray[3].corner.x ? cornerArray[2] : cornerArray[3];
let br = cornerArray[2].corner.x > cornerArray[3].corner.x ? cornerArray[2] : cornerArray[3];
//Calculate the max width/height
let widthBottom = Math.hypot(br.corner.x - bl.corner.x, br.corner.y - bl.corner.y);
let widthTop = Math.hypot(tr.corner.x - tl.corner.x, tr.corner.y - tl.corner.y);
let theWidth = (widthBottom > widthTop) ? widthBottom : widthTop;
let heightRight = Math.hypot(tr.corner.x - br.corner.x, tr.corner.y - br.corner.y);
let heightLeft = Math.hypot(tl.corner.x - bl.corner.x, tr.corner.y - bl.corner.y);
let theHeight = (heightRight > heightLeft) ? heightRight : heightLeft;
//Transform!
let finalDestCoords = cv.matFromArray(4, 1, cv.CV_32FC2, [0, 0, theWidth - 1, 0, theWidth - 1, theHeight - 1, 0, theHeight - 1]);
// corners
let srcCoords = cv.matFromArray(4, 1, cv.CV_32FC2, [tl.corner.x, tl.corner.y, tr.corner.x, tr.corner.y, br.corner.x, br.corner.y, bl.corner.x, bl.corner.y]);
let dsize = new cv.Size(theWidth, theHeight);
let M = cv.getPerspectiveTransform(srcCoords, finalDestCoords)
let dst = new cv.Mat();
cv.warpPerspective(image, dst, M, dsize);
return dst
},
旋转图像
rotate_image(image, angle) {
let dst = new cv.Mat();
let dsize = new cv.Size(image.rows, image.cols);
let center = new cv.Point(image.cols / 2, image.rows / 2);
// You can try more different parameters
let M = cv.getRotationMatrix2D(center, angle, 1);
cv.warpAffine(image, dst, M, dsize, cv.INTER_LINEAR, cv.BORDER_CONSTANT, new cv.Scalar());
return dst
},
发布于 2021-08-06 16:43:48
您只是在整个包含4个点的sortableContours数组中获取第一个等高线,并对其运行转换。你得先把它们排序到面积最大的地方。
//sorts the contours by largest area first
let slicer = Math.min(sortableContours.length, 4);
let sortedContours = sortableContours.sort((a,b) => (a.areaSize < b.areaSize) ? 1 : -1).slice(0, slicer);
此外,我建议从for循环中删除这一行代码,因为它可以在循环之外执行一次,并使进程慢很多(运行几千次)。
cv.drawContours(mat, contours, -1, (0, 255, 0), 3);
我最后要注意的是,如果您得到的结果很差,那么下面这一行可能需要从.1调整到更小的数量,比如.02。.1更宽容,但.02更精确。或者,您可以同时执行这两项操作,将所有结果保存在一个数组中,并在完成两个世界中最好的操作时,选择一个具有最大区域的结果。
cv.approxPolyDP(sortableContour.contour, approx, 0.1 * peri, true);
这两个世界都是最好的:
//iterates through the largest contours and creates transformed images if the contour's shape is a rectangle
let transformedOptions = [];
for (let sortedContour of sortedContours) {
let perimeter = cv.arcLength(sortedContour.contour, true);
let precisePoly = new cv.Mat();
let approxPoly = new cv.Mat();
cv.approxPolyDP(sortedContour.contour, precisePoly, 0.02 * perimeter, true); //the smaller number (0.02) is more precise
cv.approxPolyDP(sortedContour.contour, approxPoly, 0.1 * perimeter, true); //the larger number (0.1) is more forgiving
//if the polygon has 4 points (rectangle-ish)
if (precisePoly.rows == 4) {
transformedOptions.push(this.perspectiveTransform(originalImage, precisePoly, imageHeight, imageWidth))
}
if(approxPoly.rows == 4) {
transformedOptions.push(this.perspectiveTransform(originalImage, approxPoly, imageHeight, imageWidth))
}
precisePoly.delete();
approxPoly.delete();
}
let transformed = this.getLargestTransformation(transformedOptions);
//this could be optimized a bit
private getLargestTransformation(options) {
var transformed = null;
for(let option of options) {
if(option == null) continue;
var largestArea = 0;
var area = option.rows * option.cols;
if(transformed == null || area > largestArea) {
transformed = option;
largestArea = area;
}
}
return transformed;
}
https://stackoverflow.com/questions/60021855
复制相似问题