diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000..7208d6e --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 0000000..d2b8c0c --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml new file mode 100644 index 0000000..1cd7508 --- /dev/null +++ b/.idea/jarRepositories.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..d5cd614 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,12 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/uiDesigner.xml b/.idea/uiDesigner.xml new file mode 100644 index 0000000..2b63946 --- /dev/null +++ b/.idea/uiDesigner.xml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/anchor/主页.png b/anchor/主页.png new file mode 100644 index 0000000..b157aaa Binary files /dev/null and b/anchor/主页.png differ diff --git a/anchor/野外.png b/anchor/野外.png new file mode 100644 index 0000000..3033477 Binary files /dev/null and b/anchor/野外.png differ diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..97c50ae --- /dev/null +++ b/pom.xml @@ -0,0 +1,80 @@ + + + 4.0.0 + com.example + starter-jmacro + 0.0.1-SNAPSHOT + jar + + starter-jmacro + project for Spring Boot + + + UTF-8 + UTF-8 + 8 + true + + + + + + aliyun + Aliyun Repository + default + https://maven.aliyun.com/repository/public + + + + + + aliyun + Aliyun Repository + https://maven.aliyun.com/repository/public + default + + + + + + cn.hutool + hutool-all + 5.8.26 + + + + + + ${artifactId}-${version} + + src/main/java + + + src/main/resources + + + + ${basedir}/src/main/resources/lib + BOOT-INF/lib/ + + *.jar + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + org.apache.maven.plugins + maven-compiler-plugin + + ${java.version} + ${java.version} + + + + + diff --git a/src/main/java/com/example/jmacro/ColorUtil.java b/src/main/java/com/example/jmacro/ColorUtil.java new file mode 100644 index 0000000..6c4ad97 --- /dev/null +++ b/src/main/java/com/example/jmacro/ColorUtil.java @@ -0,0 +1,40 @@ +package com.example.jmacro; + +public class ColorUtil { + + /** + * 计算两个颜色的相似度 + * + * @param colorInt1 颜色1 + * @param colorInt2 颜色2 + * @return + */ + public static double calculateSimilarity(int colorInt1, int colorInt2) { + // 计算RGB各分量的平方差 + int[] color1 = {(colorInt1 >> 16) & 0xFF, (colorInt1 >> 8) & 0xFF, colorInt1 & 0xFF}; + int[] color2 = {(colorInt2 >> 16) & 0xFF, (colorInt2 >> 8) & 0xFF, colorInt2 & 0xFF}; + int diffR = (color1[0] - color2[0]) * (color1[0] - color2[0]); + int diffG = (color1[1] - color2[1]) * (color1[1] - color2[1]); + int diffB = (color1[2] - color2[2]) * (color1[2] - color2[2]); + + // 计算欧氏距离 + double distance = Math.sqrt(diffR + diffG + diffB); + + // 计算两个颜色之间的相似度(距离越小,相似度越高) + double similarity = 1 - distance / Math.sqrt(3 * 255 * 255); + + return similarity; + } + + public static boolean isSimilar(int colorInt1, int colorInt2) { + return calculateSimilarity(colorInt1, colorInt2) > 0.99d; + } + + public static void main(String[] args) { + int color1 = 0xffffff; // 白色 + int color2 = 0xfefefe; // 非常接近白色的颜色 + + double similarity = calculateSimilarity(color1, color2); + System.out.println("Similarity: " + similarity); // 输出相似度 + } +} diff --git a/src/main/java/com/example/jmacro/CutImageTool.java b/src/main/java/com/example/jmacro/CutImageTool.java new file mode 100644 index 0000000..5286ea2 --- /dev/null +++ b/src/main/java/com/example/jmacro/CutImageTool.java @@ -0,0 +1,58 @@ +//package com.example.jmacro; +// +//import java.awt.AWTException; +//import java.awt.Point; +//import java.awt.Rectangle; +//import java.awt.Toolkit; +//import java.awt.image.BufferedImage; +// +//public class CutImageTool { +// +// /** +// * 截取指定左上角坐标,右下角坐标的屏幕区域图像 +// */ +// public static BufferedImage getScreeImage(int topLeftX, int topLeftY, int bottomRightX, int bottomRightY) throws AWTException { +// int width = bottomRightX - topLeftX; +// int height = bottomRightY - topLeftY; +// Rectangle rectangle = new Rectangle(topLeftX, topLeftY, width, height); +// return CommonUtil.getRobot().createScreenCapture(rectangle); +// } +// +// /** +// * 截取指定左上角坐标,右下角坐标的屏幕区域图像 +// * @param topLeft +// * @param bottomRight +// * @return +// * @throws AWTException +// */ +// public static BufferedImage getScreeImage(Point topLeft, Point bottomRight) throws AWTException { +// int X = topLeft.x; +// int Y = topLeft.y; +// int width = bottomRight.x - topLeft.x; +// int height = bottomRight.y - topLeft.y; +// Rectangle rectangle = new Rectangle(X, Y, width, height); +// return CommonUtil.getRobot().createScreenCapture(rectangle); +// } +// +// /** +// * 截取指定屏幕区域图像 +// * @param topLeft +// * @param bottomRight +// * @return +// * @throws AWTException +// */ +// public static BufferedImage getScreeImage(Rectangle rectangle) throws AWTException { +// return CommonUtil.getRobot().createScreenCapture(rectangle); +// } +// +// /** +// * 截取全屏幕图像 +// * @return +// * @throws AWTException +// */ +// public static BufferedImage getFullScreeImage() throws AWTException { +// Rectangle rectangle = new Rectangle(new Rectangle(Toolkit.getDefaultToolkit().getScreenSize())); +// return CommonUtil.getRobot().createScreenCapture(rectangle); +// } +//} +// diff --git a/src/main/java/com/example/jmacro/ImageMatchTools.java b/src/main/java/com/example/jmacro/ImageMatchTools.java new file mode 100644 index 0000000..df962e8 --- /dev/null +++ b/src/main/java/com/example/jmacro/ImageMatchTools.java @@ -0,0 +1,297 @@ +//package com.example.jmacro; +// +//import java.awt.AWTException; +//import java.awt.Point; +//import java.awt.image.BufferedImage; +//import java.io.File; +//import java.io.FileInputStream; +//import java.io.FileNotFoundException; +//import java.io.IOException; +//import java.io.ObjectInputStream; +//import java.util.ArrayList; +//import java.util.List; +// +// +///** +// * 图像匹配 +// * @author Jiyh +// * +// */ +//public class ImageMatchTools { +// +// /** +// * 全屏幕查找指定区域的图像 +// * @param topLeft +// * @param bottomRight +// * @return +// * @throws AWTException +// */ +// public static int[] findImageInFullScreen(Point topLeft, Point bottomRight) throws AWTException { +// BufferedImage smallImage = CutImageTool.getScreeImage(topLeft, bottomRight); +// BufferedImage screencapture = CutImageTool.getFullScreeImage(); +// +// return findImage(screencapture, smallImage); +// } +// +// /** +// * 全屏幕区域查找指定文件代表的图像 +// * @param bigImage +// * @param smallImageFileName +// * @return +// * @throws AWTException +// */ +// public static int[] findImage( String smallImageFileName) throws AWTException { +// BufferedImage screenImage = CutImageTool.getFullScreeImage(); +// return findImage(screenImage, ImageMatchTools.readImageRGB2Object(smallImageFileName)); +// } +// +// /** +// * 在指定屏幕区域查找指定文件代表的图像 +// * @param bigImage +// * @param smallImageFileName +// * @return +// */ +// public static int[] findImage(BufferedImage creenImage, String smallImageFileName) { +// return findImage(creenImage, ImageMatchTools.readImageRGB2Object(smallImageFileName)); +// } +// +// /** +// * 在游戏屏幕区域查找指定文件代表的图像 +// * @param gameScreenTopLeft +// * @param gameScreenBottomRight +// * @param smallImageFileName +// * @return +// * @throws AWTException +// */ +// public static int[] findImageInGameScreen( String smallImageFileName) throws AWTException { +// BufferedImage gameScreenImage = CutImageTool.getScreeImage(GameScreen.topLeft, GameScreen.bottomRight); +// return findImage(gameScreenImage, ImageMatchTools.readImageRGB2Object(smallImageFileName)); +// } +// +// /** +// * 在指定屏幕区域查找指定二位数组代表的图像 +// * @param bigImage +// * @param smallRgbArray +// * @return +// */ +// public static int[] findImage(BufferedImage bigImage, int[][] smallRgbArray) { +// int bigWidth = bigImage.getWidth(); +// +// int bigHeight = bigImage.getHeight(); +// +// int smallWidth = smallRgbArray.length; +// +// int smallHeight = smallRgbArray[0].length; +// +// int[][] bigData = getImageRGB(bigImage); +// +// int[][] smallData = smallRgbArray; +// +// int[] target = { -1, -1 }; +// +// int yEnd = bigHeight - smallHeight; +// int xEnd = bigWidth - smallWidth; +// +// for (int y = 0; y < yEnd; y++) { +// for (int x = 0; x < xEnd; x++) { +// // 对关键点进行先期匹配,降低运算复杂度。如果关键点本身就不匹配,就没必要再去匹配小图的每一个像素点 +// if (bigData[x][y] == smallData[0][0] // 左上角 +// && bigData[x + smallWidth - 1][y] +// == smallData[smallWidth - 1][0] // 右上角 +// && bigData[x][y + smallHeight - 1] == smallData[0][smallHeight - 1] // 左下角 +// && bigData[x + smallWidth - 1][y + smallHeight - 1] == smallData[smallWidth - 1][smallHeight +// - 1] // 右下角 +// && bigData[x + smallWidth / 2][y + smallHeight / 2] == smallData[smallWidth / 2][smallHeight +// / 2]) { +// +// // 进行全像素匹配 +// boolean isMatched = checkAllMatch(x, y, smallHeight, smallWidth, bigData, smallData); +// if (isMatched) { +// System.out.println("像素点X" + x + " : Y" + y + ",对应的值为:" + bigData[x][y]); +// +// // 获取小图的中心位置的点 +// int centerX = x + smallWidth/2; +// int centerY = y + smallHeight/2; +// target[0] = centerX; +// target[1] = centerY; +// return target; +// } +// } +// +// } +// } +// +// return target; +// } +// +// /** +// * 在指定屏幕区域查找指定图像 +// * @param bigImage +// * @param smallImage +// * @return +// */ +// public static int[] findImage(BufferedImage bigImage, BufferedImage smallImage) { +// +// int bigWidth = bigImage.getWidth(); +// +// int bigHeight = bigImage.getHeight(); +// +// int smallWidth = smallImage.getWidth(); +// +// int smallHeight = smallImage.getHeight(); +// +// int[][] bigData = getImageRGB(bigImage); +// +// int[][] smallData = getImageRGB(smallImage); +// +// int[] target = { -1, -1 }; +// +// int yEnd = bigHeight - smallHeight; +// int xEnd = bigWidth - smallWidth; +// +// for (int y = 0; y < yEnd; y++) { +// for (int x = 0; x < xEnd; x++) { +// // 对关键点进行先期匹配,降低运算复杂度。如果关键点本身就不匹配,就没必要再去匹配小图的每一个像素点 +// if (bigData[x][y] == smallData[0][0] // 左上角 +// && bigData[x + smallWidth - 1][y] == smallData[smallWidth - 1][0] // 右上角 +// && bigData[x][y + smallHeight - 1] == smallData[0][smallHeight - 1] // 左下角 +// && bigData[x + smallWidth - 1][y + smallHeight - 1] == smallData[smallWidth - 1][smallHeight +// - 1] // 右下角 +// && bigData[x + smallWidth / 2][y + smallHeight / 2] == smallData[smallWidth / 2][smallHeight +// / 2]) { +// +// // 进行全像素匹配 +// boolean isMatched = checkAllMatch(x, y, smallHeight, smallWidth, bigData, smallData); +// if (isMatched) { +// System.out.println("像素点X" + x + " : Y" + y + ",对应的值为:" + bigData[x][y]); +// +// // 获取小图的中心位置的点 +// int centerX = x + smallWidth/2; +// int centerY = y + smallHeight/2; +// target[0] = centerX; +// target[1] = centerY; +// return target; +// } +// } +// +// } +// } +// +// return target; +// } +// +// private static boolean checkAllMatch(int x, int y, int smallHeight, int smallWidth, int[][] bigData, +// int[][] smallData) { +// boolean isMatched = true; +// for (int smallY = 0; smallY < smallHeight; smallY++) { +// for (int smallX = 0; smallX < smallWidth; smallX++) { +// // 如果发现有一个像素点,两者的值不一样,则认为不相等,如果不相等,则没必要继续比较其它点. +// if (bigData[x + smallX][y + smallY] != smallData[smallX][smallY]) { +// isMatched = false; +// return isMatched; +// } +// } +// } +// return isMatched; +// } +// +// public static int[][] getImageRGB(BufferedImage bfImage) { +// int width = bfImage.getWidth(); +// +// int height = bfImage.getHeight(); +// +// int[][] result = new int[width][height]; +// +// for (int y = 0; y < height; y++) { +// for (int x = 0; x < width; x++) { +// // 对某个像素点的RGB编码并存入数据库 +// result[x][y] = bfImage.getRGB(x, y) & 0xFFFFFF; +// +// // 单独获取每一个像素点的Red,Green,和Blue的值。 +// +// // int r = (bfImage.getRGB(x, y) & 0xFF0000) >> 16; +// +// // int g = (bfImage.getRGB(x, y) & 0xFF00) >> 8; +// +// // int b = bfImage.getRGB(x, y) & 0xFF; +// +// } +// +// } +// +// return result; +// +// } +// +// public static int[][] readImageRGB(String fileName) { +// List rgbList = new ArrayList(); +// TxtFileReader tfr = null; +// try { +// tfr = new TxtFileReader(fileName); +// String line = null; +// while ((line = tfr.readLine()) != null){ +// String[] rgbStringArray = line.split(","); +// int[] rfgArray = new int[rgbStringArray.length]; +// for (int i = 0; i < rgbStringArray.length; i++) { +// rfgArray[i] = Integer.parseInt(rgbStringArray[i]); +// } +// rgbList.add(rfgArray); +// } +// } catch (IOException e) { +// // TODO Auto-generated catch block +// e.printStackTrace(); +// }finally { +// if(tfr != null){ +// tfr.close(); +// } +// } +// +// int[][] rgbArray = new int[rgbList.size()][]; +// for (int i = 0; i < rgbArray.length; i++) { +// rgbArray[i] = rgbList.get(i); +// } +// +// return rgbArray; +// } +// public static int[][] readImageRGB2Object(String filePath) { +// File file = new File(filePath); +// FileInputStream fis = null; +// ObjectInputStream ois = null; +// try { +// fis = new FileInputStream(file); +// ois = new ObjectInputStream(fis); +// Object data = ois.readObject(); +// return (int[][])data; +// } catch (FileNotFoundException e) { +// // TODO Auto-generated catch block +// e.printStackTrace(); +// } catch (IOException e) { +// // TODO Auto-generated catch block +// e.printStackTrace(); +// } catch (ClassNotFoundException e) { +// // TODO Auto-generated catch block +// e.printStackTrace(); +// }finally { +// if(ois != null){ +// try { +// ois.close(); +// } catch (IOException e) { +// // TODO Auto-generated catch block +// e.printStackTrace(); +// } +// } +// if(fis != null){ +// try { +// fis.close(); +// } catch (IOException e) { +// // TODO Auto-generated catch block +// e.printStackTrace(); +// } +// } +// } +// +// return null; +// } +// +//} +// diff --git a/src/main/java/com/example/jmacro/JMacro.java b/src/main/java/com/example/jmacro/JMacro.java new file mode 100644 index 0000000..1b34e10 --- /dev/null +++ b/src/main/java/com/example/jmacro/JMacro.java @@ -0,0 +1,24 @@ +package com.example.jmacro; + +import java.io.File; + +/** + * 脚本 + */ +public class JMacro { + + /** + * 图例位置 + */ + private File legend; + + public JMacro() { + } + + /** + * 定位 + */ + private boolean location(){ + + } +} diff --git a/src/main/java/com/example/jmacro/LogUtil.java b/src/main/java/com/example/jmacro/LogUtil.java new file mode 100644 index 0000000..326aa7c --- /dev/null +++ b/src/main/java/com/example/jmacro/LogUtil.java @@ -0,0 +1,15 @@ +package com.example.jmacro; + +import cn.hutool.core.util.StrUtil; + +public class LogUtil { + + public static void info(String log, Object... arg) { + System.out.println(StrUtil.format(log, arg)); + } + + public static void error(String log, Object... arg) { + + System.err.println(StrUtil.format(log, arg)); + } +} diff --git a/src/main/java/com/example/jmacro/Main.java b/src/main/java/com/example/jmacro/Main.java new file mode 100644 index 0000000..3e7a8d0 --- /dev/null +++ b/src/main/java/com/example/jmacro/Main.java @@ -0,0 +1,118 @@ +package com.example.jmacro; + +import cn.hutool.core.img.ImgUtil; +import cn.hutool.json.JSONUtil; +import org.w3c.dom.css.Rect; + +import java.awt.*; +import java.awt.image.BufferedImage; +import java.io.File; + +public class Main { + + static Robot robot; + + static { + try { + robot = new Robot(); + } catch (AWTException e) { + throw new RuntimeException(e); + } + } + + public static void main(String[] args) throws AWTException { + int[] aa = findImage(loadScreen(), loadAnchor("野外")); + + System.out.println(JSONUtil.toJsonStr(aa)); + } + + public static Rect findImage(BufferedImage bigImage, BufferedImage smallImage) { + int bigWidth = bigImage.getWidth(); + int bigHeight = bigImage.getHeight(); + int smallWidth = smallImage.getWidth(); + int smallHeight = smallImage.getHeight(); + int[][] bigData = getImageRGB(bigImage); + int[][] smallData = getImageRGB(smallImage); + int[] target = {-1, -1}; + int yEnd = bigHeight - smallHeight; + int xEnd = bigWidth - smallWidth; + + for (int y = 0; y < yEnd; y++) { + for (int x = 0; x < xEnd; x++) { + // 对关键点进行先期匹配,降低运算复杂度。如果关键点本身就不匹配,就没必要再去匹配小图的每一个像素点 + if (ColorUtil.isSimilar(bigData[x][y], smallData[0][0]) && // 左上角 + ColorUtil.isSimilar(bigData[x + smallWidth - 1][y], smallData[smallWidth - 1][0]) &&// 右上角 + ColorUtil.isSimilar(bigData[x][y + smallHeight - 1], smallData[0][smallHeight - 1]) &&// 左下角 + ColorUtil.isSimilar(bigData[x + smallWidth - 1][y + smallHeight - 1], smallData[smallWidth - 1][smallHeight - 1]) && // 右下角 + ColorUtil.isSimilar(bigData[x + smallWidth / 2][y + smallHeight / 2], smallData[smallWidth / 2][smallHeight / 2]) //中心点 + ) { + + // 进行全像素匹配 + boolean isMatched = checkAllMatch(x, y, smallHeight, smallWidth, bigData, smallData); + if (isMatched) { + System.out.println("像素点X" + x + " : Y" + y + ",对应的值为:" + bigData[x][y]); + + // 获取小图的中心位置的点 + int centerX = x + smallWidth / 2; + int centerY = y + smallHeight / 2; + target[0] = centerX; + target[1] = centerY; + return new int[][]{{x,y},}; + return new Rect + } + } + + } + } + + return target; + } + + public static int[][] getImageRGB(BufferedImage bfImage) { + int width = bfImage.getWidth(); + int height = bfImage.getHeight(); + int[][] result = new int[width][height]; + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + // 对某个像素点的RGB编码并存入数据库 + result[x][y] = bfImage.getRGB(x, y) & 0xFFFFFF; + + // 单独获取每一个像素点的Red,Green,和Blue的值。 + // int r = (bfImage.getRGB(x, y) & 0xFF0000) >> 16; + // int g = (bfImage.getRGB(x, y) & 0xFF00) >> 8; + // int b = bfImage.getRGB(x, y) & 0xFF; + } + } + return result; + } + + private static boolean checkAllMatch(int x, int y, int smallHeight, int smallWidth, int[][] bigData, int[][] smallData) { + boolean isMatched = true; + for (int smallY = 0; smallY < smallHeight; smallY++) { + for (int smallX = 0; smallX < smallWidth; smallX++) { + // 如果发现有一个像素点,两者的值不一样,则认为不相等,如果不相等,则没必要继续比较其它点. + if (!ColorUtil.isSimilar(bigData[x + smallX][y + smallY], smallData[smallX][smallY])) { + isMatched = false; + return isMatched; + } + } + } + return isMatched; + } + + + // 获取屏幕截图 + static BufferedImage loadScreen() { + // 获取缺省工具包 + Toolkit tk = Toolkit.getDefaultToolkit(); + // 屏幕尺寸规格 + Dimension di = tk.getScreenSize(); + LogUtil.info("获取屏幕尺寸({},{})", di.width, di.height); + Rectangle rec = new Rectangle(0, 0, di.width, di.height); + return robot.createScreenCapture(rec); + } + + static BufferedImage loadAnchor(String anchor) { + return ImgUtil.read(new File("anchor", anchor + ".png")); + } +}