找图找色
# 找图找色
## images.requestScreenCapture([landscape])
|参数|类型|描述|
|-|-|-|
|landscape| {boolean} |布尔值, 表示将要执行的截屏是否为横屏。如果landscape为false, 则表示竖屏截图; true为横屏截图。
**向系统申请屏幕截图权限**,返回是否请求成功。
第一次使用该函数会弹出截图权限请求,建议选择“总是允许”。
这个函数只是申请截图权限,并不会真正执行截图,真正的截图函数是captureScreen()。
该函数在截图脚本中只需执行一次,而无需每次调用captureScreen()都调用一次。
如果不指定landscape值,则截图方向由当前设备屏幕方向决定,因此务必注意执行该函数时的屏幕方向。
建议在本软件界面运行该函数,在其他软件界面运行时容易出现一闪而过的黑屏现象。
示例:
```js
//请求截图
if(!requestScreenCapture()){
toast("请求截图失败");
exit();
}
//连续截图10张图片(间隔1秒)并保存到存储卡目录
for(var i = 0; i < 10; i++){
captureScreen("/sdcard/screencapture" + i + ".png");
sleep(1000);
}
```
该函数也可以作为全局函数使用。
### MIUI无法请求截图和launchApp无效说明
>d 权限管理里给一下“后台弹出界面”权限即可。
最近MIUI似乎远程推送了一个策略,突然后台弹出界面权限默认禁止了。
红米note5A高配版:
设置——应用管理——更多应用——Auto.js Pro——权限管理——后台弹出界面——开启
[红米手机请求截图权限设置教程](https://www.bilibili.com/video/av57107859/)
> 以下非官方说明

请求截图权限时,出现autojs卡死的情况,是因为不能在UI线程里直接请求。而是要创建新的线程来执行。
```js
"ui";
ui.layout(
<vertical>
<button text="第一个按钮" />
<button text="第二个按钮" />
</vertical>
);
threads.start(function () {
//在新线程执行的代码
//请求截图
if (!requestScreenCapture()) {
log("请求截图失败");
exit();
} else {
log("success");
}
});
//下面写脚本代码
```
## images.captureScreen()
**截取当前屏幕并返回一个Image对象**。
没有截图权限时执行该函数会抛出SecurityException。
该函数不会返回null,两次调用可能返回相同的Image对象。这是因为设备截图的更新需要一定的时间,短时间内(一般来说是16ms)连续调用则会返回同一张截图。
截图需要转换为Bitmap格式,从而该函数执行需要一定的时间(0~20ms)。
另外在requestScreenCapture()执行成功后需要一定时间后才有截图可用,因此如果立即调用captureScreen(),会等待一定时间后(一般为几百ms)才返回截图。
例子:
```js
//请求横屏截图
requestScreenCapture(true);
//截图
var img = captureScreen();
//获取在点(100, 100)的颜色值
var color = images.pixel(img, 100, 100);
//显示该颜色值
toast(colors.toString(color));
```
该函数也可以作为全局函数使用。
## images.captureScreen(path)
|参数|类型|描述|
|-|-|-|
| path| {string}| 截图保存路径
**截取当前屏幕并以PNG格式保存到path中**。
如果文件不存在会被创建;文件存在会被覆盖。
该函数不会返回任何值。该函数也可以作为全局函数使用。
## images.pixel(image, x, y)
|参数|类型|描述|
|-|-|-|
| image |{Image}| 图片
| x |{number} |要获取的像素的横坐标。
| y| {number}| 要获取的像素的纵坐标。
**返回图片image在点(x, y)处的像素的ARGB值**。
该值的格式为0xAARRGGBB,是一个"32位整数"(虽然JavaScript中并不区分整数类型和其他数值类型)。
坐标系以图片左上角为原点。以图片左侧边为y轴,上侧边为x轴。
```js
//花椒直播取性别节点颜色值
//此代码由飞云脚本圈原创(www.feiyunjs.com)
//请求截图权限
requestScreenCapture();
//屏幕截图
var img = captureScreen();
//取坐标点颜色值
log(images.pixel(img, 450,840))
```
## images.findColor(image, color, options)
|参数|类型|描述|
|-|-|-|
| image| {Image} |图片
|color| {number 或 string} |要寻找的颜色的RGB值。如果是一个整数,则以0xRRGGBB的形式代表RGB值(A通道会被忽略);如果是字符串,则以"#RRGGBB"代表其RGB值。
| options| {Object} |选项。在图片中寻找颜色color。找到时返回找到的点Point,找不到时返回null。选项包括:
1. region {Array} 找色区域。是一个两个或四个元素的数组。(region[0], region[1])表示找色区域的左上角;region[2]*region[3]表示找色区域的宽高。如果只有region只有两个元素,则找色区域为(region[0], region[1])到屏幕右下角。如果不指定region选项,则找色区域为整张图片。
2. threshold {number} 找色时颜色相似度的临界值,范围为0~255(越小越相似,0为颜色相等,255为任何颜色都能匹配)。默认为4。threshold和浮点数相似度(0.0~1.0)的换算为 similarity = (255 - threshold) / 255.
该函数也可以作为全局函数使用。
一个循环找色的例子如下:
```js
requestScreenCapture();
//循环找色,找到红色(#ff0000)时停止并报告坐标
while(true){
var img = captureScreen();
var point = findColor(img, "#ff0000");
if(point){
toast("找到红色,坐标为(" + point.x + ", " + point.y + ")");
}
}
```
一个区域找色的例子如下:
```js
//读取本地图片/sdcard/1.png
var img = images.read("/sdcard/1.png");
//判断图片是否加载成功
if(!img){
toast("没有该图片");
exit();
}
//在该图片中找色,指定找色区域为在位置(400, 500)的宽为300长为200的区域,指定找色临界值为4
var point = findColor(img, "#00ff00", {
region: [400, 500, 300, 200],
threshold: 4
});
if(point){
toast("找到啦:" + point);
}else{
toast("没找到");
}
```
## images.findColorInRegion(img, color, x, y[, width, height, threshold])
区域找色的简便方法。
相当于:
```js
images.findColor(img, color, {
region: [x, y, width, height],
threshold: threshold
});
```
网易公开课判断用户性别:
```js
//请求截图
if (!requestScreenCapture()) {
log("请求截图失败");
exit();
} else {
log("请求截图成功");
}
//此代码由飞云脚本圈www.feiyunjs.com原创
function APP_取性别() {
// 0,女;1,男;2,无
// 判斷是否在用戶資料頁
// waitForActivity("com.netease.vopen.timeline.ui.UserTimelineActivity"); //等待页面出现
if (id("timeline_profile_gender").exists()) {
var rect = id("timeline_profile_gender").findOne().bounds(); //寻找性别图标
var img = captureScreen();
var point = images.findColorInRegion(img, -13260321, rect.left, rect.top, rect.width(), rect.height(), 4)
if (point) {
log("找到蓝色啦:" + point); //男
return 1;
} else {
log("没找到蓝色");
point = images.findColorInRegion(img, -622207, rect.left, rect.top, rect.width(), rect.height(), 4)
if (point) {
log("找到粉色啦:" + point); //女
return 0;
} else {
log("没找到粉色");
};
};
} else {
//该用户未设置性别
};
return 2;
};
```
该函数也可以作为全局函数使用。
> (飞云)若调用此函数,打包时必须勾选图色模块,否则会报Thread[main (Spawn-2),5]: dlopen failed: library "libopencv_java3.so" not found
## images.findColorEquals(img, color[, x, y, width, height])
|参数|类型|描述|
|-|-|-|
| img |{Image} |图片
| color| {number 或 string} |要寻找的颜色
| x| {number} |找色区域的左上角横坐标
| y| {number}| 找色区域的左上角纵坐标
| width| {number} |找色区域的宽度
| height |{number} |找色区域的高度
返回 {Point}
在图片img指定区域中找到颜色和color完全相等的某个点,并返回该点的左边;如果没有找到,则返回null。
找色区域通过x, y, width, height指定,如果不指定找色区域,则在整张图片中寻找。
该函数也可以作为全局函数使用。
示例: (通过找QQ红点的颜色来判断是否有未读消息)
```js
requestScreenCapture();
launchApp("QQ");
sleep(1200);
var p = findColorEquals(captureScreen(), "#f64d30");
if(p){
toast("有未读消息");
}else{
toast("没有未读消息");
}
```
## images.findMultiColors(img, firstColor, colors[, options])
|参数|类型|描述|
|-|-|-|
| img |{Image}| 要找色的图片
| firstColor |{number 或 string} |第一个点的颜色
| colors| {Array} |表示剩下的点相对于第一个点的位置和颜色的数组,数组的每个元素为[x, y, color]
|options| {Object} |选项,包括:
|参数|类型|描述|
|-|-|-|
|region |{Array} |找色区域。是一个两个或四个元素的数组。(region[0], region[1])表示找色区域的左上角;region[2]*region[3]表示找色区域的宽高。如果只有region只有两个元素,则找色区域为(region[0], region[1])到屏幕右下角。如果不指定region选项,则找色区域为整张图片。
|threshold |{number}| 找色时颜色相似度的临界值,范围为0~255(越小越相似,0为颜色相等,255为任何颜色都能匹配)。默认为4。threshold和浮点数相似度(0.0~1.0)的换算为 similarity = (255 - threshold) / 255.
**多点找色**。类似于按键精灵的多点找色,其过程如下:
在图片img中找到颜色firstColor的位置(x0, y0)
对于数组colors的每个元素[x, y, color],检查图片img在位置(x + x0, y + y0)上的像素是否是颜色color,是的话返回(x0, y0),否则继续寻找firstColor的位置,重新执行第1步
整张图片都找不到时返回null
例如,对于代码images.findMultiColors(img, "#123456", [[10, 20, "#ffffff"], [30, 40, "#000000"]]),假设图片在(100, 200)的位置的颜色为#123456, 这时如果(110, 220)的位置的颜色为#fffff且(130, 240)的位置的颜色为#000000,则函数返回点(100, 200)。
如果要指定找色区域,则在options中指定,例如:
```js
var p = images.findMultiColors(img, "#123456", [[10, 20, "#ffffff"], [30, 40, "#000000"]], {
region: [0, 960, 1080, 960]
});
```
## images.detectsColor(image, color, x, y[, threshold = 16, algorithm = "diff"])
|参数|类型|描述|
|-|-|-|
| image |{Image}| 图片
| color| {number 或 string} |要检测的颜色
| x| {number} |要检测的位置横坐标
| y| {number} |要检测的位置纵坐标
| threshold |{number} |颜色相似度临界值,默认为16。取值范围为0~255。
| algorithm| {string} |颜色匹配算法,包括:
1. "equal": 相等匹配,只有与给定颜色color完全相等时才匹配。
2. "diff": 差值匹配。与给定颜色的R、G、B差的绝对值之和小于threshold时匹配。
3. "rgb": rgb欧拉距离相似度。与给定颜色color的rgb欧拉距离小于等于threshold时匹配。
4. "rgb+": 加权rgb欧拉距离匹配(LAB Delta E)。
5. "hs": hs欧拉距离匹配。hs为HSV空间的色调值。
返回图片image在位置(x, y)处是否匹配到颜色color。
用于检测图片中某个位置是否是特定颜色。
>s 一个判断微博客户端的某个微博是否被点赞过的例子:
```js
requestScreenCapture();
//找到点赞控件
var like = id("ly_feed_like_icon").findOne();
//获取该控件中点坐标
var x = like.bounds().centerX();
var y = like.bounds().centerY();
//截图
var img = captureScreen();
//判断在该坐标的颜色是否为橙红色
if(images.detectsColor(img, "#fed9a8", x, y)){
//是的话则已经是点赞过的了,不做任何动作
}else{
//否则点击点赞按钮
like.click();
}
```
## images.findImage(img, template[, options])
- img {Image} 大图片
- template {Image} 小图片(模板)
- options {Object} 找图选项
找图。在大图片img中查找小图片template的位置(模块匹配),找到时返回位置坐标(Point),找不到时返回null。
选项包括:
1. threshold {number} 图片相似度。取值范围为0~1的浮点数。默认值为0.9。
2. region {Array} 找图区域。参见findColor函数关于region的说明。
3. level {number} 一般而言不必修改此参数。不加此参数时该参数会根据图片大小自动调整。找图算法是采用图像金字塔进行的, level参数表示金字塔的层次, level越大可能带来越高的找图效率,但也可能造成找图失败(图片因过度缩小而无法分辨)或返回错误位置。因此,除非您清楚该参数的意义并需要进行性能调优,否则不需要用到该参数。
该函数也可以作为全局函数使用。
一个最简单的找图例子如下:
```js
var img = images.read("/sdcard/大图.png");
var templ = images.read("/sdcard/小图.png");
var p = findImage(img, templ);
if(p){
toast("找到啦:" + p);
}else{
toast("没找到");
}
```
稍微复杂点的区域找图例子如下:
```javascript
auto();
requestScreenCapture();
var wx = images.read("/sdcard/微信图标.png");
//返回桌面
home();
//截图并找图
var p = findImage(captureScreen(), wx, {
region: [0, 50],
threshold: 0.8
});
if(p){
toast("在桌面找到了微信图标啦: " + p);
}else{
toast("在桌面没有找到微信图标");
}
```
## images.findImageInRegion(img, template, x, y[, width, height, threshold])
区域找图的简便方法。相当于:
```javascript
images.findImage(img, template, {
region: [x, y, width, height],
threshold: threshold
})
```
该函数也可以作为全局函数使用。
## images.matchTemplate(img, template, options)
[v4.1.0新增]
- img {Image} 大图片
- template {Image} 小图片(模板)
- options {Object} 找图选项:
1. threshold {number} 图片相似度。取值范围为0~1的浮点数。默认值为0.9。
2. region {Array} 找图区域。参见findColor函数关于region的说明。
3. max {number} 找图结果最大数量,默认为5
4. level {number} 一般而言不必修改此参数。不加此参数时该参数会根据图片大小自动调整。找图算法是采用图像金字塔进行的, level参数表示金字塔的层次, level越大可能带来越高的找图效率,但也可能造成找图失败(图片因过度缩小而无法分辨)或返回错误位置。因此,除非您清楚该参数的意义并需要进行性能调优,否则不需要用到该参数。
返回 {MatchingResult}
在大图片中搜索小图片,并返回搜索结果MatchingResult。该函数可以用于找图时找出多个位置,可以通过max参数控制最大的结果数量。也可以对匹配结果进行排序、求最值等操作。
在大图中寻找小图,找到就点击小图的中心点
```javascript
// Design By feiYun
var templ = images.read('image/aweme/label_免运费.png');
if (templ) {
let img = captureScreen();
var res = images.matchTemplate(img, templ, {
region: region,
threshold: threshold,
max: 1,
});
let points;
res.matches.forEach(match => {
points = match.point;
// log("point = " + match.point + ", similarity = " + match.similarity);
});
// 回收图片
img.recycle();
templ.recycle();
if (points) {
let x = parseInt(points.x);
let y = parseInt(points.y);
let width = templ.getWidth();
let height = templ.getHeight();
// log(x,y)
click(x + parseInt(width / 2), y + parseInt(height / 2)); // 点击小图片中心点
} else {
// toastLog("没找到");
}
} else {
// 小图片不存在
toastLog("小图片不存在");
}
```
## images.findCircles(gray, options)
- gray {Image} 灰度图片
- options {Object} 选项包括:
1. region {Array} 找圆区域。是一个两个或四个元素的数组。(region[0], region[1])表示找圆区域的左上角;region[2]*region[3]表示找圆区域的宽高。如果只有region只有两个元素,则找圆区域为(region[0], region[1])到图片右下角。如果不指定region选项,则找圆区域为整张图片。
2. dp {number} dp是累加面与原始图像相比的分辨率的反比参数,dp=2时累计面分辨率是元素图像的一半,宽高都缩减为原来的一半,dp=1时,两者相同。默认为1。
3. minDst {number} minDist定义了两个圆心之间的最小距离。默认为图片高度的八分之一。
4. param1 {number} param1是Canny边缘检测的高阈值,低阈值被自动置为高阈值的一半。默认为100,范围为0-255。
5. param2 {number} param2是累加平面对是否是圆的判定阈值,默认为100。
6. minRadius {number} 定义了检测到的圆的半径的最小值,默认为0。
7. maxRadius {number} 定义了检测到的圆的半径的最大值,0为不限制最大值,默认为0。
- return {Array}
在图片中寻找圆(做霍夫圆变换)。
找到时返回找到的所有圆{x,y,radius}的数组,找不到时返回null。
```javascript
// 请求截图
requestScreenCapture();
// 截图
let img = captureScreen();
// 灰度化图片
let gray = images.grayscale(img);
// 找圆
let arr = findCircles(gray, {
dp: 1,
minDst: 80,
param1: 100,
param2: 100,
minRadius: 50,
maxRadius: 80,
});
// 回收图片
gray.recycle();
```
## MatchingResult
[v4.1.0新增]
## matches
- {Array} 匹配结果的数组。
数组的元素是一个Match对象:
1. point {Point} 匹配位置
2. similarity {number} 相似度
例如:
```js
var result = images.matchTemplate(img, template, {
max: 100
});
result.matches.forEach(match => {
log("point = " + match.point + ", similarity = " + match.similarity);
});
```
## points
{Array} 匹配位置的数组。
## first()
返回 {Match}
第一个匹配结果。如果没有任何匹配,则返回null。
## last()
返回 {Match}
最后一个匹配结果。如果没有任何匹配,则返回null。
## leftmost()
返回 {Match}
位于大图片最左边的匹配结果。如果没有任何匹配,则返回null。
## topmost()
返回 {Match}
位于大图片最上边的匹配结果。如果没有任何匹配,则返回null。
## rightmost()
返回 {Match}
位于大图片最右边的匹配结果。如果没有任何匹配,则返回null。
## bottommost()
返回 {Match}
位于大图片最下边的匹配结果。如果没有任何匹配,则返回null。
## best()
返回 {Match}
相似度最高的匹配结果。如果没有任何匹配,则返回null。
## worst()
返回 {Match}
相似度最低的匹配结果。如果没有任何匹配,则返回null。
## sortBy(cmp)
- cmp {Function}|{string} 比较函数,或者是一个字符串表示排序方向。例如"left"表示将匹配结果按匹配位置从左往右排序、"top"表示将匹配结果按匹配位置从上往下排序,"left-top"表示将匹配结果按匹配位置从左往右、从上往下排序。方向包括left(左), top (上), right (右), bottom(下)。
{MatchingResult}
对匹配结果进行排序,并返回排序后的结果。
```
var result = images.matchTemplate(img, template, {
max: 100
});
log(result.sortBy("top-right"));
```
## Image
表示一张图片,可以是截图的图片,或者本地读取的图片,或者从网络获取的图片。
## Image.getWidth()
返回以像素为单位图片宽度。
## Image.getHeight()
返回以像素为单位的图片高度。
## Image.saveTo(path)
- path {string} 路径
把图片保存到路径path。(如果文件存在则覆盖)
## Image.pixel(x, y)
- x {number} 横坐标
- y {number} 纵坐标
返回图片image在点(x, y)处的像素的ARGB值。
该值的格式为0xAARRGGBB,是一个"32位整数"(虽然JavaScript中并不区分整数类型和其他数值类型)。
坐标系以图片左上角为原点。以图片左侧边为y轴,上侧边为x轴。
## Point
findColor, findImage返回的对象。表示一个点(坐标)。
## Point.x
横坐标。
## Point.y
纵坐标。