1

I want to display screenshot from adb screencap directly in python without generate a file, is there any way to do this?

I have tried opencv, here is my code:

command = r"adb shell screencap -p"
proc = subprocess.Popen(shlex.split(command),stdout=subprocess.PIPE)
out = proc.stdout.read(30000000)
img = cv2.imdecode(out,cv2.IMREAD_COLOR)
if img is not None:
    cv2.imshow("",img)
    cv2.waitKey(0)
    cv2.destroyWindow("")

but I got this error on "imdecode" line:

TypeError: buf is not a numpy array, neither a scalar

I am using python3.6 and OpenCV3.4, on Windows 7. ADB v1.0.36, Android version is 8.0

Does anyone know how to do this? Thanks.

qwer11121
  • 138
  • 2
  • 15

4 Answers4

3

Thanks to GPPK, now it's working:

pipe = subprocess.Popen("adb shell screencap -p",
                        stdin=subprocess.PIPE,
                        stdout=subprocess.PIPE, shell=True)
image_bytes = pipe.stdout.read().replace(b'\r\n', b'\n')
image = cv2.imdecode(np.fromstring(image_bytes, np.uint8), cv2.IMREAD_COLOR)
cv2.imshow("", image)
cv2.waitKey(0)
cv2.destroyWindow("")
qwer11121
  • 138
  • 2
  • 15
2

Can't comment so I will post it here instead.

The accepted answer is not working on Windows (Not sure if it's OS related).

After looking into a png file myself, I figured that it's not necessary to replace '\r\n', so deleting the following line from that solution should work.

image_bytes = pipe.stdout.read().replace(b'\r\n', b'\n')

P.S. You can check a png file yourself by using the following code:

with open("screenshot.png", 'rb') as f:
     data = f.read()

print(data)

The result should be something like: b'\x89PNG\r\n\x1a\n\x00\x00\x00........

Azure
  • 21
  • 1
1

Try to use numpy.frombuffer() to create a uint8 array from the string:

command = r"adb shell screencap -p"
proc = subprocess.Popen(shlex.split(command),stdout=subprocess.PIPE)
out = proc.stdout.read(30000000)
img = cv2.imdecode(np.frombuffer(out, np.uint8), cv2.IMREAD_COLOR)  
if img is not None:
    cv2.imshow("",img)
    cv2.waitKey(0)
    cv2.destroyWindow("")

**This is untested

GPPK
  • 6,546
  • 4
  • 32
  • 57
1

Thank's for you, another solution:

command = "adb shell \"screencap -p | busybox base64\""
pcommand = os.popen(command)
png_screenshot_data = pcommand.read()
png_screenshot_data = base64.b64decode(png_screenshot_data)
pcommand.close()
images = cv2.imdecode(np.frombuffer(png_screenshot_data, np.uint8), cv2.IMREAD_COLOR)
cv2.imshow("",images)
cv2.waitKey(0)
cv2.destroyWindow("")

for me, imdecode return None with this:

image_bytes = pipe.stdout.read().replace(b'\r\n', b'\n')
image = cv2.imdecode(np.fromstring(image_bytes, np.uint8), cv2.IMREAD_COLOR)
Systemack
  • 11
  • 1