开发背景
一般来说,我们可以通过adb shell screencap指令来截取android设备中的图像,但是获取到的是完整的图像。当我们需要进行图像识别的操作时,需要获取指定区域的图像来进行对比。
功能实现
C#
部分代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
|
public void ScreenCapAndCrop(int x, int y, int width, int height, string savePath = "screencap.png") { Stream stream = NProcess.RunReturnStream($"adb -s {_serial} shell screencap -p"); List<byte> data = ReadStreamAndConvertCRLF(stream); if (data.Count == 0) { Log.Error($"{_serial} screencap failed!"); return; } byte[] imageData = [.. data];
using MemoryStream ms = new(imageData); using Bitmap bitmap = new(ms); Rectangle cropRect = new(x, y, width, height);
using Bitmap croppedImage = bitmap.Clone(cropRect, bitmap.PixelFormat); croppedImage.Save(savePath, ImageFormat.Png); }
private static List<byte> ReadStreamAndConvertCRLF(Stream stream) { ArgumentNullException.ThrowIfNull(stream);
List<byte> data = []; byte[] buffer = new byte[1024]; int read; bool isCR = false; do { byte[] buf = new byte[1024]; read = stream.Read(buf, 0, buf.Length);
for (int i = 0; i < read; i++) { if (isCR && buf[i] == 0x0A) { isCR = false; data.RemoveAt(data.Count - 1); data.Add(buf[i]); continue; } isCR = buf[i] == 0x0D; data.Add(buf[i]); } } while (read > 0); return data; }
|
其中_serial为设备号,通过adb devices获取,具体代码就不列举了。
python
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| import subprocess from PIL import Image import io
def get_screenshot_and_crop(x, y, width, height, output_path="screencap.png"): process = subprocess.Popen( ['adb', 'shell', 'screencap', '-p'], stdout=subprocess.PIPE, stderr=subprocess.PIPE ) stdout, stderr = process.communicate()
if b'\r\n' in stdout: stdout = stdout.replace(b'\r\n', b'\n')
image = Image.open(io.BytesIO(stdout)) cropped_image = image.crop((x, y, x + width, y + height)) cropped_image.save(output_path)
|
相关依赖
NProcss