【教程】Autojs使用OpenCV进行SIFT/BRISK等算法进行图像匹配
转载请注明出处:小锋学长生活大爆炸[xfxuezhang.cn]
此代码可以替代内置的images.findImage函数使用,但可能会误匹配,如果是对匹配结果要求比较高的,还是得谨慎使用。
runtime.images.initOpenCvIfNeeded();
importClass(java.util.ArrayList);
importClass(java.util.List);
importClass(java.util.LinkedList);
importClass(org.opencv.imgproc.Imgproc);
importClass(org.opencv.imgcodecs.Imgcodecs);
importClass(org.opencv.core.Core);
importClass(org.opencv.core.Mat);
importClass(org.opencv.core.MatOfDMatch);
importClass(org.opencv.core.MatOfKeyPoint);
importClass(org.opencv.core.MatOfRect);
importClass(org.opencv.core.Size);
importClass(org.opencv.features2d.DescriptorMatcher);
importClass(org.opencv.features2d.Features2d);
importClass(org.opencv.features2d.SIFT);
importClass(org.opencv.features2d.ORB);
importClass(org.opencv.features2d.BRISK);
importClass(org.opencv.features2d.AKAZE);
importClass(org.opencv.features2d.BFMatcher);
importClass(org.opencv.core.MatOfPoint2f);
importClass(org.opencv.calib3d.Calib3d);
importClass(org.opencv.core.CvType);
importClass(org.opencv.core.Point);
importClass(org.opencv.core.Scalar);
importClass(org.opencv.core.MatOfByte);/** 用法示例:* var image1 = captureScreen();* var image2 = images.read('xxxx');* match(image1, image2);*/function match(img1, img2, method) {console.time("匹配耗时");// 指定特征点算法SIFTvar match_alg = null;if(method == 'sift') {match_alg = SIFT.create();}else if(method == 'orb') {match_alg = ORB.create();}else if(method == 'brisk') {match_alg = BRISK.create();}else {match_alg = AKAZE.create();}var bigTrainImage = Imgcodecs.imdecode(new MatOfByte(images.toBytes(img1)), Imgcodecs.IMREAD_UNCHANGED);var smallTrainImage = Imgcodecs.imdecode(new MatOfByte(images.toBytes(img2)), Imgcodecs.IMREAD_UNCHANGED);// 转灰度图// console.log("转灰度图");var big_trainImage_gray = new Mat(bigTrainImage.rows(), bigTrainImage.cols(), CvType.CV_8UC1);var small_trainImage_gray = new Mat(smallTrainImage.rows(), smallTrainImage.cols(), CvType.CV_8UC1);Imgproc.cvtColor(bigTrainImage, big_trainImage_gray, Imgproc.COLOR_BGR2GRAY);Imgproc.cvtColor(smallTrainImage, small_trainImage_gray, Imgproc.COLOR_BGR2GRAY);// 获取图片的特征点// console.log("detect");var big_keyPoints = new MatOfKeyPoint();var small_keyPoints = new MatOfKeyPoint();match_alg.detect(bigTrainImage, big_keyPoints);match_alg.detect(smallTrainImage, small_keyPoints);// 提取图片的特征点// console.log("compute");var big_trainDescription = new Mat(big_keyPoints.rows(), 128, CvType.CV_32FC1);var small_trainDescription = new Mat(small_keyPoints.rows(), 128, CvType.CV_32FC1);match_alg.compute(big_trainImage_gray, big_keyPoints, big_trainDescription);match_alg.compute(small_trainImage_gray, small_keyPoints, small_trainDescription);// console.log("matcher.train");var matcher = new BFMatcher();matcher.clear();var train_desc_collection = new ArrayList();train_desc_collection.add(big_trainDescription);// vector<Mat>train_desc_collection(1, trainDescription);matcher.add(train_desc_collection);matcher.train();// console.log("knnMatch");var matches = new ArrayList();matcher.knnMatch(small_trainDescription, matches, 2);//对匹配结果进行筛选,依据distance进行筛选// console.log("对匹配结果进行筛选");var goodMatches = new ArrayList();var nndrRatio = 0.8;var len = matches.size();for (var i = 0; i < len; i++) {var matchObj = matches.get(i);var dmatcharray = matchObj.toArray();var m1 = dmatcharray[0];var m2 = dmatcharray[1];if (m1.distance <= m2.distance * nndrRatio) {goodMatches.add(m1);}}var matchesPointCount = goodMatches.size();//当匹配后的特征点大于等于 4 个,则认为模板图在原图中,该值可以自行调整if (matchesPointCount >= 4) {log("模板图在原图匹配成功!");var templateKeyPoints = small_keyPoints;var originalKeyPoints = big_keyPoints;var templateKeyPointList = templateKeyPoints.toList();var originalKeyPointList = originalKeyPoints.toList();var objectPoints = new LinkedList();var scenePoints = new LinkedList();var goodMatchesList = goodMatches;var len = goodMatches.size();for (var i = 0; i < len; i++) {var goodMatch = goodMatches.get(i);objectPoints.addLast(templateKeyPointList.get(goodMatch.queryIdx).pt);scenePoints.addLast(originalKeyPointList.get(goodMatch.trainIdx).pt);}var objMatOfPoint2f = new MatOfPoint2f();objMatOfPoint2f.fromList(objectPoints);var scnMatOfPoint2f = new MatOfPoint2f();scnMatOfPoint2f.fromList(scenePoints);//使用 findHomography 寻找匹配上的关键点的变换var homography = Calib3d.findHomography(objMatOfPoint2f, scnMatOfPoint2f, Calib3d.RANSAC, 3);/*** 透视变换(Perspective Transformation)是将图片投影到一个新的视平面(Viewing Plane),也称作投影映射(Projective Mapping)。*/var templateCorners = new Mat(4, 1, CvType.CV_32FC2);var templateTransformResult = new Mat(4, 1, CvType.CV_32FC2);var templateImage = smallTrainImage;var doubleArr = util.java.array("double", 2);doubleArr[0] = 0;doubleArr[1] = 0;templateCorners.put(0, 0, doubleArr);doubleArr[0] = templateImage.cols();doubleArr[1] = 0;templateCorners.put(1, 0, doubleArr);doubleArr[0] = templateImage.cols();doubleArr[1] = templateImage.rows();templateCorners.put(2, 0, doubleArr);doubleArr[0] = 0;doubleArr[1] = templateImage.rows();templateCorners.put(3, 0, doubleArr);//使用 perspectiveTransform 将模板图进行透视变以矫正图象得到标准图片Core.perspectiveTransform(templateCorners, templateTransformResult, homography);//矩形四个顶点var pointA = templateTransformResult.get(0, 0);var pointB = templateTransformResult.get(1, 0);var pointC = templateTransformResult.get(2, 0);var pointD = templateTransformResult.get(3, 0);var y0 = Math.round(pointA[1])>0?Math.round(pointA[1]):0;var y1 = Math.round(pointC[1])>0?Math.round(pointC[1]):0;var x0 = Math.round(pointD[0])>0?Math.round(pointD[0]):0;var x1 = Math.round(pointB[0])>0?Math.round(pointB[0]):0;console.timeEnd("匹配耗时");return {x: x0, y: y0};} else {console.timeEnd("匹配耗时");log("模板图不在原图中!");return null;}
}相关文章:
【教程】Autojs使用OpenCV进行SIFT/BRISK等算法进行图像匹配
转载请注明出处:小锋学长生活大爆炸[xfxuezhang.cn] 此代码可以替代内置的images.findImage函数使用,但可能会误匹配,如果是对匹配结果要求比较高的,还是得谨慎使用。 runtime.images.initOpenCvIfNeeded(); importClass(java.uti…...
[庆国庆 迎国庆 发文]云计算的概念
庆国庆 迎国庆 国庆发文100%可得专属勋章 一年仅有一次哦 不要错过啦 去发布 https://activity.csdn.net/creatActivity?id10567&spm1011.2480.3001.6900 https://mp.csdn.net/edit?activity_id10567&spm1057.2600.3001.9674 云计算(cloud computing&…...
计算机网络-计算机网络体系结构-概述,模型
目录 一、计算机网络概述 二、性能指标 速率 带宽 吞吐量 时延 往返时延RTT 利用率 三、计算机网络体系结构 分层结构 IOS模型 应用层-> 表示层-> 会话层-> 传输层-> 网络层-> 数据链路层-> 物理层-> TCP/IP模型 一、计算机网络概述 计…...
对示例程序spinner_asyncio.py进行修改使其能运行
学习《流畅的python》第18章 使用asyncio包处理并发,运行示例18-2 spinner_asyncio.py的时候,程序报错如下: D:\fluentPy\chapter17>python spinner_asyncio.py File "D:\fluentPy\chapter17\spinner_asyncio.py", line 30 …...
Linux命令(93)之head
linux命令之head 1.head介绍 linux命令head用来查看文件的前N行内容;默认head查看前10行 2.head用法 head [参数] 文件 head常用参数 参数说明-n从头显示N行,默认显示10行,可以不写-q隐藏文件名,在查看两个及以上文件名的情况…...
使用Visual Studio调试排查Windows系统程序audiodg.exe频繁弹出报错
VC常用功能开发汇总(专栏文章列表,欢迎订阅,持续更新...)https://blog.csdn.net/chenlycly/article/details/124272585C软件异常排查从入门到精通系列教程(专栏文章列表,欢迎订阅,持续更新...&a…...
WebSocket实战之六心跳重连机制
一、前言 WebSocket应用部署到生产环境,我们除了会碰到因为经过代理服务器无法连接的问题(注:该问题可以通过搭建WSS来解决,具体配置请看 WebSocket实战之四WSS配置 ),另外一个问题就是外网环境不稳定经常…...
Webpack 基础入门以及接入 CSS、Typescript、Babel
一、什么是 Webpack Webpack 是一款 JS 模块化开发的技术框架,其运作原理是将多个 JS 文件关联起来构成可运行的应用程序。 Webpack 拥有丰富的 plugins / loaders 插件生态圈,可以让 js 识别不同的语言如 .css, .scss, .sass, .json, .xml, .ts, .vue…...
postgresql-自增字段
postgresql-自增字段 标识列IdentitySerial类型Sequence序列 标识列Identity -- 测试表 create table t_user( -- 标识列自增字段user_id integer generated always as identity primary key,user_name varchar(50) not null unique );-- 自动生成序列 CREATE SEQUENCE public…...
SpringBoot中使用Servlet和Filter
为什么要把Servlet和Filter写在一起,因为使用方式很相似 两种方式 第一种,使用Servlet和Filter 使用Servlet 继承HttpServlet 注册Servlet 使用Filter 1.自定义过滤器 2.注册过滤器 这里注意一点 使用/**无效 至少我这2.4.5版本是这样 过滤所有请求用/* 那么其实还有…...
Monkey命令
shell, monkey, system, Android, 文件系统Monkey, 示例, 简介 一、Monkey测试简介 Monkey测试是Android平台自动化测试的一种手段,通过Monkey程序模拟用户触摸屏幕、滑动Trackball、按键等操作来对设备上的程序进行压 力测试,检测程序多久的时间会发生…...
力扣 -- 279. 完全平方数(完全背包问题)
解题步骤: 参考代码: 未优化代码: class Solution { public:int numSquares(int n) {const int INF0x3f3f3f3f;int msqrt(n);//多开一行,多开一列vector<vector<int>> dp(m1,vector<int>(n1));//初始化第一行…...
在将对象 => JSON格式时,无法序列化部分属性
问题现象: 在ssm项目中,一个controller返回Msg对象(自定义对象,包含三个属性,int code;String msg;HashMap map;同时这三个属性都有对应的get和set方法),我的map属性里面…...
用python表格初级尝试
Excel,我的野心 当我输入3,2 就表示在第3行第2列。的单元格输入数据input输入表头 (input内除了/,空格 回车 标点符号等 全部作为单元格分隔符)由我设置input输入的是行or列 给选项 1. 行 2. 列默认回车或没输入值是列由我设置起…...
【单片机】16-LCD1602和12864显示器
1.LCD显示器相关背景 1.LCD简介 (1)显示器,常见显示器:电视,电脑 (2)LCD(Liquid Crystal Display),液晶显示器,原理介绍 (3ÿ…...
AUTOSAR从入门到精通-基于 CAN 总线的汽车发电机智能调节器(下)
目录 4.4.3 CAN 通信软件实现 汽车发电机智能调节器试验与结果分析 5.1 试验方案设计...
Windows下Tensorflow docker python开发环境搭建
前置条件 windows10 更新到较新的版本,硬件支持Hyper-V。 参考:https://learn.microsoft.com/zh-cn/windows/wsl/install 启用WSL 在Powershell中输入如下指令: dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsys…...
idea常用快捷键 idea搜索快捷键
常用快捷键 IntelliJ IDEA 是一款流行的 Java 集成开发环境(IDE),有许多常用的快捷键可以帮助开发者提高效率。以下是一些常用的 IntelliJ IDEA 快捷键: CtrlSpace:基本代码补全,用于输入任何东西&#x…...
Redis Cluster Gossip Protocol: MEET
返回目录 CLUSTER MEET 过程说明 #mermaid-svg-dp95n6LRjBO1mCKE {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-dp95n6LRjBO1mCKE .error-icon{fill:#552222;}#mermaid-svg-dp95n6LRjBO1mCKE .error-text{fill:#…...
TcpConnection的读写操作【深度剖析】
文章目录 前言一、TcpConnection的读二、TcpConnection的写三、TcpConnection的关闭 前言 今天总结TcpConnection类的读写事件。 一、TcpConnection的读 当Poller检测到套接字的Channel处于可读状态时,会调用Channel的回调函数,回调函数中根据不同激活…...
【Oracle APEX开发小技巧12】
有如下需求: 有一个问题反馈页面,要实现在apex页面展示能直观看到反馈时间超过7天未处理的数据,方便管理员及时处理反馈。 我的方法:直接将逻辑写在SQL中,这样可以直接在页面展示 完整代码: SELECTSF.FE…...
Rust 异步编程
Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...
汇编常见指令
汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX(不访问内存)XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...
【HTTP三个基础问题】
面试官您好!HTTP是超文本传输协议,是互联网上客户端和服务器之间传输超文本数据(比如文字、图片、音频、视频等)的核心协议,当前互联网应用最广泛的版本是HTTP1.1,它基于经典的C/S模型,也就是客…...
Go 并发编程基础:通道(Channel)的使用
在 Go 中,Channel 是 Goroutine 之间通信的核心机制。它提供了一个线程安全的通信方式,用于在多个 Goroutine 之间传递数据,从而实现高效的并发编程。 本章将介绍 Channel 的基本概念、用法、缓冲、关闭机制以及 select 的使用。 一、Channel…...
脑机新手指南(七):OpenBCI_GUI:从环境搭建到数据可视化(上)
一、OpenBCI_GUI 项目概述 (一)项目背景与目标 OpenBCI 是一个开源的脑电信号采集硬件平台,其配套的 OpenBCI_GUI 则是专为该硬件设计的图形化界面工具。对于研究人员、开发者和学生而言,首次接触 OpenBCI 设备时,往…...
django blank 与 null的区别
1.blank blank控制表单验证时是否允许字段为空 2.null null控制数据库层面是否为空 但是,要注意以下几点: Django的表单验证与null无关:null参数控制的是数据库层面字段是否可以为NULL,而blank参数控制的是Django表单验证时字…...
前端高频面试题2:浏览器/计算机网络
本专栏相关链接 前端高频面试题1:HTML/CSS 前端高频面试题2:浏览器/计算机网络 前端高频面试题3:JavaScript 1.什么是强缓存、协商缓存? 强缓存: 当浏览器请求资源时,首先检查本地缓存是否命中。如果命…...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现指南针功能
指南针功能是许多位置服务应用的基础功能之一。下面我将详细介绍如何在HarmonyOS 5中使用DevEco Studio实现指南针功能。 1. 开发环境准备 确保已安装DevEco Studio 3.1或更高版本确保项目使用的是HarmonyOS 5.0 SDK在项目的module.json5中配置必要的权限 2. 权限配置 在mo…...
32位寻址与64位寻址
32位寻址与64位寻址 32位寻址是什么? 32位寻址是指计算机的CPU、内存或总线系统使用32位二进制数来标识和访问内存中的存储单元(地址),其核心含义与能力如下: 1. 核心定义 地址位宽:CPU或内存控制器用32位…...
