pythonopencvgrayscaleqtwidgetsvispy

how to add colored lines with opencv after covnersion from grayscale to color (vispy)


I have the following problem. I need to import grayscale images and add some colored lines in the image at distinct positions (prefered colors are red or blue because they are visible) I thought of converting the photo to rgb and then add line. shape before the conversion is a 2d array, after conversion 3d

my problem is:

the point of this script is to show different images according to a frequence. when getting the image we add certain colored lines then we show them. for simplicity here i just send the same image over and over. the grayscale image should stay have the same characterstics visually. the only colored pixels are the added lines.

I keep thinking there is something wrong with the vispy when showing the image. because if we do this with only cv2 we get the right color.

import sys
from PySide2 import QtWidgets, QtCore
from vispy import scene
from PySide2.QtCore import QMetaObject
from PySide2.QtWidgets import *
import numpy as np
import time
import imageio as iio
import cv2

class CameraThread(QtCore.QThread):
    new_image = QtCore.Signal(object)

    def __init__(self, parent=None):
        QtCore.QThread.__init__(self, parent)

    def run(self):
            try:
                while True:
                    frame = iio.imread(my_image)
                    print("shape before conversion: ", frame.data.shape)
                    frame = cv2.cvtColor(frame, cv2.COLOR_GRAY2BGR)
                    print("shape after conversion: ", frame.data.shape)
                    cv2.line(frame, pt1=(100, 300), pt2=(400, 300), color=(255, 0, 0), thickness=10)

                    self.new_image.emit(frame.data)
                    time.sleep(3.0)
            except Exception as e:
                print(f"problem: {e}")
            finally:
                print('end!')


class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        if not MainWindow.objectName():
            MainWindow.setObjectName("MainWindow")
        MainWindow.resize(800, 400)

        self.centralwidget = QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.gridLayout = QGridLayout(self.centralwidget)
        self.gridLayout.setObjectName("gridLayout")

        self.groupBox = QGroupBox(self.centralwidget)
        self.groupBox.setObjectName("groupBox")

        self.gridLayout.addWidget(self.groupBox, 0, 0, 1, 1)

        MainWindow.setCentralWidget(self.centralwidget)

        QMetaObject.connectSlotsByName(MainWindow)



class MainWindow(QtWidgets.QMainWindow):

    def __init__(self):
        super(MainWindow, self).__init__()
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        # OpenGL drawing surface
        self.canvas = scene.SceneCanvas(keys='interactive')
        self.canvas.create_native()
        self.canvas.native.setParent(self)


        self.setWindowTitle('MyApp')


        self.view = self.canvas.central_widget.add_view()

        self.view.bgcolor = '#ffffff'   # set the canvas to a white background

        self.image = scene.visuals.Image(np.zeros((1, 1, 1)),
                                         interpolation='nearest',
                                         parent= self.view.scene,
                                         cmap='grays',
                                         clim=(0, 2 ** 8 - 1))


        self.view.camera = scene.PanZoomCamera(aspect=1)
        self.view.camera.flip = (0, 1, 0)
        self.view.camera.set_range()
        self.view.camera.zoom(1000, (0, 0))

        self._camera_runner = CameraThread(parent=self)
        self._camera_runner.new_image.connect(self.new_image, type=QtCore.Qt.BlockingQueuedConnection)
        self._camera_runner.start()


    @QtCore.Slot(object)
    def new_image(self, img):
        try:
            print("shape when emitting: ", img.shape)
            self.image.set_data(img)
            self.image.update()
        except Exception as e:
            print(f"problem sending image: {e}")

def main():
    import ctypes
    ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID('my_gui')

    app = QtWidgets.QApplication([])

    main_window = MainWindow()
    main_window.show()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()

Solution

  • i found the answer thanks to the vispy forum. for the ones that are interested the whole problem was in the initialization of the image

    one needed to put a correct parameter np.zeros(1, 1, 3)

    if it s false from the very beginning it will never update automatically.