前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >用OpenCV加Robot打造Java版按键精灵

用OpenCV加Robot打造Java版按键精灵

作者头像
九转成圣
发布于 2024-04-10 10:28:06
发布于 2024-04-10 10:28:06
39300
代码可运行
举报
文章被收录于专栏:csdncsdn
运行总次数:0
代码可运行

背景

在日常生活开发中,我们时常遇到需要自动化完成的重复性任务,比如自动化测试,还记得在某银行开发某某通软件时,开发要辅助测试,每次项目上线后都要群里发100条消息,真的苦不堪言,每次发版后都要测试(因为之前出现过消息丢失),在比如游戏辅助,比如读取桌面,在桌面内进行人脸识别找到头部,然后鼠标移动到头部,按下鼠标左键进行射击(不要骂我哦,我没有开挂),再比如完成一些日常任务啥的

所涉及技术

Java中的Robot类是用于模拟鼠标和键盘输入的工具,它主要用于自动化测试、屏幕捕捉、模拟用户交互等任务。Robot类提供了以下主要功能:

  1. 模拟键盘输入:Robot类可以模拟键盘按键的输入,包括按下按键、释放按键和组合按键等操作。这使得程序可以自动化执行键盘操作,如输入文本、执行快捷键等。
  2. 模拟鼠标操作:Robot类可以模拟鼠标的移动、点击、拖拽等操作,包括左键、右键和中键的点击,以及鼠标滚轮的滚动。这使得程序可以自动化执行鼠标操作,如点击按钮、拖拽窗口等。
  3. 屏幕捕捉:Robot类可以捕捉屏幕上的图像,包括整个屏幕或指定区域的图像。这使得程序可以获取屏幕上的信息,如截图、图像识别等。
  4. 控制键盘锁定状态:Robot类可以控制键盘的锁定状态,包括大写锁定、数字锁定和滚动锁定等。
  5. 控制鼠标位置:Robot类可以获取和设置鼠标的当前位置,使得程序可以定位和控制鼠标在屏幕上的位置。
  6. 延时操作:Robot类可以设置延时,使得程序可以在执行操作之间添加等待时间,以便适应不同的情况和速度。

OpenCV(开源计算机视觉库)是一个开源的计算机视觉和机器学习软件库,提供了丰富的功能和工具,用于处理图像和视频数据。其主要功能包括但不限于以下几个方面:

  1. 图像处理:包括图像加载、保存、缩放、裁剪、旋转、平移、色彩空间转换(如RGB、HSV等)、图像平滑(模糊、滤波)、图像增强(对比度、亮度调整)、边缘检测、形态学操作(膨胀、腐蚀)、图像分割等。
  2. 视频分析:提供了视频流的读取、处理、分析和写入功能,包括视频的读取、保存、截取、帧间差分、光流估计等。
  3. 特征检测与描述:包括关键点检测(如Harris、SIFT、SURF、FAST等)、描述子生成(如ORB、BRIEF、FREAK等)以及特征匹配算法。
  4. 目标检测与跟踪:包括人脸检测、物体检测(如Haar级联检测器、HOG+SVM检测器等)、目标跟踪(如基于卡尔曼滤波器、均值迁移、CamShift等)。
  5. 摄像头标定:提供了相机标定工具,用于校准相机的内参和外参,用于后续的相机几何校正、立体视觉等应用。
  6. 三维重建与视觉SLAM:包括立体视觉匹配、三维点云重建、结构光三维重建、基于深度学习的三维重建、视觉SLAM(Simultaneous Localization and Mapping)等。
  7. 深度学习集成:提供了深度学习模块,可以用于训练和部署深度学习模型,支持常见的深度学习框架(如TensorFlow、PyTorch)和模型(如Caffe、Darknet、OpenVINO)。
  8. 计算机视觉工具:包括图像匹配、图像拼接、图像检索、目标识别、图像分析、图像修复、图像转换等。

搭建springboot项目,引入opencv依赖

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.2.RELEASE</version>
        <relativePath/>
    </parent>
    <groupId>com.lxw</groupId>
    <artifactId>robot</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>robot-study</name>
    <description>robot-study</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
       
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
       
        <dependency>
            <groupId>org.openpnp</groupId>
            <artifactId>opencv</artifactId>
            <version>4.8.1-0</version>
        </dependency>
 
 
    </dependencies>
 
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
 
