opencv cameras into qml using python and pyside2
-
hey everyone!
im trying to code an application which capture 6 different camera devices
so far i managed too use QThread getting cameras live in action, while tying to use 'addImageProvider' there is an error sayingsys:1: RuntimeWarning: Invalid return value in function QQuickImageProvider.requestImage, expected PySide2.QtGui.QImage, got tuple.
python side code is:
class VideoThread(QThread): changepixmapsignal = Signal(QImage) def __init__(self): super(VideoThread, self).__init__() self._run_flag = True def run(self): while self._run_flag: #imagine this line captures fram the camera in a while loop in_rgb_1=frame_comin_from_camera() #--------- color_frame = in_rgb_1.getFrame() h, w, ch = color_frame.shape img = QImage(color_frame.data, w, h, ch * w, QImage.Format_RGB888) scaled_img = img.scaled(640, 480, Qt.KeepAspectRatio) self.changepixmapsignal.emit(scaled_img) def stop(self): """Sets run flag to False and waits for thread to finish""" self._run_flag = False self.wait() class ImageProvider(QQuickImageProvider): imageChanged = Signal(QImage) def __init__(self): super(ImageProvider, self).__init__(QQuickImageProvider.Image) self.cam = VideoThread() self.cam.start() self.cam.changepixmapsignal.connect(self.update_image) # def requestImage(self,id, size, requestedSize): print("id: ", id) print("requested size: ", requestedSize) img = QImage(300, 300, QImage.Format_RGBA8888) img.fill(Qt.black) img = QImage("qml/pages/image.png") return img, img.size() def update_image(self, img): self.imageChanged.emit(img) class MainWindow(QObject): def __init__(self): QObject.__init__(self) self.timer = QTimer() self.timer.timeout.connect(lambda: self.setTime()) self.timer.start(1000) printTime=Signal(str) def setTime(self): now = datetime.datetime.now() fromatDate=now.strftime('%H:%M:%S %p') self.printTime.emit(fromatDate) def closeEvent(self, event): self.thread.stop() event.accept() if __name__ == "__main__": app = QGuiApplication(sys.argv) engine = QQmlApplicationEngine() main = MainWindow() myImageProvider = ImageProvider() engine.rootContext().setContextProperty("backend", main) engine.rootContext().setContextProperty("myImageProvider", myImageProvider) engine.addImageProvider("MyImageProvider", myImageProvider) engine.load(os.fspath(Path(__file__).resolve().parent / "qml/main.qml")) if not engine.rootObjects(): sys.exit(-1) sys.exit(app.exec_())
and qml side is :
Item { id: fieldProcessingPage Rectangle { id: pageRectangle anchors.fill: parent implicitWidth: 800 implicitHeight: 600 Rectangle { id: contentRectangle anchors.fill: parent Image { id: feedImage anchors.fill: parent fillMode: Image.PreserveAspectFit cache: false source: "image://MyImageProvider/img" property bool counter: false function reloadImage() { counter = !counter source = "image://MyImageProvider/img?id=" + counter } } } } Connections { target: myImageProvider function onImageChanged(image) { feedImage.reloadImage() } } }
-
Hi and welcome to devnet,
Based on the error message, just return
img
in yourrequestImage
function. -
thanks @SGaist error is gone, but when i launch the app it closes by itself, no specific error, it just say python crashed
if i comment the thread section and doesnt load cameras it launches, but when cameras are working ui wont stay long and closes rapidly
-
I must say I am not really convinced by your implementation.
For example, in your requestImage function, you create a QImage, paint it black, and then replace it with another one loaded from a file (which may or may not fail).
Added to that, you are using a thread to generate images that in the end will not go to screen.
On a side note, did you consider using QtMultimedia to grab images from these cameras ?
-
@SGaist i should say i wanted too use multimedia class but couldn't find the method for it, multimedia class captures the images or load a video from hard drive or a Url, but i couldn't connect it too these live action cameras,
also these cameras only works with their own pipeline, they called Depthai , its using Opencv technology, so just calling a webcam camera wont help, also i have 6 cameras to connect to application,
any idea for that? -
How are these camera accessible ?
-
@SGaist only trough opencv, its actually a new tech from opencv, i leave the website below
https://docs.luxonis.com/en/latest/processors kinda pushed inside the camera like a rasbery pie but there is no access to it, for showing the video i can use call back method or showing frame by frame using a while loop
in a thread
but same problem stays, when i use imageprovider qt crashes
is it possible that i can not use more than one stream of images with imageprovider class?
i read the documentation in cpp, it says image provider finds the available stream of images meaning i can not say this stream is camera one for frame number1 and next stream is camera two for frame number 2 ? -
Did you saw that there is a Qt example in their sources ?
You might want to first get that one running before adding QML to the mix.
-
@SGaist i did, it runs smooth with one camera, since its using available picture to stream, problem is when we have more than one camera, i cant choose each stream directly to communicate with in Qt.
lets say i have a class in python that each def() does one job with a camera, one for focusing on for taking a picture one for sending too AI model and so on, i need to make 6 different object from this class for 6 different cameras and connect them to buttons in Qml, what i explained is alright, but the only part i can not do is the live stream for each camera separately, there is no function or at least i couldn't find which define separate stream of images for separate windows in qml, there are two method so far which looks for available stream of image not a specific one, one is imageprovider, other is paintclass
this is were i have the main problem