https://docs.opencv.org/4.8.0/opencv.js
function imageLoad(img) {
return new Promise((resolve) => {
img.onload = resolve;
});
}
function findPic(target, template, canvasShow = false){
// # 读取图片
var target_rgb = cv.imread(target)
// # 图片灰度化
let target_gray = new cv.Mat();
cv.cvtColor(target_rgb, target_gray, cv.COLOR_BGR2GRAY)
// # 读取模块图片
var template_rgb = cv.imread(template)
// let channels = new cv.MatVector();
// cv.split(template_rgb, channels);
// let template_gray = channels.get(2); // 灰度图像存储在第三个通道
// channels.delete();
// # 图片灰度化
let template_gray = new cv.Mat();
cv.cvtColor(template_rgb, template_gray, cv.COLOR_BGR2GRAY)
// 创建匹配结果图像对象
let result = new cv.Mat()
// # 匹配模块位置
cv.matchTemplate(target_gray, template_gray, result, cv.TM_CCOEFF_NORMED)
// # 获取最佳匹配位置
value = cv.minMaxLoc(result)
if (canvasShow) {
let maxPoint = value.maxLoc;
let minPoint = value.minLoc;
// 绘制矩形框标记匹配位置
let topLeft = maxPoint;
let bottomRight = new cv.Point(maxPoint.x + template_rgb.cols, maxPoint.y + template_rgb.rows);
let minBottomRight = new cv.Point(minPoint.x + template_rgb.cols, minPoint.y + template_rgb.rows);
var canvas = document.createElement('canvas')
document.body.append(canvas)
// cv.rectangle(target_rgb, topLeft, bottomRight, [255, 0, 0, 255], 2);
cv.rectangle(target_rgb, minPoint, minBottomRight, [255, 0, 0, 255], 2);
console.log(maxPoint, minPoint)
// // 显示匹配结果图像
cv.imshow(canvas, target_rgb);
// bottomRight.delete()
// minBottomRight.delete()
}
// // 释放内存
target_rgb.delete();
target_gray.delete();
template_rgb.delete()
template_gray.delete()
result.delete()
// print(value)
// # 返回最佳X坐标
return value
}
function cropImage(image, startX, startY, endX, endY) {
// 创建一个 Canvas 元素
let canvas = document.createElement('canvas');
let context = canvas.getContext('2d');
// 设置 Canvas 大小与图像宽高一致
canvas.width = endX - startX;
canvas.height = endY - startY;
// 在 Canvas 上绘制裁剪后的图像
context.drawImage(image, startX, startY, canvas.width, canvas.height, 0, 0, canvas.width, canvas.height);
// 创建一个新的图像对象
let croppedImage = new Image();
// 将 Canvas 上的图像数据赋值给新的图像对象
croppedImage.src = canvas.toDataURL();
// 返回裁剪后的图像对象
// return croppedImage;
return canvas
}
function getNotTMImage(templateImg) {
// 创建Canvas对象
var canvas2 = document.createElement('canvas');
var ctx2 = canvas2.getContext('2d');
// 将模板图像绘制到Canvas上并转换为灰度图像
canvas2.width = templateImg.width;
canvas2.height = templateImg.height;
ctx2.clearRect(0, 0, canvas2.width, canvas2.height);
ctx2.drawImage(templateImg, 0, 0);
var templateImageData = ctx2.getImageData(0, 0, templateImg.width, templateImg.height);
var templatePixels = templateImageData.data;
for (var i = 0; i < templatePixels.length; i += 4) {
var alpha = templatePixels[i + 3]; // 获取透明度通道值
if (alpha === 0) {
templatePixels[i] = templatePixels[i + 1] = templatePixels[i + 2] = 0; // 将透明内容设为黑色
} else {
var gray = Math.round(0.2989 * templatePixels[i] + 0.5870 * templatePixels[i + 1] + 0.1140 * templatePixels[i + 2]);
templatePixels[i] = templatePixels[i + 1] = templatePixels[i + 2] = gray; // 转换为灰度图像
}
}
var templatePixels2 = templateImageData.data;
var minX = templateImg.width;
var minY = templateImg.height;
var maxX = 0;
var maxY = 0;
// 计算图形去除透明后的实际宽高
for (var y = 0; y < templateImg.height; y++) {
for (var x = 0; x < templateImg.width; x++) {
var idx = (y * templateImg.width + x) * 4;
var alpha = templatePixels2[idx + 3];
if (alpha !== 0) {
minX = Math.min(minX, x);
minY = Math.min(minY, y);
maxX = Math.max(maxX, x);
maxY = Math.max(maxY, y);
}
}
}
// 计算不透明部分的宽高
var width = maxX - minX + 1;
var height = maxY - minY + 1;
// console.log(width,height)
// // 返回结果
// console.log('不透明部分的宽度:',templateImg.width, width);
// console.log('不透明部分的高度:', height);
ctx2.putImageData(templateImageData, 0, 0);
// 设置Canvas的宽度和高度为裁剪尺寸
canvas2.width = width; // 替换为你想要的裁剪后的宽度
canvas2.height = height; // 替换为你想要的裁剪后的高度
// 绘制裁剪后的图像到Canvas上
ctx2.drawImage(templateImg, minX, minY, width, height, 0, 0, width, height);
var imageData = ctx2.getImageData(0, 0, width, height);
// 创建一个新的Canvas元素和2D上下文对象
var newCanvas = document.createElement("canvas");
var newCtx = newCanvas.getContext("2d");
// 设置新Canvas的宽度和高度为裁剪尺寸
newCanvas.width = width;
newCanvas.height = height;
// 在新Canvas上绘制裁剪的图片数据
newCtx.putImageData(imageData, 0, 0);
const ndataImage = newCanvas.toDataURL()
var newImage = new Image();
newImage.src= ndataImage
return {newImage: newCanvas,minX, minY};
}
const bgImage = document.querySelector('.slider-img-bg')
const itemImage = document.querySelector('.slider-item')
var targetImage = new Image()
targetImage.src = bgImage.src
var {newImage, minX, minY} = getNotTMImage(itemImage)
var sImage = cropImage(targetImage, 0, minY - 10, targetImage.width, minY + newImage.height + 10)
var values = null
try {
values = findPic(sImage, newImage, true)
} catch (error) {
if (typeof err === 'number' && !isNaN(err) ) {
values = findPic(sImage, newImage, true)
} else {
throw error
}
}
const {x} = values.minLoc
const returnX = (x / targetImage.width * bgImage.width) - minX
tigerSetVariable('returnX', returnX)
tigerNextBlock()