</project>

加载opencv库

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    public static void loadOpencv() {
        // 加载opencv库
        System.load(new File("src/main/resources/lib/opencv/opencv_java490.dll").getAbsolutePath());
    }

读取桌面为Mat

mat可以理解为图片的矩阵形式

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public static Mat desktopMat(Robot robot) {
        BufferedImage bi = robot.createScreenCapture(new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()));
        int type = bi.getType();
        System.out.println("type = " + type);
        int width = bi.getWidth();
        int height = bi.getHeight();
        int[] pixels = bi.getRGB(0, 0, width, height, null, 0, width);
        Mat mat = new Mat(height, width, CvType.CV_8UC3);
        byte[] data = new byte[width * height * 3];
        int index = 0;
        for (int y = 0; y < height; y++) {
            for (int x = 0; x < width; x++) {
                int pixel = pixels[y * width + x];
                // 提取 RGB 值并转换为 BGR
                data[index++] = (byte) (pixel & 0xFF); // B
                data[index++] = (byte) ((pixel >> 8) & 0xFF); // G
                data[index++] = (byte) ((pixel >> 16) & 0xFF); // R
            }
        }
        mat.put(0, 0, data);
        return mat;
    }

读取目标图片

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    public static Mat imread(String filename) {
        Mat img = Imgcodecs.imread(filename);
        // 检查图像是否成功加载
        if (img.empty()) {
            throw new RuntimeException("读取图片失败:" + filename);
        }
        return img;
    }

 在桌面范围内查找目标图片并返回中心点坐标

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    public static org.opencv.core.Point findImage(Mat src, Mat template) {
        // 创建结果图像
        Mat result = new Mat();
        // 进行模板匹配
        Imgproc.matchTemplate(src, template, result, Imgproc.TM_CCOEFF_NORMED);

        // 设置匹配阈值
        double threshold = 0.8;

        // 在原始图像中寻找匹配结果
        Core.MinMaxLocResult mmr = Core.minMaxLoc(result);
        org.opencv.core.Point maxLoc = mmr.maxLoc;
        if (mmr.maxVal >= threshold) {
            // 计算匹配区域的右下角坐标
            org.opencv.core.Point matchLoc = new org.opencv.core.Point(maxLoc.x + template.cols(), maxLoc.y + template.rows());
            // 绘制矩形框 此步骤只为展示效果,可注释掉
            Imgproc.rectangle(src, maxLoc, matchLoc, new Scalar(0, 255, 0), 2);
            // 在匹配区域的中心点绘制红色的点 此步骤只为展示效果,可注释掉
            Point center = new Point((maxLoc.x + matchLoc.x) / 2, (maxLoc.y + matchLoc.y) / 2);
            Imgproc.circle(src, center, 5, new Scalar(0, 0, 255), -1);
            // 显示结果 此步骤只为展示效果,可注释掉
            HighGui.imshow("Match Result", src);
            // 此步骤只为展示效果,可注释掉
            HighGui.waitKey();
            return center;
        } else {
            throw new RuntimeException("没有搜索到目标图标");
        }
    }

Robot控制移动到中心点 

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
     public void move(Robot robot,org.opencv.core.Point point){
        robot.mouseMove((int)point.x,(int)point.y);
    }

