我在使用 OpenCV (JS) 定位转换后的图像时遇到困难。 基本上,我上传一张图像,选择图像的四个点(四个角),然后将其转换为从鸟瞰图显示。
如果我有意从左上、右上、右下、左下选择点,则变换后图像的方向将与原始图像相同。 但是,如果我从右下角逆时针选择点,方向就会翻转。
有哪些方法可以将源点保留为 [[左上 x,y]、[右上 x,y]、[右下 x,y]、[左下 x,y] ]?
我从源点返回的数字数组如下:
const srcPoints = [261, 35.5, 514, 23.5, 677, 487.5, 181, 538.5];
这是我的整个转换逻辑:
export function transformPerspective({
originalImage,
padding,
srcPoints,
}: TransformPerspective): Promise<HTMLImageElement> {
return new Promise((resolve) => {
let img = new Image();
img.id = "konvaImage";
img.src = originalImage;
img.style.display = "none";
document.body.appendChild(img);
img.onload = () => {
// here the srcPoints need to be sorted in the top-left/top-right/bottom-right/bottom-left order
let srcTri = cv.matFromArray(4, 1, cv.CV_32FC2, srcPoints);
const dstWidth = 900;
const dstHeight = 1000;
let dstTri = cv.matFromArray(4, 1, cv.CV_32FC2, [
padding,
padding,
dstWidth - padding,
padding,
dstWidth - padding,
dstHeight - padding,
padding,
dstHeight - padding,
]);
let matrix = cv.getPerspectiveTransform(srcTri, dstTri);
let dsize = new cv.Size(dstWidth, dstHeight);
let myimg = cv.imread(
document.querySelector("#konvaImage") as HTMLImageElement
);
let warpedImage = new cv.Mat();
cv.warpPerspective(myimg, warpedImage, matrix, dsize);
const outputCanvas = document.createElement("canvas");
outputCanvas.id = "outputCanvas";
outputCanvas.width = 900;
outputCanvas.height = 1000;
outputCanvas.style.display = "none";
document.body.append(outputCanvas);
cv.imshow("outputCanvas", warpedImage);
const imageFromCanvas = new window.Image();
imageFromCanvas.src = outputCanvas.toDataURL();
// cleanup
myimg.delete();
warpedImage.delete();
matrix.delete();
srcTri.delete();
dstTri.delete();
outputCanvas.remove();
// used to update my canvas image
resolve(imageFromCanvas);
};
});
}
有什么想法吗?
只需创建一个辅助函数来按左上/右上/右下/左下顺序对源点进行排序:
function sortSourcePoints(srcPoints) {
const sortedPoints = [...srcPoints];
sortedPoints.sort((a, b) => {
if (a < b) return -1;
if (a > b) return 1;
return 0;
});
const [topLeft, topRight, bottomRight, bottomLeft] = sortedPoints;
return [topLeft, topRight, bottomRight, bottomLeft];
}
然后,更新您的
transformPerspective
函数以使用排序后的源点:
export function transformPerspective({
originalImage,
padding,
srcPoints,
}: TransformPerspective): Promise<HTMLImageElement> {
return new Promise((resolve) => {
// ...
img.onload = () => {
const sortedSrcPoints = sortSourcePoints(srcPoints);
// ...
let srcTri = cv.matFromArray(4, 1, cv.CV_32FC2, sortedSrcPoints);
// ...
};
// ...
});
}