当前位置: 首页 > news >正文

C#_查找图片(按键精灵找图)

一、class

    internal class Picture{/// <summary>/// 查找图片,不能镂空/// </summary>/// <param name="subPic"></param>/// <param name="searchRect">如果为empty,则默认查找整个图像</param>/// <param name="matchRate">图片匹配度,默认90%</param>/// <param name="errorRange">容错,单个色值范围内视为正确0~255</param>/// <param name="isFindAll">是否查找所有相似的图片</param>/// <returns>返回查找到的图片的中心点坐标</returns>public List<System.Drawing.Point> FindPicture(string subPic, System.Drawing.Rectangle searchRect, double matchRate = 0.9, byte errorRange = 0, bool isFindAll = false){List<System.Drawing.Point> ListPoint = new List<System.Drawing.Point>();var subBitmap = new Bitmap(subPic);//创建Bitmap位图类(尺寸与分辨率相同)            Bitmap parBitmap = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);//从一个继承自Image类的对象中创建Graphics对象            Graphics g = Graphics.FromImage(parBitmap);//截取屏幕并复制到(g)myimage里            g.CopyFromScreen(new Point(0, 0), new Point(0, 0), new Size(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height));//保存截图//parBitmap.Save(System.Environment.CurrentDirectory + @"\temp\test.bmp");int subWidth = subBitmap.Width;int subHeight = subBitmap.Height;int parWidth = parBitmap.Width;int parHeight = parBitmap.Height;if (searchRect.IsEmpty){searchRect = new System.Drawing.Rectangle(0, 0, parBitmap.Width, parBitmap.Height);}var searchLeftTop = searchRect.Location;var searchSize = searchRect.Size;System.Drawing.Color startPixelColor = subBitmap.GetPixel(0, 0);var subData = subBitmap.LockBits(new System.Drawing.Rectangle(0, 0, subBitmap.Width, subBitmap.Height), ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);var parData = parBitmap.LockBits(new System.Drawing.Rectangle(0, 0, parBitmap.Width, parBitmap.Height), ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);var byteArrarySub = new byte[subData.Stride * subData.Height];var byteArraryPar = new byte[parData.Stride * parData.Height];Marshal.Copy(subData.Scan0, byteArrarySub, 0, subData.Stride * subData.Height);Marshal.Copy(parData.Scan0, byteArraryPar, 0, parData.Stride * parData.Height);var iMax = searchLeftTop.Y + searchSize.Height - subData.Height;//行var jMax = searchLeftTop.X + searchSize.Width - subData.Width;//列int smallOffsetX = 0, smallOffsetY = 0;int smallStartX = 0, smallStartY = 0;int pointX = -1; int pointY = -1;for (int i = searchLeftTop.Y; i < iMax; i++){for (int j = searchLeftTop.X; j < jMax; j++){//大图x,y坐标处的颜色值int x = j, y = i;int parIndex = i * parWidth * 4 + j * 4;var colorBig = System.Drawing.Color.FromArgb(byteArraryPar[parIndex + 3], byteArraryPar[parIndex + 2], byteArraryPar[parIndex + 1], byteArraryPar[parIndex]);;if (ColorAEqualColorB(colorBig, startPixelColor, errorRange)){smallStartX = x - smallOffsetX;//待找的图X坐标smallStartY = y - smallOffsetY;//待找的图Y坐标int sum = 0;//所有需要比对的有效点int matchNum = 0;//成功匹配的点for (int m = 0; m < subHeight; m++){for (int n = 0; n < subWidth; n++){int x1 = n, y1 = m;int subIndex = m * subWidth * 4 + n * 4;var color = System.Drawing.Color.FromArgb(byteArrarySub[subIndex + 3], byteArrarySub[subIndex + 2], byteArrarySub[subIndex + 1], byteArrarySub[subIndex]);sum++;int x2 = smallStartX + x1, y2 = smallStartY + y1;int parReleativeIndex = y2 * parWidth * 4 + x2 * 4;//比对大图对应的像素点的颜色var colorPixel = System.Drawing.Color.FromArgb(byteArraryPar[parReleativeIndex + 3], byteArraryPar[parReleativeIndex + 2], byteArraryPar[parReleativeIndex + 1], byteArraryPar[parReleativeIndex]);if (ColorAEqualColorB(colorPixel, color, errorRange)){matchNum++;}}}if ((double)matchNum / sum >= matchRate){Console.WriteLine((double)matchNum / sum);pointX = smallStartX + (int)(subWidth / 2.0);pointY = smallStartY + (int)(subHeight / 2.0);var point = new System.Drawing.Point(pointX, pointY);if (!ListContainsPoint(ListPoint, point, 10)){ListPoint.Add(point);}if (!isFindAll){goto FIND_END;}}}//小图x1,y1坐标处的颜色值}}FIND_END:subBitmap.UnlockBits(subData);parBitmap.UnlockBits(parData);subBitmap.Dispose();parBitmap.Dispose();GC.Collect();return ListPoint;}bool ColorAEqualColorB(System.Drawing.Color colorA, System.Drawing.Color colorB, byte errorRange = 10){return colorA.A <= colorB.A + errorRange && colorA.A >= colorB.A - errorRange &&colorA.R <= colorB.R + errorRange && colorA.R >= colorB.R - errorRange &&colorA.G <= colorB.G + errorRange && colorA.G >= colorB.G - errorRange &&colorA.B <= colorB.B + errorRange && colorA.B >= colorB.B - errorRange;}bool ListContainsPoint(List<System.Drawing.Point> listPoint, System.Drawing.Point point, double errorRange = 10){bool isExist = false;foreach (var item in listPoint){if (item.X <= point.X + errorRange && item.X >= point.X - errorRange && item.Y <= point.Y + errorRange && item.Y >= point.Y - errorRange){isExist = true;}}return isExist;}}
}