测试代码

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    public static void main(String[] args) {
        try {
            loadOpencv();
            // 创建 Robot 对象
            Robot robot = new Robot();
            robot.setAutoDelay(500);
            // 模拟ctrl+d快捷键切换到桌面
            robot.keyPress(KeyEvent.VK_WINDOWS);
            robot.keyPress(KeyEvent.VK_D);
            robot.keyRelease(KeyEvent.VK_D);
            robot.keyRelease(KeyEvent.VK_WINDOWS);
            robot.delay(1000);
            // 读取桌面截图
            Mat desktop = desktopMat(robot);
            // 读取 idea图片 
            Mat idea = Imgcodecs.imread("src/main/resources/img/find/idea.png");
            // 区域找图并返回中心点
            Point center = findImage(desktop, idea);
            // 移动到中心点
            move(robot, center);

        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

效果图

在桌面范围内寻找idea图标,找到了用绿色框框起来idea图标,用红色点标记中心位置,

Opencv库路径

Opencv类库见附件

OpenCVUtil

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.opencv.calib3d.Calib3d;
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.DMatch;
import org.opencv.core.Mat;
import org.opencv.core.MatOfByte;
import org.opencv.core.MatOfDMatch;
import org.opencv.core.MatOfKeyPoint;
import org.opencv.core.MatOfPoint2f;
import org.opencv.core.Point;
import org.opencv.core.Rect;
import org.opencv.core.Scalar;
import org.opencv.core.Size;
import org.opencv.features2d.DescriptorMatcher;
import org.opencv.features2d.Feature2D;
import org.opencv.features2d.Features2d;
import org.opencv.features2d.ORB;
import org.opencv.features2d.SIFT;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

@Slf4j
public class OpenCVUtil {
    static {
        // 加载opencv库
        try {
//            System.load(new File("src/main/resources/lib/opencv/opencv_java490.dll").getAbsolutePath());
            System.load(new File("src/main/resources/lib/opencv/opencv_java481.dll").getAbsolutePath());
        } catch (Exception e) {
            log.error("加载加载opencv库跑出异常", e.getMessage());
        }
    }

    /**
     * 读取桌面为Mat
     */
    public static Mat desktopMat(Robot robot) {
        BufferedImage bi = robot.createScreenCapture(new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()));
        int type = bi.getType();
        System.out.println("type = " + type);
        int width = bi.getWidth();
        int height = bi.getHeight();
        int[] pixels = bi.getRGB(0, 0, width, height, null, 0, width);
        Mat mat = new Mat(height, width, CvType.CV_8UC3);
        byte[] data = new byte[width * height * 3];
        int index = 0;
        for (int y = 0; y < height; y++) {
            for (int x = 0; x < width; x++) {
                int pixel = pixels[y * width + x];
                // 提取 RGB 值并转换为 BGR
                data[index++] = (byte) (pixel & 0xFF); // B
                data[index++] = (byte) ((pixel >> 8) & 0xFF); // G
                data[index++] = (byte) ((pixel >> 16) & 0xFF); // R
            }
        }
        mat.put(0, 0, data);
        return mat;
    }

    /**
     * 查找并返回中心点
     * 效果还不错
     *
     * @param original 大图
     * @param target   需要查找的小图
     * @return 找到的小图中心点的坐标
     */
    public static Point findImage(String original, String target) {
        // 读取原始图像和目标图像
        Mat src = imread(original);
        Mat template = imread(target);
        return findImage(src, template);
    }

    public static Point findImage(Mat src, String target) {
        // 读取原始图像和目标图像
        Mat template = imread(target);
        return findImage(src, template);
    }

    public static Point findImage(Mat src, Mat template) {
        // 创建结果图像
        Mat result = new Mat();
        // 进行模板匹配
        Imgproc.matchTemplate(src, template, result, Imgproc.TM_CCOEFF_NORMED);

        // 设置匹配阈值
        double threshold = 0.8;

        // 在原始图像中寻找匹配结果
        Core.MinMaxLocResult mmr = Core.minMaxLoc(result);
        Point maxLoc = mmr.maxLoc;
        if (mmr.maxVal >= threshold) {
            // 计算匹配区域的右下角坐标
            Point matchLoc = new Point(maxLoc.x + template.cols(), maxLoc.y + template.rows());
//            // 输出匹配区域的中心点坐标
//            System.out.println("Match found at: (" + (matchLoc.x + maxLoc.x) / 2 + ", " + (matchLoc.y + maxLoc.y) / 2 + ")");
            // 绘制矩形框
//            Imgproc.rectangle(src, maxLoc, matchLoc, new Scalar(0, 255, 0), 2);
            // 在匹配区域的中心点绘制红色的点
            //            Imgproc.circle(src, center, 5, new Scalar(0, 0, 255), -1);
            // 显示结果
//            HighGui.imshow("Match Result", src);
//            HighGui.waitKey();
            return new Point((maxLoc.x + matchLoc.x) / 2, (maxLoc.y + matchLoc.y) / 2);
        } else {
            throw new RuntimeException("没有搜索到目标图标");
        }
    }

    /**
     * 读取图片
     *
     * @param filename 图片文件全路径
     * @return 图片矩阵
     */
    public static Mat imread(String filename) {
        Mat img = Imgcodecs.imread(filename);
        // 检查图像是否成功加载
        if (img.empty()) {
            throw new RuntimeException("读取图片失败:" + filename);
        }
        return img;
    }

    public static Mat imread(byte[] bytes) {
        MatOfByte matOfByte = new MatOfByte(bytes);
        Mat img = Imgcodecs.imdecode(matOfByte, Imgcodecs.IMREAD_COLOR);
        // 检查图像是否成功加载
        if (img.empty()) {
            throw new RuntimeException("读取图片失败");
        }
        return img;
    }

    /**
     * 写图片
     *
     * @param filename 图片文件全路径
     * @param img      图片矩阵
     * @return 是否写成功
     */
    public static boolean imwrite(String filename, Mat img) {
        return Imgcodecs.imwrite(filename, img);
    }

    /**
     * 生产灰度图片
     *
     * @param img 图片矩阵
     * @return 绘图图片
     */
    public static Mat cvtColor(Mat img) {
        Mat gray = new Mat();
        Imgproc.cvtColor(img, gray, Imgproc.COLOR_BGR2GRAY);
        return gray;
    }

    public static Mat threshold(Mat img) {
        Mat thresh = new Mat();
        Imgproc.threshold(cvtColor(img), thresh, 0, 255, Imgproc.THRESH_BINARY_INV + Imgproc.THRESH_OTSU);
        return thresh;
    }

    /**
     * 用ORB获取关键的和计算描述子
     * 特点:准
     *
     * @param img 图片矩阵
     * @return 特征点和描述子
     */
    public static KeyPointAndDescriptor detectAndCompute4ORB(Mat img) {
        return detectAndCompute(img, ORB.create());
    }

    /**
     * 用SIFT获取关键的和计算描述子
     * 特点:快
     *
     * @param img 图片矩阵
     * @return 特征点和描述子
     */
    public static KeyPointAndDescriptor detectAndCompute4SIFT(Mat img) {
        return detectAndCompute(img, SIFT.create());
    }

    private static KeyPointAndDescriptor detectAndCompute(Mat img, Feature2D detector) {
        Mat gray = cvtColor(img);
        // 检测图像中的关键点
        MatOfKeyPoint keyPoint = new MatOfKeyPoint();
        // 计算关键点的描述子
        Mat descriptor = new Mat();
        // 获取关键点并计算描述子,更常用 第二个参数 Mat mask,感兴趣的区域,空对象表示对整个图操作
        detector.detectAndCompute(gray, new Mat(), keyPoint, descriptor);
        return new KeyPointAndDescriptor(keyPoint, descriptor);
    }

    /**
     * 绘制关键点
     *
     * @param img      图像矩阵
     * @param keyPoint 关键点
     * @return 包含关键点的图片
     */
    private static Mat drawKeypoints(Mat img, MatOfKeyPoint keyPoint) {
        // 绘制关键点
        Mat imgWithKeyPoints = new Mat();
        Features2d.drawKeypoints(img, keyPoint, imgWithKeyPoints);
        return imgWithKeyPoints;
    }


    /**
     * 查找图片并显示矩形和中心点
     *
     * @param original 大图
     * @param target   小图
     */
    public static void findImageWithShow(String original, String target) {

        // 读取原始图像和目标图像
        Mat src = imread(original);
        Mat template = imread(target);
        findImageWithShow(src, template);
    }

    public static void findImageWithShow(Mat src, Mat template) {
        // 创建结果图像
        Mat result = new Mat();
        // 进行模板匹配
        Imgproc.matchTemplate(src, template, result, Imgproc.TM_CCOEFF_NORMED);
        // 设置匹配阈值
        double threshold = 0.8;

        // 在原始图像中寻找匹配结果
        Core.MinMaxLocResult mmr = Core.minMaxLoc(result);
        Point maxLoc = mmr.maxLoc;
        if (mmr.maxVal >= threshold) {
            // 计算匹配区域的右下角坐标
            Point matchLoc = new Point(maxLoc.x + template.cols(), maxLoc.y + template.rows());
//            // 输出匹配区域的中心点坐标
            System.out.println("Match found at: (" + (matchLoc.x + maxLoc.x) / 2 + ", " + (matchLoc.y + maxLoc.y) / 2 + ")");
            // 绘制矩形框
            Imgproc.rectangle(src, maxLoc, matchLoc, new Scalar(0, 255, 0), 2);
            // 在匹配区域的中心点绘制红色的点
            Point center = new Point((maxLoc.x + matchLoc.x) / 2, (maxLoc.y + matchLoc.y) / 2);
            Imgproc.circle(src, center, 5, new Scalar(0, 0, 255), -1);
            // 显示结果
            HighGui.imshow("Match Result", src);
            HighGui.waitKey();
        } else {
            HighGui.imshow("Match Result", src);
            HighGui.waitKey();
//            throw new RuntimeException("没有搜索到目标图标");
        }
    }

    /**
     * 关键的和描述子
     * 描述子:对关键点有贡献的像素
     */
    @Data
    public static class KeyPointAndDescriptor {
        MatOfKeyPoint keyPoint;
        Mat descriptor;

        public KeyPointAndDescriptor(MatOfKeyPoint keyPoint, Mat descriptor) {
            this.keyPoint = keyPoint;
            this.descriptor = descriptor;
        }
    }

    public static Mat montage(String imageName1, String imageName2) {
        Mat image1 = imread(imageName1);
        Mat image2 = imread(imageName2);
        int cols1 = image1.cols();
        int cols2 = image2.cols();
        int rows1 = image1.rows();
        int rows2 = image2.rows();
        if (cols1 == cols2) {
            return montage(image1, image2, false, 50);
        }
        if (rows1 == rows2) {
            return montage(image1, image2, true, 50);
        }
        throw new RuntimeException("宽高都不相同,无法判断是上下拼接或者左右拼接");
    }

    public static Mat montage(String imageName1, String imageName2, boolean isLeftRight) {
        return montage(imageName1, imageName2, isLeftRight, 50);
    }

    public static Mat montage(String imageName1, String imageName2, boolean isLeftRight, int distance) {
        Mat image1 = imread(imageName1);
        Mat image2 = imread(imageName2);
        int cols1 = image1.cols();
        int cols2 = image2.cols();
        int rows1 = image1.rows();
        int rows2 = image2.rows();
        if (isLeftRight) {
            if (rows1 != rows2) {
                Size imageSize = new Size(image2.cols(), Math.max(image1.rows(), image2.rows()));
                Imgproc.resize(image2, image2, imageSize);
            }
        } else {
            if (cols1 != cols2) {
                Size imageSize = new Size(image2.rows(), Math.max(image1.cols(), image2.cols()));
                Imgproc.resize(image2, image2, imageSize);
            }
        }
        return montage(image1, image2, isLeftRight, distance);
    }

    /**
     * 拼图
     *
     * @param image1      左边的或者上边的
     * @param image2      右边的或者下边的
     * @param isLeftRight 是否为左右拼图
     * @param distance    相似度 值越小要求相似度越高
     */
    public static Mat montage(Mat image1, Mat image2, boolean isLeftRight, int distance) {

        // 获取特征点和描述子
        KeyPointAndDescriptor keyPointAndDescriptor1 = detectAndCompute4SIFT(image1);
        KeyPointAndDescriptor keyPointAndDescriptor2 = detectAndCompute4SIFT(image2);
        MatOfKeyPoint keyPoint1 = keyPointAndDescriptor1.getKeyPoint();
        MatOfKeyPoint keyPoint2 = keyPointAndDescriptor2.getKeyPoint();
        Mat descriptors1 = keyPointAndDescriptor1.getDescriptor();
        Mat descriptors2 = keyPointAndDescriptor2.getDescriptor();

        // 创建暴力匹配器
        DescriptorMatcher matcher = DescriptorMatcher.create(DescriptorMatcher.BRUTEFORCE);
        MatOfDMatch matches = new MatOfDMatch();
        matcher.match(descriptors1, descriptors2, matches);

        // 筛选匹配
        LinkedList<DMatch> goodMatchesList = new LinkedList<>();
        List<DMatch> matchesList = matches.toList();
        for (DMatch match : matchesList) {
            // 调整阈值以筛选好的匹配 两个特征点之间的距离(相似度).距离越短,相似度越高
            if (match.distance < distance) {
                goodMatchesList.addLast(match);
            }
        }

        // 提取匹配点对
        List<Point> objList = new LinkedList<>();
        List<Point> sceneList = new LinkedList<>();
        for (int i = 0; i < goodMatchesList.size(); i++) {
            objList.add(keyPoint1.toList().get(goodMatchesList.get(i).queryIdx).pt);
            sceneList.add(keyPoint2.toList().get(goodMatchesList.get(i).trainIdx).pt);
        }

        MatOfPoint2f obj = new MatOfPoint2f();
        obj.fromList(objList);
        MatOfPoint2f scene = new MatOfPoint2f();
        scene.fromList(sceneList);
        if (objList.size() < 4) {
            throw new RuntimeException("计算单应性矩阵所需的点对数量至少为 4 对");
        }

        // 计算单应性矩阵
        Mat homography = Calib3d.findHomography(scene, obj, Calib3d.RANSAC, 5);
        Size size;
        if (isLeftRight) {
            size = new Size(image1.cols() + image2.cols(), image1.rows());
        } else {
            size = new Size(image1.cols(), image1.rows() + image2.rows());
        }
        // 使用单应性矩阵进行图像配准
        Mat result = new Mat();
        Imgproc.warpPerspective(image2, result, homography, size);
        Mat roi = new Mat(result, new Rect(0, 0, image1.cols(), image1.rows()));
        image1.copyTo(roi);
        return result;
    }

    /**
     * 通道分离
     *
     * @param mat
     * @return
     */
    public static List<Mat> split(Mat mat) {
        List<Mat> channels = new ArrayList<>();
        Core.split(mat, channels);
        return channels;
    }

    /**
     * 图片显示
     *
     * @param mats
     */
//    public static void show(LinkedHashMap<String,Mat> mats) {
//        // 获取默认工具包
//        Toolkit toolkit = Toolkit.getDefaultToolkit();
//        // 获取屏幕的尺寸
//        Dimension screenSize = toolkit.getScreenSize();
//        // 输出屏幕宽度和高度
//        int i = 0;
//        int columnCount = 0;
//        for (Map.Entry<String, Mat> entry : mats.entrySet()) {
//            Mat mat = entry.getValue();
//            String winName = entry.getKey();
//            System.out.println("winName = " + winName);
//            HighGui.imshow(winName, mat);
//            int xSpace = 10;
//            int count = i / (screenSize.width / (mat.cols()+ xSpace));
//            int y = count*(mat.rows()+40);
//            int x = (mat.cols()+ xSpace)*columnCount;
//            if(x+mat.cols() > screenSize.width){
//                columnCount = 0;
//                x = (mat.cols()+ xSpace)*columnCount;
//            }
//            columnCount++;
//            HighGui.moveWindow(winName,x,y);
//            i++;
//        }
//    }
    public static void show(LinkedHashMap<String, Mat> mats) {
        // 获取默认工具包
        Toolkit toolkit = Toolkit.getDefaultToolkit();
        // 获取屏幕的尺寸
        Dimension screenSize = toolkit.getScreenSize();
        // 输出屏幕宽度和高度
        int i = 0;
        int x = 0;
        int y = 0;
        int xSpacing = 10;
        int ySpacing = 40;
        for (Map.Entry<String, Mat> entry : mats.entrySet()) {
            Mat mat = entry.getValue();
            String winName = entry.getKey();
            System.out.println("winName = " + winName);
            HighGui.imshow(winName, mat);
            if (i > 0) {
                x += (mat.cols() + xSpacing);
                if (x + mat.cols() > screenSize.width) {
                    x = 0;
                    y += (mat.rows() + ySpacing);
                }
            }
            HighGui.moveWindow(winName, x, y);
            i++;
        }
    }

    /**
     * 高斯降噪
     *
     * @param mat
     */
    public static void gaussianBlur(Mat mat) {
        Imgproc.GaussianBlur(mat, mat, new Size(5, 5), 0);
    }

    /**
     * 开运算去除内部早点
     *
     * @param mat
     */
    public static void morphOpen(Mat mat) {
        Mat kernel = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(5, 5));
        Imgproc.morphologyEx(mat, mat, Imgproc.MORPH_OPEN, kernel);

    }

    public static void morphClose(Mat mat) {
        Mat kernel = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(5, 5));
        Imgproc.morphologyEx(mat, mat, Imgproc.MORPH_CLOSE, kernel);
    }

    public static void morphOpenClose(Mat mat) {
        morphOpen(mat);
        morphClose(mat);
    }

    public static Mat sketch(Mat mat) {
        Mat gray = cvtColor(mat);
        // 高斯模糊
        Mat blurredImage = new Mat();
        Imgproc.GaussianBlur(gray, blurredImage, new Size(21, 21), 0);
        // 融合原始灰度图像和模糊图像
        Mat sketchImage = new Mat();
        Core.divide(gray, blurredImage, sketchImage, 256.0);

        return sketchImage;
    }


}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-03-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
【Java版本OpenCV】无敌OpenCV越学越爽Java版代码持续更新(环境搭建|核心代码)
以上章节采免安装方式,所以安装章节可以直接跳过,节约点时间用springboot整合OpenCV(也可以用maven项目或者简单的java项目),主要是引入一个jar包和库文件,jar跨平台,库文件不跨平台,所以要区分windows和linux,至于工具idea就ok. 环境安装可以参考:springboot免安装整合Opencv兼容windows和linux
九转成圣
2024/04/10
2.2K0
【Java版本OpenCV】无敌OpenCV越学越爽Java版代码持续更新(环境搭建|核心代码)
【5】OpenCV2.4.9实现图像拼接与融合方法【SURF、SIFT、ORB、FAST、Harris角点 、stitch 】
本文出现的数据结果和码源见:https://download.csdn.net/download/sinat_39620217/18269470
汀丶人工智能
2022/12/21
3.1K0
【5】OpenCV2.4.9实现图像拼接与融合方法【SURF、SIFT、ORB、FAST、Harris角点 、stitch 】
Java使用OpenCV进行答题卡识别
https://github.com/opencv/opencv/releases
码客说
2022/09/09
3K1
Java使用OpenCV进行答题卡识别
OpenPose 基于OpenCV DNN 的手部关键点检测
原文:OpenPose 基于OpenCV DNN 的手部关键点检测 - AIUAI
AIHGF
2019/06/14
3.6K0
opencv角点检测学习总结[通俗易懂]
如果一个点在两个正交方向上都有明显的导数,则我们认为此点更倾向于是独一无二的,所以许多可跟踪的特征点都是角点。
全栈程序员站长
2022/09/27
1K0
【教程】Autojs使用OpenCV进行SIFT/BRISK等算法进行图像匹配
小锋学长生活大爆炸
2023/10/05
9550
OpenCV图像藏密--将图像隐藏到另一张图像中
密码学的应用流行多年并且技巧繁多。本文所有介绍的是图像藏密(image steganography)的隐藏技术。而密码学分为加密和解密,本文先介绍加密再介绍解密。1
程序员小涛
2020/12/03
2.3K0
OpenCV图像藏密--将图像隐藏到另一张图像中
OpenCV 估算图像的投影关系:基础矩阵和RANSAC[通俗易懂]
根据针孔摄像机模型,我们可以知道,沿着三维点X和相机中心点之间的连线,可以在图像上找到对应的点x。反过来,在三维空间中,与成像平面上的位置x对应的场景点可以位于这条线上的所有位置。这说明如果要根据图像中的一个点找到另一幅图像中对应的点,就需要在第二个成像平面上沿着这条线的投影搜索,这条线成为对极线,在这里是 l’ 。另外,所有的对极线都通过同一个点,这个点成为极点,这是图中的 e 和 e’。那么这时,出来了一个矩阵F,称为基础矩阵。
全栈程序员站长
2022/08/04
1.9K0
OpenCV 估算图像的投影关系:基础矩阵和RANSAC[通俗易懂]
计算机视觉 OpenCV Android | 基本特征检测 之 模板匹配
则运行接下来的demo代码,检测结果将如下:(截图中蓝色箭头所指的红色方框即为程序所匹配并绘制的)
凌川江雪
2019/03/04
1.3K0
计算机视觉 OpenCV Android | 基本特征检测 之 模板匹配
【走进OpenCV】重映射与仿射变换
其中的 f 就是映射方式,也就说,像素点在另一个图像中的位置是由 f 来计算的。
小白学视觉
2019/10/24
1.3K0
OpenCV图像匹配算法之sift
//utils.h #ifndef _UTILS_H #define _UTILS_H #include <opencv2/opencv.hpp> #include <opencv2/features2d/features2d.hpp> #include <opencv2/core/core.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <opencv2\nonfree\nonfree.hpp> using nam
用户7999227
2021/09/22
5510
【OpenCV入门之十五】随心所欲绘制想要形状
画圆画点都是使用circle()函数来画,点就是圆,我们平常所说的圆只不过是半径大一点而已。
小白学视觉
2019/05/30
1.9K0
Java + opencv 实现人脸识别,图片人脸识别、视频人脸识别、摄像头实时人脸识别
opencv官网下载windows安装包 https://opencv.org/releases/ 选择最新版4.1.1 下载完成后是一个opencv-4.1.1-vc14_vc15.exe,双击安装。
全栈程序员站长
2022/08/30
23K0
Java + opencv 实现人脸识别,图片人脸识别、视频人脸识别、摄像头实时人脸识别
OpenCV特征点检测——ORB特征
目录 什么是ORB 如何解决旋转不变性 如何解决对噪声敏感的问题 关于尺度不变性 关于计算速度 关于性能 Related posts 什么是ORB ORB是是ORiented Brief的简称。ORB
智能算法
2018/04/02
1.6K0
OpenCV特征点检测——ORB特征
10、图像的几何变换——平移、镜像、缩放、旋转、仿射变换 OpenCV2:图像的几何变换,平移、镜像、缩放、旋转(1)OpenCV2:图像的几何变换,平移、镜像、缩放、旋转(2)数字图像
  图像几何变换又称为图像空间变换,它将一副图像中的坐标位置映射到另一幅图像中的新坐标位置。我们学习几何变换就是确定这种空间映射关系,以及映射过程中的变化参数。图像的几何变换改变了像素的空间位置,建立一种原图像像素与变换后图像像素之间的映射关系,通过这种映射关系能够实现下面两种计算:
