Python — Kivy как интегрировать OpenCV?

#python #opencv #camera #kivy #ip

Вопрос:

У меня проблема с сочетанием opencv и kivy! У меня есть код, который подключает меня к моей ip-камере на python и показывает ее прямую трансляцию. Этот код (без kivy) работает отлично:

 import cv2
import numpy as np
import urllib.request
from urllib.request import urlopen
import matplotlib.pylab as plt
from matplotlib import cm
from sympy.solvers import solve
from sympy import Symbol
from sympy import lambdify
from sympy import *
 
 
def connection(host='http://192.168.4.1:81/stream'):
    try:
        urllib.request.urlopen(host)
        return True
    except:
        return False
 
def startlivecamimage():
    if connection():
        stream = urlopen('http://192.168.4.1:81/stream') 
        bytes = b''
        while True: 
            try:
                bytes  = stream.read(1024) 
                a = bytes.find(b'xffxd8') 
                b = bytes.find(b'xffxd9') 
                if a != -1 and b != -1: 
                    jpg = bytes[a:b 2] 
                    bytes = bytes[b 2:] 
                    getliveimage = cv2.imdecode(np.frombuffer(jpg, dtype=np.uint8), cv2.IMREAD_COLOR)
                    livestreamrotated1 = cv2.rotate(getliveimage, cv2.ROTATE_90_CLOCKWISE)
                    
                cv2.imshow('WeldCam LIVE', livestreamrotated1) 
 
            except Exception as e:
                continue
 
            keyPress = cv2.waitKey(1)
 
startlivecamimage()
 

Но когда я хочу использовать один и тот же код в сочетании с экраном киви и нажатием кнопки, он больше не работает:

 from logging import info
import cv2
import numpy as np
import urllib.request
from urllib.request import urlopen
import os
import platform
import datetime
import time
import sys
import math
import matplotlib.pylab as plt
import threading
from matplotlib import cm
from numpy.core.fromnumeric import repeat
from numpy.core.numeric import False_
from sympy.solvers import solve
from sympy import Symbol
from sympy import lambdify
from sympy import *
from datetime import datetime
from colorama import init, Fore, Back, Style
import kivy
from kivy.app import App
from kivy.clock import Clock
from kivy.effects.dampedscroll import DampedScrollEffect
from kivy.effects.scroll import ScrollEffect
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.label import Label
from kivy.uix.gridlayout import GridLayout
from kivy.uix.textinput import TextInput
from kivy.uix.slider import Slider
from kivy.uix.image import Image
from kivy.graphics.texture import Texture
from kivy.uix.button import Button
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.popup import Popup
from kivy.uix.relativelayout import RelativeLayout
from kivy.uix.settings import SettingsWithSpinner, SettingItem
from kivy.clock import Clock, mainthread
from kivy.core.window import Window
from kivy.uix.scrollview import ScrollView
from kivy.effects.scroll import ScrollEffect
from kivy.lang import Builder
import json
 
INTERVAL = 0.01
 
kivy.require("2.0.0")
 
Builder.load_string("""
#:import Factory kivy.factory.Factory
 
<MyScreens>:
    Screen:
        name: 'mainmenuscreen'
        BoxLayout:
            spacing: 1
            orientation: "vertical"
 
            Button:
                text: 'Start IP Camera'
                on_release: 
                    app.ip_camera_schedule()
 
            Button:
                text: 'Quit'
                on_release: root.current = app.exit_software()
""")
 
class MyScreens(ScreenManager):
    pass
 
 