二、代码

  前台操作,自行加延迟或锁定键盘鼠标。

1、全屏找图

            Picture picture = new Picture();List<System.Drawing.Point> points = new List<System.Drawing.Point>();points = picture.FindPicture(System.Environment.CurrentDirectory + @"\temp\test.bmp", Rectangle.Empty);

2、区域找图

            Picture picture = new Picture();List<System.Drawing.Point> points = new List<System.Drawing.Point>();Rectangle rectangle = new Rectangle(50, 50, 300, 300);points = picture.FindPicture(System.Environment.CurrentDirectory + @"\temp\test.bmp", rectangle);

3、循环找图

            do{points = picture.FindPicture(System.Environment.CurrentDirectory + @"\temp\test.bmp", rectangle);Thread.Sleep(1000);} while (points.Count == 0);

4、循环找图,避免死循环

            //查找10次,找不到跳出循环int i = 0;do{points = picture.FindPicture(System.Environment.CurrentDirectory + @"\temp\test.bmp", rectangle);i++;Thread.Sleep(1000);} while (points.Count == 0 && i < 10);

5、找图后鼠标点击

  鼠标点击相关代码见此处。

            if (points.Count > 0){//移动鼠标到坐标点MouseHelper.SetCursorPos(points[0].X, points[0].Y);//鼠标左键单击MouseHelper.mouse_event(MouseHelper.MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);MouseHelper.mouse_event(MouseHelper.MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);}

相关文章:

C#_查找图片(按键精灵找图)

一、class internal class Picture{/// <summary>/// 查找图片&#xff0c;不能镂空/// </summary>/// <param name"subPic"></param>/// <param name"searchRect">如果为empty&#xff0c;则默认查找整个图像</param>…...

C#中.NET Framework4.8 控制台应用通过EF访问新建数据库

目录 一、 操作步骤 二、编写EF模型和数据库上下文 三、 移植&#xff08;Migrations&#xff09;数据库 四、编写应用程序并运行 前文已经说过.NET Framework4.8 控制台应用通过EF访问已经建立的数据库&#xff0c;这里说的已经建立的数据库指的是已经建立的SQLServer那样…...

无防御香港服务器如何防CC

虽然相对于DDos攻击&#xff0c;CC攻击的防护危害性相对没有那么大&#xff0c;但是像香港地区普遍对内地的网络比较小的话&#xff0c;CC攻击还是 蛮让人头痛的&#xff0c;实际上对CC的防护尤其是一些小体量的网站&#xff0c;租用高防服务器是划不来的&#xff0c;如果服务器…...

MyBatis的插件能在哪些地方进行拦截?

程序员的公众号&#xff1a;源1024&#xff0c;获取更多资料&#xff0c;无加密无套路&#xff01; 最近整理了一波电子书籍资料&#xff0c;包含《Effective Java中文版 第2版》《深入JAVA虚拟机》&#xff0c;《重构改善既有代码设计》&#xff0c;《MySQL高性能-第3版》&…...

【BUG库】 记录自己学习工作中遇到的程序BUG

BUG库 CGoalgorithm环境相关vscode -- 保存 在这篇博客中 我会记录自己在学习和工作中遇到的一系列bug C Go algorithm 环境相关 vscode – 保存 使用vscode时未保存代码就使用终端运行 vscode和终端并不是实时同步的 需要我们自己手动使用ctrl s同步 解决方法 自己手动…...

卡尔曼家族从零解剖-(07) 高斯分布积分为1,高斯分布线性变换依旧为高斯分布,两高斯函数乘积仍为高斯。

讲解关于slam一系列文章汇总链接:史上最全slam从零开始&#xff0c;针对于本栏目讲解的 卡尔曼家族从零解剖 链接 :卡尔曼家族从零解剖-(00)目录最新无死角讲解&#xff1a;https://blog.csdn.net/weixin_43013761/article/details/133846882 文末正下方中心提供了本人 联系…...

设计模式-访问者模式(Visitor)

设计模式-访问者模式&#xff08;Visitor&#xff09; 一、访问者模式概述1.1 什么是访问者模式1.2 简单实现访问者模式1.3 使用访问者模式的注意事项 二、访问者模式的用途三、访问者模式实现方式3.1 递归遍历实现访问者模式3.2 迭代遍历实现访问者模式3.3 Java8 Stream API 实…...

C++二分查找算法:132 模式解法二枚举2

题目及解法一&#xff1a; https://blog.csdn.net/he_zhidan/article/details/134362273 分析 第一步&#xff0c;选择各3对应的1&#xff0c;如果有多个符合对应最小的1&#xff0c;记录num[0,j)中的最小值iMin&#xff0c;如果nums[j]大于iMin&#xff0c;则m3To1 [nums[j…...

JavaWeb-HTML

​ 一、什么是HTML HTML是hypertext markup language&#xff08;超文本标记语言&#xff09;的缩写。HTML文件本质上是文本文件&#xff0c;普通的文本文件只能显示字符&#xff0c;而HTML文件可以在浏览器上显示更丰富的信息&#xff08;如图片等&#xff09;。 超文本&am…...

新外卖霸王餐小程序、H5、微信公众号版外卖系统源码

最新外卖霸王餐小程序、H5、微信公众号版外卖系统源码、霸王餐美团、饿了么系统&#xff0c;粉丝裂变玩源码下载&#xff0c;外卖cps小程序项目&#xff0c;外卖红包cps带好友返利佣金分销系统程序、饿了么美团联盟源码&#xff0c;外卖cps带分销返利后端源码&#xff0c;基于L…...

LeetCode - #89 格雷编码

文章目录 前言1. 描述2. 示例3. 答案关于我们 前言 我们社区陆续会将顾毅&#xff08;Netflix 增长黑客&#xff0c;《iOS 面试之道》作者&#xff0c;ACE 职业健身教练。&#xff09;的 Swift 算法题题解整理为文字版以方便大家学习与阅读。 LeetCode 算法到目前我们已经更新…...

11.3SpringMVC

一.概念 1.SpringMvc: a.构建在Servlet(api)基础上. b.是一个Web框架(HTTP). c.来自于Spring webMVC模块. 2.MVC 二.注册路由的注解 1.RequestMapping("/test") // 路由注册 注意: 这个注解在类和方法上都要使用,代表不同等级的路由. 2.RestController a)R…...

c语言从入门到实战——数组指针与函数指针

数组指针与函数指针 前言1. 字符指针变量2. 数组指针变量2.1 数组指针变量是什么&#xff1f;2.2 数组指针变量怎么初始化? 3. 二维数组传参的本质4. 函数指针变量4.1 函数指针变量的创建4.2 函数指针变量的使用4.3 两段有趣的代码4.3.1 typedef关键字 5. 函数指针数组6. 转移…...

Rust图形界面编程:egui平直布局

文章目录 平直布局with_layout 平直布局 在前面的示例中&#xff0c;已经用到了ui.horizontal用来布局&#xff0c;其特点是水平摆放控件。相应地&#xff0c;ui.vertical则是垂直摆放控件。根据控件的摆放顺序不同&#xff0c;这两个布局组件衍生出一系列布局函数 horizonta…...

Android13 wifi adb 串口开启

Android13 wifi adb 串口开启 文章目录 Android13 wifi adb 串口开启一、前言二、开启wifi adb1、开启wifi adb 命令&#xff1a;2、查看和设置 adb默认值3、adb 开启属性prop和settings属性的关系 三、总结1、Android13 开启adb 串口命令2、Android 13 wifi adb设置固定端口解…...

关于一个屏幕取词程序,AI给的创建思路及指导

我&#xff1a;我在windows上&#xff0c;经常碰到各种软件当中有自己不认识的英文&#xff0c;请问如果要用python开发一个随时添加屏幕上任意英文单词到生词词典中的软件&#xff0c;该怎么进行&#xff1f; AI&#xff1a;开发一个能够从屏幕上捕获英文单词并将其添加到生词…...

MySql跨库跨表触发器

一、跨库触发器的概念 跨库触发器是指能在一个数据库中创建的触发器&#xff0c;但触发器的操作涉及到其他数据库中的表。这种触发器的存在可以帮助我们实现一些复杂的业务逻辑&#xff0c;比如在一个数据库中的表更新时&#xff0c;自动更新另一个数据库中的相关表。 二、创建…...

NextJS开发:shadcn/ui中Button组件扩展增加图标

shadcn/ui组件比较灵活&#xff0c;但是功能相比ant之类组件还是缺少太多功能&#xff0c;本文为shadcn/ui为button组件增加图标&#xff0c;加载中动画等效果。 安装Lucide npm install lucideLucide组件 import { cn } from /lib/utils; import { icons } from lucide-rea…...

Go 语言

1. 请简要介绍一下 Go 语言的特点。 Go 语言是一种高性能、并发支持强大且易于学习的编程语言。以下是 Go 语言的一些主要特点&#xff1a; 高性能&#xff1a;Go 语言的运行速度接近 C 和 Java&#xff0c;某些场景下甚至更快&#xff0c;这使得它非常适合用于高性能计算和网…...

【计算机网络笔记】DHCP协议

系列文章目录 什么是计算机网络&#xff1f; 什么是网络协议&#xff1f; 计算机网络的结构 数据交换之电路交换 数据交换之报文交换和分组交换 分组交换 vs 电路交换 计算机网络性能&#xff08;1&#xff09;——速率、带宽、延迟 计算机网络性能&#xff08;2&#xff09;…...

Wan2.2-I2V-A14B企业级部署案例:单卡24GB显存实现高并发视频API服务

Wan2.2-I2V-A14B企业级部署案例&#xff1a;单卡24GB显存实现高并发视频API服务 1. 企业级视频生成解决方案概述 在数字内容创作领域&#xff0c;视频生成技术正经历革命性变革。Wan2.2-I2V-A14B作为新一代文生视频模型&#xff0c;通过私有化部署方案&#xff0c;为企业提供…...

Linux七大常见误解与真相解析

1. Linux 神话的起源与现状Linux 作为开源操作系统的代表&#xff0c;自1991年诞生以来就伴随着各种误解和神话。这些误解往往源于早期Linux的使用门槛较高、图形界面不够完善等历史原因。但经过30多年的发展&#xff0c;现代Linux发行版已经发生了翻天覆地的变化。在技术社区中…...

Vision Transformer在timm中的实现与优化

Vision Transformer在timm中的实现与优化 【免费下载链接】pytorch-image-models The largest collection of PyTorch image encoders / backbones. Including train, eval, inference, export scripts, and pretrained weights -- ResNet, ResNeXT, EfficientNet, NFNet, Visi…...

万象视界灵坛惊艳效果展示:同一张宠物图在‘金毛犬’‘幼犬’‘户外玩耍’‘毛发蓬松’多维排序

万象视界灵坛惊艳效果展示&#xff1a;同一张宠物图在"金毛犬""幼犬""户外玩耍""毛发蓬松"多维排序 1. 效果展示开场 今天我要向大家展示万象视界灵坛这个神奇工具的实际效果。它就像一个视觉魔法师&#xff0c;能够深入理解图片中的…...

python异常模拟工具类(异常生成工具类)

文章目录创建代码类使用主要是做测试的时候方便&#xff0c;创建代码类 1、新建python文件exception_mock_utils.py&#xff0c;代码为&#xff1a; import random import time from typing import Any, Optionalclass ExceptionMockUtils:"""异常模拟工具类用…...

VideoSrt:零基础视频字幕自动化解决方案

VideoSrt&#xff1a;零基础视频字幕自动化解决方案 【免费下载链接】video-srt-windows 这是一个可以识别视频语音自动生成字幕SRT文件的开源 Windows-GUI 软件工具。 项目地址: https://gitcode.com/gh_mirrors/vi/video-srt-windows 视频创作者的效率痛点&#xff1a…...

【中文文献管理效率提升90%】茉莉花插件:科研工作者的智能文献处理解决方案

【中文文献管理效率提升90%】茉莉花插件&#xff1a;科研工作者的智能文献处理解决方案 【免费下载链接】jasminum A Zotero add-on to retrive CNKI meta data. 一个简单的Zotero 插件&#xff0c;用于识别中文元数据 项目地址: https://gitcode.com/gh_mirrors/ja/jasminum…...

LangChain 与 LangGraph 介绍

一&#xff64;AI 时代下的编程范式 1. Vibe Coding 氛围编程 1.1 Vibe Coding 的起源 在过去十年间&#xff0c;低代码 / 无代码平台和 AI 代码助手持续冲击着软件开发行业。如今&#xff0c;一种被称为 Vibe Coding 的新兴实践突然走红&#xff0c;甚至颠覆了人们对 "…...

AI大模型产品经理零基础到进阶学习路线图,非常详细收藏我这一篇就够了

AI产品经理区别于普通产品经理的地方&#xff0c;不止在懂得AI算法&#xff0c;更重要的是具有AI思维。 人工智能产品设计要以操作极度简单为标准&#xff0c;但是前端的简单代表后端的复杂&#xff0c;系统越复杂&#xff0c;才能越智能。 同样&#xff0c;人工智能的发展依…...

4步解决RetroArch缩略图显示异常,恢复游戏库视觉体验

4步解决RetroArch缩略图显示异常&#xff0c;恢复游戏库视觉体验 【免费下载链接】RetroArch Cross-platform, sophisticated frontend for the libretro API. Licensed GPLv3. 项目地址: https://gitcode.com/GitHub_Trending/re/RetroArch 在RetroArch的使用过程中&am…...