场景
通常web前端想对图片做裁切,用的较多的前端组件比如Cropper.js,裁切都是规则矩形裁切
进入官网对应的演练场,可以看到矩形裁切的功能
如果我们的场景是,需要裁切的照片如下面所示,拍摄时不是垂直拍摄,按我的专业方向来说就是非正射照片,需要选取的四边形区域不是正正好好的矩形,会有一定的变形,如图片中框定的红色区域所示,那么Cropper.js等只能规则矩形裁剪的前端库就不适用了!
这里我找到的方法就是利用opencv.js来实现在web前端场景做四边形非矩形裁剪
opencv.js
本科和研究生时候用C++做遥感图像处理时,学习和用到opencv,它的功能超级强大,通过官网可以了解到现在借助WebAssembly,已经可以在web端发挥它的能力了!
示例代码
下面是我做的一个简单的html示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>OpenCV.js Perspective Transform</title>
<style>
canvas {
border: 1px solid black;
}
</style>
</head>
<body>
<h1>OpenCV.js Perspective Transform</h1>
<h3 id="status">Loading the Opencv ...</h3>
<input type="file" id="fileInput" accept="image/*" />
<canvas id="canvas"></canvas>
<canvas id="outputCanvas"></canvas>
<script>
let imgElement = new Image();
let points = [];
const maxPoints = 4;
document
.getElementById("fileInput")
.addEventListener("change", (event) => {
const file = event.target.files[0];
const reader = new FileReader();
reader.onload = function (e) {
imgElement.src = e.target.result;
};
reader.readAsDataURL(file);
});
imgElement.onload = function () {
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
canvas.width = imgElement.width;
canvas.height = imgElement.height;
ctx.drawImage(imgElement, 0, 0);
points = [];
canvas.addEventListener("click", getPoint);
};
function getPoint(event) {
if (points.length < maxPoints) {
const canvas = document.getElementById("canvas");
const rect = canvas.getBoundingClientRect();
const x = event.clientX - rect.left;
const y = event.clientY - rect.top;
points.push([x, y]);
drawPoint(x, y);
if (points.length === maxPoints) {
performPerspectiveTransform();
}
}
}
function drawPoint(x, y) {
const ctx = document.getElementById("canvas").getContext("2d");
ctx.fillStyle = "red";
ctx.beginPath();
ctx.arc(x, y, 5, 0, Math.PI * 2);
ctx.fill();
}
function performPerspectiveTransform() {
const srcPoints = cv.matFromArray(4, 1, cv.CV_32FC2, points.flat());
const dstPoints = cv.matFromArray(4, 1, cv.CV_32FC2, [
0,
0,
imgElement.width,
0,
imgElement.width,
imgElement.height,
0,
imgElement.height,
]);
const M = cv.getPerspectiveTransform(srcPoints, dstPoints);
const src = cv.imread("canvas");
const dst = new cv.Mat();
cv.warpPerspective(
src,
dst,
M,
new cv.Size(imgElement.width, imgElement.height),
cv.INTER_LINEAR,
cv.BORDER_CONSTANT,
new cv.Scalar()
);
cv.imshow("outputCanvas", dst);
src.delete();
dst.delete();
M.delete();
srcPoints.delete();
dstPoints.delete();
}
function onOpenCvReady() {
document.getElementById("status").remove();
}
</script>
<script
async
src="https://docs.opencv.org/4.5.3/opencv.js"
onload="onOpenCvReady();"
type="text/javascript"
></script>
</body>
</html>
初始页面如下打开一张图片显示在左侧,直接在左侧图片顺时针点选四个点
在左侧图片选完四个点自动在右侧裁剪出四个点组成区域的照片,这里其实是用到opencv.js透视变换,大家可以自行根据上面示例代码查看
并最后附上测试图片
附上阿b视频链接