#Program is called "SchweißnahtlehreApp"
class SchweißnahtlehreApp(App):
    def __init__(self,*args,**kwargs):
        super().__init__(*args,**kwargs)
 
 
    def build(self):
        myscreenmanager = MyScreens()
        return myscreenmanager
 
    #function to check connection to IP Camera
    def connection(host='http://192.168.4.1:81/stream'):
        try:
            urllib.request.urlopen(host)
            return True
        except:
            return False
 
    def ip_camera_schedule(self):
        if SchweißnahtlehreApp.connection():
                Clock.schedule_interval(self.startipcamera, 0.5)
 
    def startipcamera(self, *args):
        stream = urlopen('http://192.168.4.1:81/stream') 
        bytes = b''
        try:
            print("trying...")
            bytes  = stream.read(1024) 
            a = bytes.find(b'xffxd8') 
            b = bytes.find(b'xffxd9') 
            if a != -1 and b != -1:
                print("step 1 done")
                jpg = bytes[a:b 2] 
                print("step 2 done")
                bytes = bytes[b 2:] 
                print("step 3 done")
                getliveimage = cv2.imdecode(np.frombuffer(jpg, dtype=np.uint8), cv2.IMREAD_COLOR)
                print("step 4 done")
                livestreamrotated1 = cv2.rotate(getliveimage, cv2.ROTATE_90_CLOCKWISE)
                cv2.imshow('frame', livestreamrotated1)
        except Exception as e:
            print("this did not work")
        keyPress = cv2.waitKey(1)
    
    def exit_software(self):
       App.get_running_app().stop()
        
if __name__ == '__main__':
    SchweißnahtlehreApp().run()
 

(пожалуйста, не обращайте внимания на весь импорт, они понадобятся мне позже в моей программе, и я не хотел их удалять)

В чем здесь проблема? Я хотел бы добавить в этот момент:

  • Я действительно не знаю, что делают эти строки:
 a = bytes.find(b'xffxd8') 
b = bytes.find(b'xffxd9') 
if a != -1 and b != -1:
 

когда я меняю «-1» на «0», он работает до тех пор, пока «шаг 3 не будет выполнен», а затем принимает исключение.
Поэтому он выходит из строя в строке «cv2.imdecode..».
Код без kivy работает с a/b != -1 И 0.

Код с Kivy и a/b != 0 мгновенно вылетает

  • Интеграция Kivy отлично работает, если я использую USB-камеру вместо IP-камеры: вот почему я не думаю, что это общая проблема «kivy opencv». Если я использую «cv2.VideoCapture(0)» и свою USB-камеру, интеграция работает нормально! Но мне нужен код для потока IP-камеры…

Заранее благодарю вас за любую помощь!!

Комментарии:

1. ваш поток «разбора» — это беспорядок. нет никаких причин, по которым вы должны «находить» какие-либо маркеры в потоке… может быть, один раз, но не несколько раз. функция чтения() в потоке может возвращать меньше байтов, чем ожидалось, потому что это все, что еще поступило. вы абсолютно ОБЯЗАНЫ это проверить и разобраться с этим. даст ли это вам больше или меньше данных, зависит от времени . время , безусловно, зависит от того, потому что вы используете waitKey() И kivy. прочитайте учебник по kivy, чтобы узнать, как отображать изображения с помощью самого kivy . либо используйте imshow waitkey OpenCV, либо используйте kivy, но вы не должны смешивать это.

2. о, и НЕ открывайте поток повторно. это просто расточительно. Я ожидаю, что веб-сервер отправит вам MJPEG или что-то в этом роде multipart/x-mixed-replace . просто не делайте этого сами. используйте API, который считывает данные с сервера и выдает вам кучу картинок.

3. Спасибо вам за ваши ответы! В конце концов, я не буду использовать imshow и waitkey, а интегрирую OpenCV в виде изображения kivy…но сначала мне нужно получить изображение OpenCV с IP-камеры…и в этом проблема на данный момент. Я не могу преобразовать его в изображение kivy, если нет изображения для преобразования…

4. Я совершенно пропустил то, что вы сказали: «Я действительно не знаю, что делают эти строки», вот и вся проблема… ну, на самом деле проблема в том, что вы, кажется, не можете понять, что они делают, и вы просто произвольно меняете их, а затем удивляетесь, почему что-то не работает. Я бы предложил поработать над обоими аспектами.

Ответ №1:

Блог CSDN использует opencv и kivy для показа фотографий.