牙叔教程 简单易学
使用场景
两张图片找不同, 大家来找茬之类的
效果展示
autojs版本
8.8.7-0
get知识点
- 灰度
- 图片做减法
- 高斯滤波
- 闭运算( 先膨胀, 再腐蚀 )
- 查找轮廓
- 查找最小外接矩形
- 计算矩形中心
- 计算轮廓面积
- 遍历轮廓点位
- 画轮廓
- 构造Size
- 构造Scalar
- MatOfPoint转MatOfPoint2f
流程图
代码讲解
1. 读取图片
var path = "测试图片.png"; var img = images.read(path); path = "测试图片有绿圈.png"; var img2 = images.read(path);
2. 获取mat
let src1Mat = img.getMat(); let src2Mat = img2.getMat();
3. 颜色空间转换 灰度图
let src1MatGray = new Mat(); let src2MatGray = new Mat(); Imgproc.cvtColor(src1Mat, src1MatGray, Imgproc.COLOR_BGR2GRAY); Imgproc.cvtColor(src2Mat, src2MatGray, Imgproc.COLOR_BGR2GRAY);
4. 图片做减法
var dst = new Mat(); Core.subtract(src2MatGray, src1MatGray, dst);
5. 保存做了减法的图片
var subtractImg = images.matToImage(dst); let subtractImgPath = files.join(files.getSdcardPath(), "图片减法.png"); images.save(subtractImg, subtractImgPath);
6. 高斯滤波
let 高斯滤波后的图像 = new Mat(); Imgproc.GaussianBlur(dst, 高斯滤波后的图像, newSize(5), 3, 3);
7. 闭运算 (先膨胀后腐蚀)
let 闭运算后的图像 = new Mat(); Imgproc.morphologyEx( 高斯滤波后的图像, 闭运算后的图像, Imgproc.MORPH_CLOSE, Imgproc.getStructuringElement(Imgproc.MORPH_RECT, newSize(5)) );
8. 查找轮廓
let contours = new java.util.ArrayList(); let hierarchy = new Mat(); Imgproc.findContours(闭运算后的图像, contours, hierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);
9. 遍历轮廓, 提取数据
let bigArr = []; let cxyArr = []; let areaArr = []; for (let i = 0; i < contours.size(); ++i) { let item = contours.get(i); // 最小外接矩形 let rotateRect = Imgproc.minAreaRect(new MatOfPoint2f(item.toArray())); // 矩形中心 cxyArr.push([rotateRect.center.x, rotateRect.center.y]); // 轮廓面积 let area = Math.abs(Imgproc.contourArea(item)); areaArr.push(area); var len = item.size(); let arr = []; // 提取轮廓坐标 for (var w = 0; w < len.width; w++) { for (var h = 0; h < len.height; h++) { arr.push(item.get(h, w)); } } bigArr.push(arr); }
10. 画面积较大的轮廓
var len = bigArr.length; for (var i = 0; i < len; i++) { if (areaArr[i] < 10000) { continue; } let arr = bigArr[i]; var arrLen = arr.length; path.moveTo(arr[0][0], arr[0][1]); for (var j = 1; j < arrLen; j++) { path.lineTo(arr[j][0], arr[j][1]); } path.close(); // 画轮廓 canvas.drawPath(path, paint); // 画轮廓中心 let xy = cxyArr[i]; canvas.drawPoint(xy[0], xy[1], paint); }
11. 保存图片
var image = canvas.toImage(); images.save(image, "/sdcard/tmp.png");
12. 释放资源
img.recycle(); img2.recycle(); subtractImg.recycle(); image.recycle(); src1Mat.release(); src2Mat.release(); src1MatGray.release(); src2MatGray.release(); dst.release(); 高斯滤波后的图像.release(); 闭运算后的图像.release(); hierarchy.release();
13. 打开图片
app.viewFile("/sdcard/tmp.png");
相关知识点
1. 另一种图片减法
Core.absdiff(src2MatGray, src1MatGray, dst);
2. findContours 参数轮廓的检索模式, 定义轮廓的近似方法
findContours( InputOutputArray image, OutputArrayOfArrays contours, OutputArray hierarchy, int mode, int method, Point offset=Point()); 取值一:CV_RETR_EXTERNAL只检测最外围轮廓,包含在外围轮廓内的内围轮廓被忽略 取值一:CV_CHAIN_APPROX_NONE 保存物体边界上所有连续的轮廓点到contours向量内 取值二:CV_CHAIN_APPROX_SIMPLE 仅保存轮廓的拐点信息
3. Scalar
color = new Scalar(0,255,0) color = new Scalar(199);
4. drawContours
Imgproc.drawContours(闭运算后的图像, contours, idx, color, Core.FILLED, 8, hierarchy);
参考文章
- Opencv求轮廓的中心点坐标
- OpenCV中的findContours函数参数详解
- 高斯滤波
- 开运算、闭运算操作
- 使用OPENCV查找两张图片不同的部分
......太多了, 起码参考了几十张帖子
声明
部分内容来自网络
本教程仅用于学习, 禁止用于其他用途