From f83b2fb9230dfebc9446af07aeee5ec9ea68366c Mon Sep 17 00:00:00 2001 From: hyb1996 <946994919@qq.com> Date: Thu, 1 Feb 2018 20:36:44 +0800 Subject: [PATCH] feat: findMultiColors --- autojs/src/main/assets/modules/__images__.js | 31 ++++++-- .../autojs/core/image/ColorFinder.java | 76 +++++++++++++------ 2 files changed, 77 insertions(+), 30 deletions(-) diff --git a/autojs/src/main/assets/modules/__images__.js b/autojs/src/main/assets/modules/__images__.js index 0ab9e799..e83e1256 100644 --- a/autojs/src/main/assets/modules/__images__.js +++ b/autojs/src/main/assets/modules/__images__.js @@ -1,5 +1,7 @@ module.exports = function(__runtime__, scope){ + const defaultColorThreshold = 4; + var images = {}; var colors = Object.create(__runtime__.colors); colors.alpha = function(color){ @@ -41,7 +43,7 @@ module.exports = function(__runtime__, scope){ images.detectsColor = function(img, color, x, y, threshold, algorithm){ color = parseColor(color); algorithm = algorithm || "diff"; - threshold = threshold || 16; + threshold = threshold || defaultColorThreshold; var colorDetector = getColorDetector(color, algorithm, threshold); var pixel = images.pixel(img, x, y); return colorDetector.detectsColor(colors.red(pixel), colors.green(pixel), colors.blue(pixel)); @@ -54,7 +56,7 @@ module.exports = function(__runtime__, scope){ if(options.similarity){ var threshold = parseInt(255 * (1 - options.similarity)); }else{ - var threshold = options.threshold || 16; + var threshold = options.threshold || defaultColorThreshold; } if(options.region){ return colorFinder.findColor(img, color, threshold, buildRegion(options.region, img)); @@ -77,21 +79,36 @@ module.exports = function(__runtime__, scope){ }); } - images.findColors = function(img, color, options){ + images.findAllPointsForColor = function(img, color, options){ color = parseColor(color); options = options || {}; if(options.similarity){ var threshold = parseInt(255 * (1 - options.similarity)); }else{ - var threshold = options.threshold || 16; + var threshold = options.threshold || defaultColorThreshold; } if(options.region){ - return toPointArray(colorFinder.findAllColors(img, color, threshold, buildRegion(options.region, img))); + return toPointArray(colorFinder.findAllPointsForColor(img, color, threshold, buildRegion(options.region, img))); }else{ - return toPointArray(colorFinder.findAllColors(img, color, threshold, null)); + return toPointArray(colorFinder.findAllPointsForColor(img, color, threshold, null)); } } + images.findMultiColors = function(img, firstColor, paths, options){ + options = options || {}; + firstColor = parseColor(firstColor); + var list = java.lang.reflect.Array.newInstance(java.lang.Integer.TYPE, paths.length * 3); + for(var i = 0; i < paths.length; i++){ + var p = paths[i]; + list[i * 3] = p[0]; + list[i * 3 + 1] = p[1]; + list[i * 3 + 2] = parseColor(p[2]); + } + var region = options.region ? buildRegion(options.region, img) : null; + var threshold = options.threshold === undefined ? defaultColorThreshold : options.threshold; + return colorFinder.findMultiColors(img, firstColor, threshold, region, list); + } + images.findImage = function(img, template, options){ options = options || {}; var threshold = options.threshold || 0.9; @@ -159,7 +176,7 @@ module.exports = function(__runtime__, scope){ return color; } - scope.__asGlobal__(images, ['requestScreenCapture', 'captureScreen', 'findImage', 'findImageInRegion', 'findColor', 'findColorInRegion', 'findColorEquals']); + scope.__asGlobal__(images, ['requestScreenCapture', 'captureScreen', 'findImage', 'findImageInRegion', 'findColor', 'findColorInRegion', 'findColorEquals', 'findMultiColors']); scope.colors = colors; diff --git a/autojs/src/main/java/com/stardust/autojs/core/image/ColorFinder.java b/autojs/src/main/java/com/stardust/autojs/core/image/ColorFinder.java index ce0252ce..054d0785 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/image/ColorFinder.java +++ b/autojs/src/main/java/com/stardust/autojs/core/image/ColorFinder.java @@ -4,11 +4,8 @@ import android.graphics.Color; import android.os.Build; import android.support.annotation.RequiresApi; -import com.stardust.autojs.runtime.exception.ScriptInterruptedException; -import com.stardust.concurrent.VolatileBox; import com.stardust.util.ScreenMetrics; -import org.opencv.android.Utils; import org.opencv.core.Core; import org.opencv.core.Mat; import org.opencv.core.MatOfPoint; @@ -16,12 +13,6 @@ import org.opencv.core.Point; import org.opencv.core.Rect; import org.opencv.core.Scalar; -import java.util.List; -import java.util.Vector; -import java.util.concurrent.SynchronousQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - /** * Created by Stardust on 2017/5/18. */ @@ -47,15 +38,35 @@ public class ColorFinder { return findColor(imageWrapper, color, threshold, null); } - public Point findColor(ImageWrapper imageWrapper, int color, int threshold, Rect region) { - Point[] points = findAllColors(imageWrapper, color, threshold, region); - if (points.length == 0) { + public Point findColor(ImageWrapper image, int color, int threshold, Rect rect) { + MatOfPoint matOfPoint = findColorInner(image, color, threshold, rect); + if (matOfPoint == null) { return null; } - return points[0]; + Point point = matOfPoint.toArray()[0]; + if (rect != null) { + point.x = mScreenMetrics.scaleX((int) (point.x + rect.x)); + point.y = mScreenMetrics.scaleX((int) (point.y + rect.y)); + } + return point; } - public Point[] findAllColors(ImageWrapper image, int color, int threshold, Rect rect) { + public Point[] findAllPointsForColor(ImageWrapper image, int color, int threshold, Rect rect) { + MatOfPoint matOfPoint = findColorInner(image, color, threshold, rect); + if (matOfPoint == null) { + return new Point[0]; + } + Point[] points = matOfPoint.toArray(); + if (rect != null) { + for (int i = 0; i < points.length; i++) { + points[i].x = mScreenMetrics.scaleX((int) (points[i].x + rect.x)); + points[i].y = mScreenMetrics.scaleX((int) (points[i].y + rect.y)); + } + } + return points; + } + + private MatOfPoint findColorInner(ImageWrapper image, int color, int threshold, Rect rect) { Mat bi = new Mat(); Scalar lowerBound = new Scalar(Color.red(color) - threshold, Color.green(color) - threshold, Color.blue(color) - threshold, 255); @@ -69,16 +80,35 @@ public class ColorFinder { Mat nonZeroPos = new Mat(); Core.findNonZero(bi, nonZeroPos); if (nonZeroPos.rows() == 0 || nonZeroPos.cols() == 0) { - return new Point[0]; + return null; } - Point[] points = new MatOfPoint(nonZeroPos).toArray(); - if (rect != null) { - for (int i = 0; i < points.length; i++) { - points[i].x = mScreenMetrics.scaleX((int) (points[i].x + rect.x)); - points[i].y = mScreenMetrics.scaleX((int) (points[i].y + rect.y)); - } - } - return points; + return new MatOfPoint(nonZeroPos); } + public Point findMultiColors(ImageWrapper image, int firstColor, int threshold, Rect rect, int[] points) { + Point[] firstPoints = findAllPointsForColor(image, firstColor, threshold, rect); + for (Point firstPoint : firstPoints) { + if (firstPoint == null) + continue; + if (checksPath(image, firstPoint, threshold, rect, points)) { + return firstPoint; + } + } + return null; + } + + private boolean checksPath(ImageWrapper image, Point startingPoint, int threshold, Rect rect, int[] points) { + for (int i = 0; i < points.length; i += 3) { + int x = points[i]; + int y = points[i + 1]; + int color = points[i + 2]; + ColorDetector colorDetector = new ColorDetector.DifferenceDetector(color, threshold); + int c = image.pixel((int) (x + startingPoint.x), (int) (y + startingPoint.y)); + if (!colorDetector.detectsColor(Color.red(c), Color.green(c), Color.blue(c))) { + return false; + } + + } + return true; + } } \ No newline at end of file