поток видео Python пропустить кадры - PullRequest
0 голосов
/ 18 марта 2019

Я хочу жить поиск экрана моего телефона Android с OpenCV и Python. Мой телефон передает свой экран через http, и я читаю поток с некоторым кодом, подобным этому:

host = "192.168.178.168:8080"
hoststr = 'http://' + host +  '/stream.mjpeg'
print 'Streaming ' + hoststr
stream=urllib2.urlopen(hoststr)
bytes=''
drop_count = 0
while True:
    bytes+=stream.read(1024)
    a = bytes.find('\xff\xd8')
    b = bytes.find('\xff\xd9')
    if a!=-1 and b!=-1:
        drop_count+=1
        if drop_count > 120:
            drop_count = 0
            jpg = bytes[a:b+2]
            bytes= bytes[b+2:]
            i=cv2.imdecode(np.fromstring(jpg,dtype=np.uint8),cv2.IMREAD_COLOR)
            cv2.imshow(hoststr,i)
            process_img(i)#my image processing
            if cv2.waitKey(1) ==27:
                exit(0)

Проблема в том, что мой поиск на экране занимает слишком много времени и создает большую задержку. Поскольку частота кадров, которые посылает мой телефон, очень высока, мне бы хотелось обрабатывать только одно изображение в секунду или в течение двух секунд. Как я могу это сделать? Я не могу изменить fps на моем телефоне. Я могу изменить размер изображения на экране телефона до 50% перед отправкой, но если я изменю его размер более чем на 50%, я больше не могу найти то, что ищу, с помощью opencv. Но даже при изменении размера на 50% это слишком сильно задерживается. Если я сделаю простой счетчик и обработаю только каждое изображение 2/10/30, это не поможет.

РЕДАКТИРОВАТЬ: я добавил свою простую реализацию счетчика для удаления кадров, это не помогает. Если я не обрабатываю изображение, я получаю постоянную небольшую задержку с кадрированием и без него.

EDIT²: наконец-то решил, к сожалению, я не помню, где я его читал, но это очень просто с openCV VideoCapture:

screen_capture = cv2.VideoCapture(stream_url) #init videocapture
drop_count = 0 #init drop counter
while True:
    drop_count+=1
    ret = screen_capture.grab() #grab frame but dont process it
    if drop_count % 5 == 0: #check if not dropping frame
        ret, img = self.screen_capture.retrieve() #process frame

Таким образом, кадры, которые вы хотите отбросить, действительно удаляются, и задержка не возникает.

1 Ответ

0 голосов
/ 19 марта 2019

Я предполагаю, что задержка становится такой длинной, потому что вы отображаете только обработанные кадры.Фактически показывается только 1 из каждых 120 кадров.И этот кадр показан для следующих 120 кадров и времени обработки.Это на самом деле может показаться запаздывающим.
Вы должны отображать все кадры нормально и вызывать функцию process_img() только на каждом 120-м кадре.
Попробуйте, если это улучшит ситуацию:

if a!=-1 and b!=-1:
    drop_count+=1
    jpg = bytes[a:b+2]
    bytes= bytes[b+2:]
    i=cv2.imdecode(np.fromstring(jpg,dtype=np.uint8),cv2.IMREAD_COLOR)
    cv2.imshow(hoststr,i)
    if drop_count > 120: # only process every 120th frame
        drop_count = 0
        process_img(i)#my image processing
    if cv2.waitKey(1) ==27:
        exit(0)
...