方案一
一种方法是先通过 adb screencap 将截屏保存到手机里。再通过 adb pull 将图片从手机传输到本地,具体命令如下:
adb screencap -p > /sdcard/screen.png
adb pull /sdcard/screen.png ./screen.png
然后再用 OpenCV 读取图片即可使用。
不过对于需要直接操作图片的情况,这个方法就有点多此一举了。直接传输流数据的方案二就更为合适。
方案二
获取文件数据
screencap -p 可以将截屏的数据流直接输出,尝试运行了如下adb命令, 确实得到了屏幕截图:
adb shell screencap -p > /sdcard/screen.png
这样就可以通过 stdout 来获取图片了,尝试通过 Python 获取截屏并保存:
#adb调用获取截图数据流, ps: 127.0.0.1:7555 为手机的端口号,这里我使用模拟器来测试
process = subprocess.Popen(
['adb', '-s', '127.0.0.1:7555', 'shell', 'screencap', '-p'],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)
stdout = proc.stdout.read()
#保存图片
with open('./screnn.png', 'wb') as f:
a = f.write(stdout)
保存后发现图片并不能被使用,经过对比截屏图片和代码保存的图片发现了问题:在 Windows 中,Python 获取的图片数据会把原数据流中的 \n 转义为 \r\r\n 或 \r\n,所以图片无法被正常识别。
既然知道了原因,我们只要进行反向操作就能获得原来的截屏数据了:
#将输出中的 \r\r\n 和 \r\n 替换为 \n 就是原图了
stdout.replace(b'\r\n', b'\n').replace(b'\r\n', b'\n')
cv加载图片数据
获取图片数据流后,就是用 OpenCV 加载了, 不过 OpenCV 常用的 cv.imread() 方法只能从文件中获取图片。 需要用 cv.imdecode() 方法加载数据流:
# 先用 bytearray 将图片数据流转为 ByteArray 格式,再用 numpy.asarray 将 Bytearray 转为数组。
array = numpy.asarray(bytearray(byteImage), dtype=numpy.uint8),
# 获取图片
img = cv.imdecode(array, cv.IMREAD_COLOR)
这样就用成功的用 OpenCV 加载图片了,接下来就可以按你的想法操作截屏了。
代码
# 方案一
def screencap1():
cmd('adb -s 127.0.0.1:7555 shell screencap -p > /sdcard/screen.png')
cmd('adb -s 127.0.0.1:7555 pull /sdcard/screen.png ./screen.png')
return cv.imread('./screen.png')
# 方案二
def screencap2():
byteImage = cmd('adb -s 127.0.0.1:7555 shell screencap -p').replace(b'\r\n', b'\n').replace(b'\r\n', b'\n')
# opencv读取内存图片
return cv.imdecode(numpy.asarray(bytearray(byteImage), dtype=numpy.uint8), cv.IMREAD_COLOR)
# 执行命令
def cmd(cmdStr: str):
cmds = cmdStr.split(' ')
proc = subprocess.Popen(
cmds,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)
stdout, stderr = proc.communicate()
# returncode 代表执行cmd命令报错
if proc.returncode > 0:
raise Exception(proc.returncode, stderr)
return stdout
本文介绍了如何通过Python的ADB模块配合OpenCV直接获取手机截屏数据,避免了先保存再传输的步骤。在方案二中,通过ADB获取到的数据流在Windows环境下因字符转义导致图片无法识别,通过对数据流的处理,成功用OpenCV的imdecode方法加载图片。
3649

被折叠的 条评论
为什么被折叠?