vv彭
2020/10/27
4.1K0
10、图像的几何变换——平移、镜像、缩放、旋转、仿射变换
    


OpenCV2:图像的几何变换,平移、镜像、缩放、旋转(1)OpenCV2:图像的几何变换,平移、镜像、缩放、旋转(2)数字图像
ubuntu16.0.4 opencv4.0.0 GPU 版本的 SURF
opencv4.0.0 自带的 samples GPU surf_keypoint_matcher.cpp
用户1148525
2019/05/27
1.4K0
opencv图像角点提取
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/179735.html原文链接:https://javaforall.cn
全栈程序员站长
2022/09/27
5760
OpenCV 直线检测
/*------------------------------------------------------------------------------------------*\ This file contains material supporting chapter 7 of the cookbook: Computer Vision Programming using the OpenCV Library. by Robert Laganiere, Packt
流川疯
2022/11/29
5380
OpenCV 直线检测
实战 | OpenCV实现多角度模板匹配(详细步骤 + 代码)
本文将介绍使用OpenCV实现多角度模板匹配的详细步骤 + 代码。(来源公众号:OpenCV与AI深度学习)
Color Space
2022/05/26
13.7K0
实战 | OpenCV实现多角度模板匹配(详细步骤 + 代码)
QT+QT creator+OpenCV图像灰度化
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/115569.html原文链接:https://javaforall.cn
全栈程序员站长
2022/07/10
5090
推荐阅读
相关推荐
【Java版本OpenCV】无敌OpenCV越学越爽Java版代码持续更新(环境搭建|核心代码)
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验