前序:
今天有幸,看到2位部落客的文章,在此表示感謝。自己也動手實作了一下。
實作原理 請參考部落客 https://www.cnblogs.com/dongkuo/p/8285162.html
另感謝部落客 http://www.cnblogs.com/litblank/p/8267526.html 提供的基礎部分代碼,免去了我自己再寫一邊的麻煩。
由于第一篇是python 實作,樓主是JAVA出生,想通過java實作,剛好在評論中看到了 第二位部落客的java實作連接配接,但是自己用部落客的代碼,測試發現效果并不理想,擷取的位置點不對。。。可能是打開方式不對~~~0.0
遂根據第一位部落客的思路,重新實作了一下,親測3張圖,基本都是ok 的,下面就看看代碼部分的實作。
代碼實作:
1 package code;
2
3 import java.awt.AWTException;
4 import java.awt.Graphics2D;
5 import java.awt.Transparency;
6 import java.awt.image.BufferedImage;
7 import java.io.File;
8 import java.io.IOException;
9 import java.io.InputStreamReader;
10 import java.io.LineNumberReader;
11 import java.util.Map;
12 import java.util.Map.Entry;
13 import java.util.TreeMap;
14 import javax.imageio.ImageIO;
15
16 public class Jump {
17 //存放圖檔的路徑
18 static String file1 = "C:\\Users\\JJJ\\Desktop\\jump3.jpg";
19 //始 掃描行,針對不同的手機分辨率可能不一樣,需要修改,此處建議手工測量下坐上角跳躍步數的數字位置,估算出起始行 樓主的手機是se 像素是 1156*640
20 static int start_y = 200;
21 static boolean istest = false;
22 static int background_x = 10; //定義預設的背景色,一定是不會出現其他物體的位置
23 static int background_y = 580;
24
25 public static void main(String[] args) throws AWTException, InterruptedException, IOException {
26 istest = true;
27
28
29 System.out.println("開始:計算" + file1);
30 if (istest) {
31 cmd_java("cmd /c start adb.bat ", "C:\\Users\\JJJ\\Downloads\\cofface_adb\\cofface_adb_windows_v5.1");//批處理檔案
32 }
33 BufferedImage bi = (BufferedImage) ImageIO.read(new File(file1));
34 Map<Integer, Integer> treemap = new TreeMap<Integer, Integer>();
35 // 擷取圖像的寬度和高度
36 int width = bi.getWidth();
37 int height = bi.getHeight();
38 //小人中心點坐标
39 int poix = 0;
40 int poiy = 0;
41 //目标物體的最頂點X軸 和左邊或右邊的Y軸
42 int mubiaopoix1 = 0;
43 int mubiaopoiy2 = 0;
44 //目标中心點坐标
45 int mubiaopoix = 0;
46 int mubiaopoiy = 0;
47 BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
48 Graphics2D g2d = img.createGraphics();
49 // 設定畫布為透明
50 img = g2d.getDeviceConfiguration().createCompatibleImage(width, height, Transparency.TRANSLUCENT);
51 // 掃描圖檔,擷取小人的底部中心坐标
52 for (int i = start_y; i < height; i++) {
53 for (int j = 0; j < width; j++) {// 行掃描
54 int dip = bi.getRGB(j, i);
55 int p = dip;
56 int red = 0xff & (p >> 16);
57 int green = 0xff & (p >> 8);
58 int blue = 0xff & p;
59 // 目标人圖形
60 if (i < (height / 1.5))
61 {
62 if ((red > 53 && red < 59) && (green > 57 && green < 61) && (blue > 59 && blue < 103))
63 { // 擷取小人坐标,從中取除Y值最大的一個
64 treemap.put(i, j);
65 }
66 }
67 }
68 }
69 //擷取最後的小人底部坐标 ,此處使用treemap 直接排好序,循環擷取Y軸值最大的一個
70 for (Entry<Integer, Integer> entry : treemap.entrySet())
71 {
72 poiy = entry.getKey();
73 poix = entry.getValue();
74 }
75 //開始掃描目标物體的最上和最左坐标 ,掃描的Y最大值為目前小人的Y值
76 treemap.clear(); //清除前面的記錄,準備存放目标物體的坐标
77 RGB rgb = null;
78 boolean frist = true;
79 RGB rgb_0 = pixToRgb(bi, background_x, background_y); //預設的背景色
80 for (int y = start_y; y < poiy; y++) {
81 int x = 0;
82 if (poix < width /2) //此處特别說明下,如果小人的坐标在整個螢幕的左邊,則目标物體一定在右邊,遂起始x軸從小人之後開始加20開始循環,反之則不用
83 {
84 x = poix + 20;
85 }
86 else
87 {
88 x = 20;
89 }
90 for (; x < width - 20; x++) {// 行掃描
91 int dip = bi.getRGB(x, y);
92 int p = dip;
93 RGB rgb_1 = pixToRgb(bi, x, y);
94 if(frist && rgbCz(rgb_0,rgb_1,10)) //如果不相同則說明找到了第一個點
95 {
96 mubiaopoix1 = x;
97 rgb = rgb_1;
98 frist = false;
99 continue;
100 }
101 if (!frist && rgbBcz(rgb,rgb_1,10))
102 {
103 treemap.put(x, y); //存放所有目前台面的像素點坐标,然後從中選出X值最小的一個,
104 }
105 }
106 }
107 //擷取目标物體的坐标,如果是在右半邊,則擷取最後一個值的Y軸,如果是在左邊,則擷取第一個
108 if (poix > width / 2)
109 {
110 for (Entry<Integer, Integer> entry : treemap.entrySet())
111 {
112 mubiaopoiy2 = entry.getValue();
113 break;
114 }
115 }
116 else
117 {
118 for (Entry<Integer, Integer> entry : treemap.entrySet())
119 {
120 mubiaopoiy2 = entry.getValue();
121 }
122 }
123 //通過擷取的2個點坐标計算出中心點位置
124 mubiaopoix = mubiaopoix1;
125 mubiaopoiy = mubiaopoiy2;
126 //計算 小人與目标人物的距離
127 int total = (mubiaopoix - poix) * (mubiaopoix - poix) + (mubiaopoiy - poiy) * (mubiaopoiy - poiy);
128 double length = (double) Math.sqrt(total);
129 double time = length * 1.35; //時間系數
130 System.out.println("小人的坐标為:" + poix + "," + poiy);
131 System.out.println("目标物體的坐标為:" + mubiaopoix + "," + mubiaopoiy);
132 System.out.println("需要按壓螢幕的時間為:" + time + "毫秒");
133 }
134 153
154 static InputStreamReader ir = null;
155 static LineNumberReader input = null;
156
157 public static void cmd_java(String cmd) throws IOException {
158 Process process = Runtime.getRuntime().exec(cmd, null, new File("C:\\Users\\chenyd\\adb"));
159 ir = new InputStreamReader(process.getInputStream());
160 input = new LineNumberReader(ir);
161 while (input.readLine() != null) {
162 }
163 input.close();
164 ir.close();
165 }
166
167 public static void cmd_java(String cmd, String url) throws IOException {
168 Process process = Runtime.getRuntime().exec(cmd, null, new File(url));
169 ir = new InputStreamReader(process.getInputStream());
170 input = new LineNumberReader(ir);
171 while (input.readLine() != null) {
172 System.out.println(11);
173 }
174 input.close();
175 ir.close();
176 }
177
178 /**
179 * 顔色的內插補點不在範圍内
180 */
181 public static boolean rgbCz(RGB rgb_1, RGB rgb_2, int fd_rgb) {
182 if (Math.abs(rgb_1.getRed() - rgb_2.getRed()) > fd_rgb && Math.abs(rgb_1.getGreen() - rgb_2.getGreen()) > fd_rgb
183 && Math.abs(rgb_1.getBlue() - rgb_2.getBlue()) > fd_rgb) {
184 return true;
185 }
186 return false;
187 }
188
189 /**
190 * 顔色的內插補點在範圍内
191 */
192 public static boolean rgbBcz(RGB rgb_1, RGB rgb_2, int fd_rgb) {
193 if (Math.abs(rgb_1.getRed() - rgb_2.getRed()) < fd_rgb && Math.abs(rgb_1.getGreen() - rgb_2.getGreen()) < fd_rgb
194 && Math.abs(rgb_1.getBlue() - rgb_2.getBlue()) < fd_rgb) {
195 return true;
196 }
197 return false;
198 }
199
200 public static RGB pixToRgb(BufferedImage bi, int j, int i) {
201 try {
202 int dip = bi.getRGB(j, i);
203 int p = dip;
204 int red = 0xff & (p >> 16);
205 int green = 0xff & (p >> 8);
206 int blue = 0xff & p;
207 return new RGB(j, i, red, green, blue);
208 } catch (Exception e) {
209
210 }
211 return null;
212 }
213
214 }
215
216 class RGB {
217
218 public RGB() {
219 }
220
221 public RGB(int x, int y, int red, int green, int blue) {
222 super();
223 X = x;
224 Y = y;
225 this.red = red;
226 this.green = green;
227 this.blue = blue;
228 }
229
230 public int X;
231 public int Y;
232 public int red;
233 public int green;
234 public int blue;
235
236 public int getRed() {
237 return red;
238 }
239
240 public void setRed(int red) {
241 this.red = red;
242 }
243
244 public int getGreen() {
245 return green;
246 }
247
248 public void setGreen(int green) {
249 this.green = green;
250 }
251
252 public int getBlue() {
253 return blue;
254 }
255
256 public void setBlue(int blue) {
257 this.blue = blue;
258 }
259
260 public int getX() {
261 return X;
262 }
263
264 public void setX(int x) {
265 X = x;
266 }
267
268 public int getY() {
269 return Y;
270 }
271
272 public void setY(int y) {
273 Y = y;
274 }
275
276 }
由于樓主目前沒有安卓裝置,還無法帶上adb實驗,目前隻是通過手動截取圖檔,和測量距離計算了3張,總體比較下來,還算是正确的。
第一張圖檔
計算結果如圖:
第二張圖檔
計算結果如圖:
第三張圖檔
後續再搞個安卓裝置試試~
give me the ball!