统一管理网站系统,百度搜不到自己的网站,用wordpress主题首页,软件开发前景和发展基础介绍模板匹配是指在当前图像A里寻找与图像B最相似的部分#xff0c;本文中将图像A称为模板图像#xff0c;将图像B称为搜索匹配图像。引言#xff1a;一般在Opencv里实现此种功能非常方便#xff1a;直接调用result cv2.matchTemplate(templ, search, method)templ 为…基础介绍模板匹配是指在当前图像A里寻找与图像B最相似的部分本文中将图像A称为模板图像将图像B称为搜索匹配图像。引言一般在Opencv里实现此种功能非常方便直接调用result cv2.matchTemplate(templ, search, method)templ 为原始图像search 为搜索匹配图像它的尺寸必须小于或等于原始图像method 表示匹配方式method一般取值 type CompareWay | CV_TM_SQDIFF| CV_TM_SQDIFF_NORMED| CV_TM_CCORR| CV_TM_CCORR_NORMED| CV_TM_CCOEFF| CV_TM_CCOEFF_NORMED;
当然这里我们不是主要讲Opencv的api的只是单独提出来说明在前端实现对应的算法就能进行模板匹配。比如以CV_TM_SQDIFF算法为例 遍历的起始坐标从原图A的左数第1个像素值开始 以搜索匹配B图的大小w * h匹配比较原图上对应空间上(w * h)的像素值 依次进行A图右移一像素去匹配B图直到A图右侧(w)小于B图的w然后换行再匹配 重复进行到A图距离底部不支持h大于B图的高度 最后找出最小误差值我们的目标是实现这两张图的匹配 这里实现对应的js算法/*** 差值平方和匹配 CV_TM_SQDIFF* param template 匹配的图片灰度值[x,x,x,...] w * h 长度的灰度图片数据* param search 搜索的图片灰度值[x,x,x,...] w * h 长度的灰度图片数据* param tWidth 匹配图片的width* param tHeight 匹配图片的height* param sWidth 搜索图片的width* param sHeight 搜索图片的height*/
const cvTmSqDiff (template, search, tWidth, tHeight, sWidth, sHeight) {let minValue Infinity;let x -1;let y -1;for (let th 0; th tHeight; th 1) {for (let tW 0; tW tWidth; tW 1) {if (tW sWidth tWidth || th sHeight tHeight) {continue;}let sum 0;for (let sH 0; sH sHeight; sH 1) {for (let sW 0; sW sWidth; sW 1) {const tValue template[(th sH) * tWidth tW sW];const sValue search[sH * sWidth sW];sum (tValue - sValue) * (tValue - sValue);}}if (minValue sum) {minValue sum;x tW;y th;}if (sum 0) {return { x, y };}}}return { x, y };
};
因此根据上述算法的可行性我们可以先将A图和B图进行RGB值转Gary值 借鉴OpenCV中的转换方式Gray 0.299*r 0.587*g 0.114*b
再将转换好A图和B图的灰度值进行匹配比较const {x, y} cvTmSqDiff(template, search, tWidth, tHeight, sWidth, sHeight);
得到的x、y则是在原图A上的对应匹配成功的坐标加上对应B图的大小我们则可以在原图的基础上画出一个矩形框表示匹配的区域 前端分步实现上面大概讲了匹配的大致实现思路下面开始正式的js代码实现 1、加载原图A和原图BPromise.all([imgLoader(./lena.png), imgLoader(./search.png)]).then((values: any) {...}
);
2、得到图片数据的rgb值并转化为灰度值Promise.all([getImageData(values[0]), getImageData(values[1])]).then((dataValues: any) {const model rgbToGary(dataValues[0]);const search rgbToGary(dataValues[1]);...}
);
3、获取对应的匹配坐标const posi getTemplatePos(model,search,dataValues[0].width,dataValues[0].height,dataValues[1].width,dataValues[1].height,CV_TM_CCOEFF_NORMED
);
4、绘制原图和匹配到矩形框const canvas document.createElement(canvas);
canvas.width dataValues[0].width;
canvas.height dataValues[0].height;
const ctx canvas.getContext(2d);ctx.drawImage(values[0], 0, 0);
ctx.strokeStyle red;
ctx.strokeRect(posi.x,posi.y,dataValues[1].width,dataValues[1].height
);
document.body.appendChild(canvas);
上述所用的的函数imgLoader getImageData rgbToGary getTemplatePos 都可以在这里找到xy-imageloader 也可以npm安装npm i xy-imageloader 完整代码import imgLoader, { getImageData, rgbToGary } from xy-imageloader;
import { getTemplatePos } from xy-imageloader/lib/utils;
Promise.all([imgLoader(./lena.png), imgLoader(./search.png)]).then((values: any) {Promise.all([getImageData(values[0]), getImageData(values[1])]).then((dataValues: any) {const model rgbToGary(dataValues[0]);const search rgbToGary(dataValues[1]);const posi getTemplatePos(model,search,dataValues[0].width,dataValues[0].height,dataValues[1].width,dataValues[1].height,CV_TM_CCOEFF_NORMED);const canvas document.createElement(canvas);canvas.width dataValues[0].width;canvas.height dataValues[0].height;const ctx canvas.getContext(2d);ctx.drawImage(values[0], 0, 0);ctx.strokeStyle red;ctx.strokeRect(posi.x,posi.y,dataValues[1].width,dataValues[1].height);document.body.appendChild(canvas);});}
);
附算法思想 * CV_TM_SQDIFF CV_TM_SQDIFF_NORMED CV_TM_CCORR CV_TM_CCORR_NORMED CV_TM_CCOEFF CV_TM_CCOEFF_NORMED 算法具体实现可参考 xy-imageloader