在使用opencv.js进行图像处理时,有时候会遇到投影变换后图像结果为空白的透明图片的问题。以下是我遇到的问题以及解决方法。
我在处理图像时,代码能够成功识别出文档的四个坐标,但到了投影变换这一步,得到的结果总是空白的透明图片,并且没有报错。以下是我使用的投影变换部分代码:
// 投影变换 let srcquad = cv.matfromarray(4, 1, cv.cv_32fc2, points.flat()); let dstquad = cv.matfromarray(4, 1, cv.cv_32fc2, [0, 0, img.cols, 0, img.cols, img.rows, 0, img.rows]); let transmtx = cv.getperspectivetransform(srcquad, dstquad); let target = new cv.mat(); cv.warpperspective(img, target, transmtx, new cv.size(img.cols, img.rows)); // 显示结果 cv.imshow(canvas, target);
为了解决这个问题,我进行了以下改进:
以下是改进后的完整代码:
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>OpenCV.js Example</title>
</head>
<body>
<script async src="https://docs.opencv.org/4.5.5/opencv.js" onload="onOpenCvReady();"></script>
<canvas id="canvasOutput"></canvas>
<script>
function onOpenCvReady() {
console.log("OpenCV.js加载完成.");
processImage();
}
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function processImage() {
await sleep(3000); // 等待 3 秒
let imageUrl = "../archives/111.jpg";
let imgElement = new Image();
imgElement.src = imageUrl;
var img;
// 加载图像
imgElement.onload = function() {
try {
img = cv.imread(imgElement);
if (img.empty()) {
console.error("Image could not be read.");
return;
}
// 获取 canvas 元素并设置大小
let canvas = document.getElementById('canvasOutput');
canvas.width = img.cols;
canvas.height = img.rows;
// 重置图像大小
let dsize = new cv.Size(img.cols, img.rows);
let dst = new cv.Mat();
cv.resize(img, dst, dsize, 0, 0, cv.INTER_AREA);
// 转为灰度图像
console.log("转换之前:", img);
let gray = new cv.Mat(); // 创建一个新的 Mat 对象来存灰度图像
cv.cvtColor(dst, gray, cv.COLOR_BGR2GRAY); // 使用适当的转换
console.log("转换之后:", gray);
// 高斯滤波
cv.GaussianBlur(gray, gray, new cv.Size(11, 11), 0, 0);
cv.imshow(canvas, gray);
cv.Canny(gray, gray, 20, 50, 3);
let contours = new cv.MatVector();
let hierarchy = new cv.Mat();
cv.findContours(gray, contours, hierarchy, cv.RETR_CCOMP, cv.CHAIN_APPROX_NONE);
let index = 0, maxArea = 0;
const area = img.cols * img.rows;
for (let i = 0; i < contours.size(); ++i) {
let tempArea = Math.abs(cv.contourArea(contours.get(i)));
if (tempArea > maxArea && tempArea > 0.3 * area) {
index = i;
maxArea = tempArea;
}
}
if (maxArea === 0) return;
const foundContour = contours.get(index);
const arcL = cv.arcLength(foundContour, true);
let approx = new cv.Mat();
// 逼近多边形
cv.approxPolyDP(foundContour, approx, 0.01 * arcL, true);
if (approx.total() === 4) {
let points = [];
const data32S = approx.data32S;
for (let i = 0, len = data32S.length / 2; i < len; i++) {
points[i] = {x: data32S[i * 2], y: data32S[i * 2 + 1]};
}
console.log("检测到四边形点:", points);
// 投影变换
let srcQuad = cv.matFromArray(4, 1, cv.CV_32FC2, points.flat());
let dstQuad = cv.matFromArray(4, 1, cv.CV_32FC2, [0, 0, img.cols, 0, img.cols, img.rows, 0, img.rows]);
let transmtx = cv.getPerspectiveTransform(srcQuad, dstQuad);
let target = new cv.Mat();
cv.warpPerspective(img, target, transmtx, new cv.Size(img.cols, img.rows));
// 显示结果
cv.imshow(canvas, target);
// 创建一个临时的 canvas 元素
let tempCanvas = document.createElement('canvas');
tempCanvas.width = target.cols;
tempCanvas.height = target.rows;
let tempCtx = tempCanvas.getContext('2d');
// 将 cv.Mat 转换为 ImageData
let imageData = new ImageData(new Uint8ClampedArray(target.data), target.cols, target.rows);
// 将 ImageData 绘制到临时的 canvas 上
tempCtx.putImageData(imageData, 0, 0);
// 将 canvas 生成 Blob 对象
tempCanvas.toBlob((blob) => {
// 创建一个 URL 对象
let url = URL.createObjectURL(blob);
// 创建一个 a 元素并设置其属性
let a = document.createElement('a');
a.href = url;
a.download = 'processed_image.png'; // 设置下载文件的名称
// 将 a 元素添加到 body 中
document.body.appendChild(a);
// 触发点击事件以开始下载
a.click();
// 下载完成后移除 a 元素
document.body.removeChild(a);
// 释放 URL 对象
URL.revokeObjectURL(url);
}, 'image/png');
// 释放内存
target.delete(); // 在这里释放 target,否则会造成内存泄露
}
// 释放内存
img.delete();
dst.delete();
gray.delete(); // 释放灰度图像 Mat
contours.delete();
hierarchy.delete();
approx.delete();
foundContour.delete();
} catch (err) {
console.error("图像处理出现错误:", err);
}
}
imgElement.onerror = function() {
console.error("Image could not be loaded.");
};
}
</script>
</body>
</html>通过上述改进,我成功解决了投影变换后结果为空白透明图片的问题。希望这些改进对大家也有帮助。
以上就是如何解决OpenCV.js投影变换后结果为空白透明图片的问题?的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号