Пример #1
0
def displayMetaDataSubWindow(self, tableTitle, dataset):
    """
    Creates a subwindow that displays a DICOM image's metadata. 
    """
    try:
        logger.info('ViewMetaData.displayMetaDataSubWindow called.')
        title = "DICOM Image Metadata"
                    
        widget = QWidget()
        widget.setLayout(QVBoxLayout()) 
        metaDataSubWindow = QMdiSubWindow(self)
        metaDataSubWindow.setAttribute(Qt.WA_DeleteOnClose)
        metaDataSubWindow.setWidget(widget)
        metaDataSubWindow.setObjectName("metaData_Window")
        metaDataSubWindow.setWindowTitle(title)
        height, width = self.getMDIAreaDimensions()
        metaDataSubWindow.setGeometry(width * 0.4,0,width*0.6,height)
        lblImageName = QLabel('<H4>' + tableTitle + '</H4>')
        widget.layout().addWidget(lblImageName)

        DICOM_Metadata_Table_View = buildTableView(self, dataset) 
            
        widget.layout().addWidget(DICOM_Metadata_Table_View)

        self.mdiArea.addSubWindow(metaDataSubWindow)
        metaDataSubWindow.show()
    except Exception as e:
        print('Error in : ViewMetaData.displayMetaDataSubWindow' + str(e))
        logger.error('Error in : ViewMetaData.displayMetaDataSubWindow' + str(e))
Пример #2
0
    def setupWindows(self):
        """
        Set up QMdiArea parent and subwindows.
        Add available cameras on local system as items to 
        list widget.
        """
        # Create images directory if it does not already exist
        path = 'images'
        if not os.path.exists(path):
            os.makedirs(path)

        # Set up list widget that will display identified
        # cameras on your computer.
        picture_label = QLabel("Press 'Spacebar' to take pictures.")
        camera_label = QLabel("Available Cameras")
        self.camera_list_widget = QListWidget()
        self.camera_list_widget.setAlternatingRowColors(True)

        # Add availableCameras to a list to be displayed in
        # list widget. Use QCameraInfo() to list available cameras.
        self.cameras = list(QCameraInfo().availableCameras())
        for camera in self.cameras:
            self.list_item = QListWidgetItem()
            self.list_item.setText(camera.deviceName())
            self.camera_list_widget.addItem(self.list_item)

        # Create button that will allow user to select camera
        choose_cam_button = QPushButton("Select Camera")
        choose_cam_button.clicked.connect(self.selectCamera)

        # Create child widgets and layout for camera controls subwindow
        controls_gbox = QGroupBox()
        controls_gbox.setTitle("Camera Controls")

        v_box = QVBoxLayout()
        v_box.addWidget(picture_label, alignment=Qt.AlignCenter)
        v_box.addWidget(camera_label)
        v_box.addWidget(self.camera_list_widget)
        v_box.addWidget(choose_cam_button)

        controls_gbox.setLayout(v_box)

        controls_sub_window = QMdiSubWindow()
        controls_sub_window.setWidget(controls_gbox)
        controls_sub_window.setAttribute(Qt.WA_DeleteOnClose)

        # Create view finder subwindow
        self.view_finder_window = QMdiSubWindow()
        self.view_finder_window.setWindowTitle("Camera View")
        self.view_finder_window.setAttribute(Qt.WA_DeleteOnClose)

        # Create QMdiArea widget to manage subwindows
        mdi_area = QMdiArea()
        mdi_area.tileSubWindows()
        mdi_area.addSubWindow(self.view_finder_window)
        mdi_area.addSubWindow(controls_sub_window)

        # Set mdi_area widget as the central widget of main window
        self.setCentralWidget(mdi_area)
Пример #3
0
 def onFileNew(self):
     newDoc = QMdiSubWindow(self)
     newDoc.setAttribute(Qt.WA_DeleteOnClose)
     newDoc.setWindowTitle('新文档 ' + str(self.newDocIndex))
     self.newDocIndex += 1
     newDoc.setWidget(QPlainTextEdit(newDoc))
     self.mdiArea.addSubWindow(newDoc)
     newDoc.show()
Пример #4
0
 def addWorkspaceMdiWindow(self, widget):
     window = QMdiSubWindow()
     window.setWidget(widget)
     window.setAttribute(Qt.WA_DeleteOnClose)
     window.setWindowIcon(
         QIcon(WorkspaceWidget.window_icons[widget._workspace_widget_type]))
     self.addSubWindow(window)
     window.show()
     widget.show()
Пример #5
0
    def __on_open(self):
        window = QMdiSubWindow()
        window.setAttribute(Qt.WA_DeleteOnClose, True)
        window.setWindowTitle('Sub Window ' + str(MyMainWindow.window_index))
        window.resize(300, 200)
        self.mdi_area.addSubWindow(window)
        window.show()

        MyMainWindow.window_index += 1
Пример #6
0
 def treeItemClicked(self, item, column):
     tab = self.get_treeItem_tab(item.text(column))
     if tab is not None:
         tab.setFocus()
     else:
         if item.text(column) == 'Perfmon':
             self.treeItemWindow_open(item)
         else:
             newDoc = QMdiSubWindow(self)
             newDoc.setAttribute(Qt.WA_DeleteOnClose)
             newDoc.setWindowTitle(item.text(column))
             self.newDocIndex += 1
             newDoc.setWidget(QPlainTextEdit(
                 item.text(column) * 10, newDoc))
             self.mdiArea.addSubWindow(newDoc)
             newDoc.show()
Пример #7
0
    def treeItemWindow_open(self, item):
        title = item.text(0)
        subWind = QMdiSubWindow(self)
        subWind.setAttribute(Qt.WA_DeleteOnClose)
        subWind.setWindowTitle(title)
        self.newDocIndex += 1
        mainWid = QWidget()
        l = QtWidgets.QVBoxLayout(mainWid)
        txtWind = QPlainTextEdit(mainWid)
        txtWind.setPlainText(f"perfmon.x = {item.x}, \n y = {item.y}")
        figWind = MyCanvas(mainWid,
                           width=5,
                           height=4,
                           dpi=100,
                           treeWidgetItem=item)
        l.addWidget(figWind)
        l.addWidget(txtWind)
        l.setStretch(0, 3)  # 设置第一列的伸展比例为 3
        l.setStretch(1, 1)  # 设置第二列的伸展比例为 1, 这样2列的伸展比为3:1

        subWind.setWidget(mainWid)
        self.mdiArea.addSubWindow(subWind)
        subWind.show()
Пример #8
0
class MDIWindow(QMainWindow):
    count = 0

    def __init__(self):
        super().__init__()

        self.data_dict = {}
        self.mdi = QMdiArea()
        self.setCentralWidget(self.mdi)
        #        self.mdi.resize(950,950)

        bar = self.menuBar()

        self.current_dir = None
        self.opened_wd_names = []
        file = bar.addMenu("File")
        file.addAction("New")
        file.addAction("cascade")
        file.addAction("Tiled")
        file.triggered[QAction].connect(self.WindowTrig)

        load = bar.addMenu("Load")
        load.addAction("2D")
        load.addAction("3D")
        load.triggered[QAction].connect(self.dir_open)

        toolbar = QToolBar()
        self.addToolBar(toolbar)

        bw_button_action = QAction('base_wnd', self)
        bw_button_action.setStatusTip('base window button')
        bw_button_action.triggered.connect(self.onclicktb)
        toolbar.addAction(bw_button_action)

        self.setWindowTitle("MDI Application")

        self.base_wd = QMdiSubWindow()
        self.base_wd.setAttribute(Qt.WA_DeleteOnClose, False)
        self.base_wd.resize(400, 400)
        self.base_wd.plt_i = pg.PlotItem(labels={
            'left': ('slits', 'degrees'),
            'bottom': ('Kin. Energy', 'eV')
        })
        self.base_wd.plt_iv = pg.ImageView(view=self.base_wd.plt_i)
        self.base_wd.setWidget(self.base_wd.plt_iv)
        self.base_wd.setWindowTitle("plot window")
        self.mdi.addSubWindow(self.base_wd)
        self.base_wd.show()

        data_DockWidget = QDockWidget('data', self)
        data_DockWidget.setObjectName(('data window'))
        data_DockWidget.setAllowedAreas(Qt.RightDockWidgetArea)

        self.data_list = QListWidget()
        data_DockWidget.setWidget(self.data_list)
        self.addDockWidget(Qt.RightDockWidgetArea, data_DockWidget)

        self.data_list.itemClicked.connect(self.show_data)
        self.data_list.itemDoubleClicked.connect(self.get_data)
        self.mdi.subWindowActivated.connect(self.get_data)

    def WindowTrig(self, p):
        if p.text() == "New":
            MDIWindow.count = MDIWindow.count + 1
            sub = QMdiSubWindow()
            sub.setWidget(QTextEdit())
            sub.setWindowTitle("Sub Window" + str(MDIWindow.count))
            self.mdi.addSubWindow(sub)
            sub.show()

        if p.text() == "cascade":
            self.mdi.cascadeSubWindows()

        if p.text() == "Tiled":
            self.mdi.tileSubWindows()

    def dir_open(self, p):
        self.current_dir = dlg.File_dlg.openDirNameDialog(self)
        print(self.current_dir)
        if p.text() == "2D":
            print('2D')
            files_ls = glob.glob(self.current_dir + '/*.ibw')
            fls = [f[len(self.current_dir) + 1:] for f in files_ls]
            print(files_ls)
            self.data_list.addItems(fls)
        if p.text() == "3D":
            zip_ls = glob.glob(self.current_dir + '/*.zip')
            zp = [f[len(self.current_dir) + 1:] for f in zip_ls]
            print(zp)
            self.data_list.addItems(zp)

    def show_data(self, s):
        print('show data')
        file_name = s.text()
        self.data_dict = ut.ibw2dict(self.current_dir + '/' + file_name)

        e_sc = self.data_dict['E_axis'][1] - self.data_dict['E_axis'][0]
        a_sc = self.data_dict['A_axis'][1] - self.data_dict['A_axis'][0]
        e_str = self.data_dict['E_axis'][0]
        a_str = self.data_dict['A_axis'][0]
        self.base_wd.plt_i.setRange(xRange=[self.data_dict['E_axis'][0], self.data_dict['E_axis'][-1]], \
                            yRange=[self.data_dict['A_axis'][0], self.data_dict['A_axis'][-1]], update=True, padding = 0)

        self.base_wd.plt_i.getViewBox().setLimits(xMin= e_str, xMax = self.data_dict['E_axis'][-1],\
                                          yMin=self.data_dict['A_axis'][0], yMax=self.data_dict['A_axis'][-1])

        self.base_wd.plt_iv.setImage(
            self.data_dict['data'],
            pos=[self.data_dict['E_axis'][0], self.data_dict['A_axis'][0]],
            scale=[e_sc, a_sc])
        #        self.base_wd.plt_iv.ui.histogram.hide()
        self.base_wd.plt_iv.ui.roiBtn.hide()
        self.base_wd.plt_iv.ui.menuBtn.hide()

    def get_data(self, s):
        if isinstance(s, QMdiSubWindow) and str(
                s.objectName()) in self.opened_wd_names:
            sub = self.mdi.currentSubWindow()
            self.data_dict = ut.ibw2dict(self.current_dir + '/' +
                                         str(s.objectName()))
        elif isinstance(s, QListWidgetItem):
            file_name = s.text()
            self.opened_wd_names.append(file_name)
            MDIWindow.count = MDIWindow.count + 1
            sub = QMdiSubWindow()
            sub.resize(550, 550)
            sub.setWindowTitle(file_name)
            sub.setObjectName(file_name)
            self.data_dict = ut.ibw2dict(self.current_dir + '/' + file_name)
        else:
            print(isinstance(s, QMdiSubWindow), isinstance(s, QListWidgetItem))
            print(type(s))
            return
        e_sc = self.data_dict['E_axis'][1] - self.data_dict['E_axis'][0]
        a_sc = self.data_dict['A_axis'][1] - self.data_dict['A_axis'][0]
        e_rg = self.data_dict['E_axis'][-1] - self.data_dict['E_axis'][0]
        a_rg = self.data_dict['A_axis'][-1] - self.data_dict['A_axis'][0]

        e_str = self.data_dict['E_axis'][0]
        a_str = self.data_dict['A_axis'][0]
        e_end = self.data_dict['E_axis'][-1]
        a_end = self.data_dict['A_axis'][-1]
        print(e_str, a_str)
        print(e_end, a_end)
        print(e_rg, a_rg)
        print(e_sc, a_sc)

        gr_v = pg.GraphicsView()
        l = pg.GraphicsLayout()
        gr_v.setCentralWidget(l)
        sub.setWidget(gr_v)
        self.mdi.addSubWindow(sub)
        sub.show()

        p1 = l.addPlot(x=[1, 2],
                       y=[1, 2],
                       name="Plot1",
                       title="EDC",
                       pen="r",
                       row=0,
                       col=0)
        #       label1 = pg.LabelItem(justify='right')
        #        p1.addItem(label1)

        plt_i = pg.PlotItem(labels={
            'left': ('slits', 'degrees'),
            'bottom': ('Kin. Energy', 'eV')
        })
        plt_i.setRange(xRange=[e_str, e_end],
                       yRange=[a_str, a_end],
                       update=True,
                       padding=0)

        vb = plt_i.getViewBox()
        vb.setLimits(xMin=e_str, xMax=e_end, yMin=a_str, yMax=a_end)
        vb.setMouseMode(vb.RectMode)

        l.addItem(plt_i, row=1, col=0)
        img_i = pg.ImageItem(self.data_dict['data'], border=None)
        qrect = vb.viewRect()
        img_i.setRect(qrect)
        vb.addItem(img_i)
        vb.autoRange()
        #        vb.invertX()
        vb.invertY()
        hist = pg.HistogramLUTItem(image=img_i)

        l.addItem(hist, row=0, col=1)

        p2 = l.addPlot(x=[1, 2],
                       y=[2, 1],
                       name="Plot2",
                       title="MDC",
                       pen="g",
                       row=1,
                       col=1)
        #        label2 = pg.LabelItem(justify='left')
        #        plt_i.addItem(label2)

        # cross hair
        vLine = pg.InfiniteLine(angle=90, movable=False)
        hLine = pg.InfiniteLine(angle=0, movable=False)
        p1.addItem(vLine, ignoreBounds=False)
        p1.addItem(hLine, ignoreBounds=False)

        vb1 = p1.vb

        pcv = plt_i.addLine(x=e_end, pen='r')
        pch = plt_i.addLine(y=a_str, pen='r')

        #        lROI = pg.ROI(((e_str+e_end)/2,a_str), size=(5*e_sc,a_rg))
        #        vb.addItem(lROI)
        #        slice, coor = lROI.getArrayRegion(self.data_dict['data'], img_i ,returnMappedCoords = True)

        #        print('slice')
        #        sl_sum=np.sum(slice, axis=0)
        #        print(sl_sum[0:10])
        #        print(type(slice), slice.shape)
        #        print(type(coor), coor.shape)
        #        print(coor[1,0,0:10])
        #        p2.invertY()
        #        p2.setYLink(plt_i)
        #        p2.plot(y=coor[1,0,:], x=sl_sum)

        def onMouseMoved(point):
            p = vb.mapSceneToView(point)
            pcv.setValue(p.x())
            pch.setValue(p.y())
            #            print(p.x(), p.y())

            hROI = pg.ROI((e_str, p.y()), size=(e_rg, 5 * a_sc))
            vb.addItem(hROI)
            hROI.hide()
            sl, co = hROI.getArrayRegion(self.data_dict['data'],
                                         img_i,
                                         returnMappedCoords=True)
            sl_sum = np.sum(sl, axis=1)
            p1.setXLink(plt_i)
            p1.plot(x=co[0, :, 0], y=sl_sum, clear=True)

            vROI = pg.ROI((p.x(), a_str), size=(5 * e_sc, a_rg))
            vb.addItem(vROI)
            vROI.hide()
            slc, coo = vROI.getArrayRegion(self.data_dict['data'],
                                           img_i,
                                           returnMappedCoords=True)
            sl_sum = np.sum(slc, axis=0)
            p2.invertY()
            p2.setYLink(plt_i)
            p2.plot(y=coo[1, 0, :], x=sl_sum, clear=True)


#            label2.setText("{}-{}".format(p.x(), p.y()))

        img_i.scene().sigMouseMoved.connect(onMouseMoved)

    def onclicktb(self):
        self.base_wd.plt_i = pg.PlotItem(labels={
            'left': ('slits', 'degrees'),
            'bottom': ('Kin. Energy', 'eV')
        })
        self.base_wd.plt_iv = pg.ImageView(view=self.base_wd.plt_i)
        self.base_wd.setWidget(self.base_wd.plt_iv)
        self.base_wd.show()
Пример #9
0
class Camera(QMainWindow):
    def __init__(self):
        super().__init__()

        self.initializeUI()

    def initializeUI(self):
        """
        Initialize the window and display its contents to the screen
        """
        self.setGeometry(100, 100, 600, 400)
        self.setWindowTitle('12.2 – Camera GUI')

        self.setupWindows()

        self.show()

    def setupWindows(self):
        """
        Set up QMdiArea parent and subwindows.
        Add available cameras on local system as items to 
        list widget.
        """
        # Create images directory if it does not already exist
        path = 'images'
        if not os.path.exists(path):
            os.makedirs(path)

        # Set up list widget that will display identified
        # cameras on your computer.
        picture_label = QLabel("Press 'Spacebar' to take pictures.")
        camera_label = QLabel("Available Cameras")
        self.camera_list_widget = QListWidget()
        self.camera_list_widget.setAlternatingRowColors(True)

        # Add availableCameras to a list to be displayed in
        # list widget. Use QCameraInfo() to list available cameras.
        self.cameras = list(QCameraInfo().availableCameras())
        for camera in self.cameras:
            self.list_item = QListWidgetItem()
            self.list_item.setText(camera.deviceName())
            self.camera_list_widget.addItem(self.list_item)

        # Create button that will allow user to select camera
        choose_cam_button = QPushButton("Select Camera")
        choose_cam_button.clicked.connect(self.selectCamera)

        # Create child widgets and layout for camera controls subwindow
        controls_gbox = QGroupBox()
        controls_gbox.setTitle("Camera Controls")

        v_box = QVBoxLayout()
        v_box.addWidget(picture_label, alignment=Qt.AlignCenter)
        v_box.addWidget(camera_label)
        v_box.addWidget(self.camera_list_widget)
        v_box.addWidget(choose_cam_button)

        controls_gbox.setLayout(v_box)

        controls_sub_window = QMdiSubWindow()
        controls_sub_window.setWidget(controls_gbox)
        controls_sub_window.setAttribute(Qt.WA_DeleteOnClose)

        # Create view finder subwindow
        self.view_finder_window = QMdiSubWindow()
        self.view_finder_window.setWindowTitle("Camera View")
        self.view_finder_window.setAttribute(Qt.WA_DeleteOnClose)

        # Create QMdiArea widget to manage subwindows
        mdi_area = QMdiArea()
        mdi_area.tileSubWindows()
        mdi_area.addSubWindow(self.view_finder_window)
        mdi_area.addSubWindow(controls_sub_window)

        # Set mdi_area widget as the central widget of main window
        self.setCentralWidget(mdi_area)

    def setupCamera(self, cam_name):
        """
        Create and setup camera functions.
        """
        for camera in self.cameras:
            # Select camera by matching cam_name to one of the
            # devices in the cameras list.
            if camera.deviceName() == cam_name:
                self.cam = QCamera(camera)  # Construct QCamera device

                # Create camera viewfinder widget and add it to the
                # view_finder_window.
                self.view_finder = QCameraViewfinder()
                self.view_finder_window.setWidget(self.view_finder)
                self.view_finder.show()

                # Sets the view finder to display video
                self.cam.setViewfinder(self.view_finder)

                # QCameraImageCapture() is used for taking
                # images or recordings.
                self.image_capture = QCameraImageCapture(self.cam)

                # Configure the camera to capture still images.
                self.cam.setCaptureMode(QCamera.CaptureStillImage)
                self.cam.start()  # Slot to start the camera
            else:
                pass

    def selectCamera(self):
        """
        Slot for selecting one of the available cameras displayed 
        in list widget. 
        """
        try:
            if self.list_item.isSelected():
                camera_name = self.list_item.text()
                self.setupCamera(camera_name)
            else:
                print("No camera selected.")
                pass
        except:
            print("No cameras detected.")

    def keyPressEvent(self, event):
        """
        Handle the key press event so that the camera takes images.
        """
        if event.key() == Qt.Key_Space:
            try:
                self.cam.searchAndLock()
                self.image_capture.capture("images/")
                self.cam.unlock()
            except:
                print("No camera in viewfinder.")
Пример #10
0
class GuiCam(QMainWindow):
    def __init__(self):
        super(GuiCam, self).__init__()

        self.cameras = []
        self.cam_sync = True

        # Create Camera sub_window contents
        self.list_cameras = QListWidget()
        self.list_cameras.setAlternatingRowColors(True)
        self.button_select_camera = QPushButton("Select Camera")

        # Add availableCameras to a list to be displayed in list widget.
        # Use QCameraInfo() to auto detected local camera(s) and list available cameras.
        # cameras = QCameraInfo().availableCameras()
        # self.init_list(self.list_cameras, [cam.deviceName() for cam in list(cameras)])  # + list(videos))

        self.init_list(self.list_cameras, ["Front Camera", "Real Camera"])  # + list(videos))

        # dictionary data structure to construct camera filter functions tuning parameters
        self.functions = {thresholding: [["0: Disable Filter; 1:Active Filter", 1],
                                         ["0:gray; 1:Simple Thresholding; 2:Adaptive Thresholding", 0],
                                         ["Simple Thresholding: 0:BINARY; 1:BINARY_INV; 2:TRUNC; 3:TOZERO; "
                                          "4:TOZERO_INV; 5:THRESH_OTSU", 0],
                                         ["Simple Thresholding: Threshold value", 127],
                                         ["Kernel", 0]],
                          smoothing: [["0: Disable Filter; 1:Active Filter", 1],
                                      ["0:Averaging; 1:Gaussian; 2:Median; 3: Bilateral; 4: De Noise", 0],
                                      ["", 0],
                                      ["", 0],
                                      ["Kernel", 0]],
                          morphology: [["0: Disable Filter; 1:Active Filter", 1],
                                       ["0:Erosion; 1:Dilation; 2:Morphology; ", 0],
                                       ["Morphology Operator 0:Open;1:Close;2:GRADIENT;3:TOPHAT;4:BLACKHAT", 0],
                                       ["morph_element 0:RECT; 1:CROSS; 2:ELLIPSE", 0],
                                       ["Kernel", 0]],
                          histograms: [["0: Disable Filter; 1:Active Filter", 1],
                                       ["0:Equalization; 1:adaptive equalization; 2:Contrast&Brightness; 3:gamma; "
                                        "4:low-light;", 0],
                                       ["alpha-contrast", 50],
                                       ["beta-brightness", 50],
                                       ["", 0]],
                          arithmetic: [["0: Disable Filter; 1:Active Filter", 1],
                                       ["", 0],
                                       ["Scale", 0],
                                       ["alpha-contrast", 50],
                                       ["beta-brightness", 50]],
                          transformations: [["0: Disable Filter; 1:Active Filter", 1],
                                            ["0:Scaling(select rect); 1:Perspective(by select 4 points); "
                                             "2:Affine(by select 3 points);", 0],
                                            ["Scaling factor", 0],
                                            ["", 0],
                                            ["", 0]],
                          extraction: [["0: Disable Filter; 1:Active Filter", 1], ["", 0], ["", 0], ["", 0], ["", 0]],
                          none: [["", 0], ["", 0], ["", 0], ["", 0], ["", 0]], }

        # hold camera filter functions
        # data struct: {function: [["description", value],,,]}
        self.spinbox_tip_value = []
        # Camera AI parts
        self.models = [BarCode,
                       Color,
                       CascadeClassifier,
                       Diff2frame,
                       Diff3frame,
                       Background,
                       Lane,
                       Face,
                       HOGDescriptor,
                       GoodFeature,
                       Tracker,
                       CamShift,
                       Template,
                       ColorShape,
                       Feature,
                       SimpleBlob,
                       Caffe,
                       Tensorflow,
                       Yolo,
                       GrabCut,
                       Model, ]
        self.spin_boxes = []  # hold camera filter function parameters using spinbox value
        self.list_functions = QListWidget()
        self.list_functions.setAlternatingRowColors(True)
        self.button_select_filter = QPushButton("Select filter")
        self.dialog_color = QColorDialog()

        self.camera_contents = QWidget()
        self.dock_camera = QDockWidget()

        self.filter_contents = QWidget()
        self.dock_filter = QDockWidget()

        self.color_contents = QWidget()
        self.dock_color = QDockWidget()

        # Create Model sub_window contents
        # self.models = []  # hold AI models for objects detecting and tracing
        self.list_models = QListWidget()
        self.list_models.setAlternatingRowColors(True)
        self.button_select_model = QPushButton("Select Model")
        self.gbox_model = QGroupBox()

        self.sub_window_models = QMdiSubWindow()
        self.sub_window_models.setAttribute(Qt.WA_DeleteOnClose)
        self.sub_window_models.setWindowTitle("AI Model")

        # Create View sub_window contents
        self.label_image = QLabel()
        self.label_image.setAlignment(Qt.AlignTop)

        self.sub_window_view = QMdiSubWindow()
        self.sub_window_view.setAttribute(Qt.WA_DeleteOnClose)
        self.sub_window_view.setWindowTitle("View")

        # Create Menu Actions
        self.act_file_open = QAction(QIcon('images/open_file.png'), "Open", self)
        self.act_file_close = QAction(QIcon('images/close_file.png'), "Close", self)
        self.act_file_save = QAction(QIcon('images/save_file.png'), "Save", self)
        self.act_file_record = QAction(QIcon('images/record_file.png'), "Record", self)
        self.act_file_print = QAction(QIcon('images/print.png'), "Print", self)
        self.act_file_exit = QAction(QIcon('images/exit.png'), 'Exit', self)

        self.act_edit_image = QAction(QIcon('images/add_image.png'), "Add image", self)
        self.act_edit_logo = QAction(QIcon('images/add_logo.png'), "Add logo", self)

        self.init_ui()

    def init_ui(self):
        """
        Initialize the window and display its contents to the screen
        """
        # defines the location of the window on computer screen and its
        # dimensions, width and height. So the window we just started is located
        # at x=100,; y=100 in the window and has width=1600 and height=800

        self.setGeometry(900, 100, 1600, 800)
        self.setWindowTitle('12.2 – Camera GUI')

        self.init_menu()
        self.init_toolbar()
        self.init_camera()
        self.init_filter()
        self.init_color()
        self.init_model()
        self.init_window()

        self.show()

    @staticmethod
    def init_list(list_widget, list_widget_items):
        list_widget.clear()
        for item_text in list_widget_items:
            item = QListWidgetItem()
            item.setText(str(item_text))
            list_widget.addItem(item)

    def init_menu(self):
        """
        Create menu for CVision GUI
        """
        # Create actions for file menu
        self.act_file_open.setShortcut('Ctrl+O')
        self.act_file_open.setStatusTip('Open a new image/video')
        self.act_file_open.triggered.connect(self.open_file)

        self.act_file_close.setShortcut('Ctrl+E')
        self.act_file_close.setStatusTip('Close an image/video')
        self.act_file_close.triggered.connect(self.close_file)

        self.act_file_save.setShortcut('Ctrl+S')
        self.act_file_save.setStatusTip('Save image')
        self.act_file_save.triggered.connect(self.save_file)

        self.act_file_record.setShortcut('Ctrl+R')
        self.act_file_record.setStatusTip('Record video')
        self.act_file_record.triggered.connect(self.record_file)

        self.act_file_print.setShortcut('Ctrl+P')
        self.act_file_print.setStatusTip('Print image')
        self.act_file_print.triggered.connect(self.print)
        self.act_file_print.setEnabled(False)

        self.act_file_exit.setShortcut('Ctrl+Q')
        self.act_file_exit.setStatusTip('Quit program')
        self.act_file_exit.triggered.connect(self.exit)

        # Create actions for edit menu
        self.act_edit_image.setShortcut('Ctrl+A')
        self.act_edit_image.setStatusTip('Open a blend image')
        self.act_edit_image.triggered.connect(self.add_image)

        self.act_edit_logo.setShortcut('Ctrl+L')
        self.act_edit_logo.setStatusTip('Open a logo image')
        self.act_edit_logo.triggered.connect(self.add_logo)

        # Create menu_bar
        menu_bar = self.menuBar()
        menu_bar.setNativeMenuBar(False)

        # Create file menu and add actions
        file_menu = menu_bar.addMenu('File')
        file_menu.addAction(self.act_file_open)
        file_menu.addAction(self.act_file_close)
        file_menu.addAction(self.act_file_save)
        file_menu.addAction(self.act_file_record)
        file_menu.addSeparator()
        file_menu.addAction(self.act_file_print)
        file_menu.addSeparator()
        file_menu.addAction(self.act_file_exit)

        # Create edit menu and add actions
        edit_menu = menu_bar.addMenu('Edit')
        edit_menu.addAction(self.act_edit_image)
        edit_menu.addAction(self.act_edit_logo)

        # Create view menu and add actions
        view_menu = menu_bar.addMenu('View')
        view_menu.addAction(self.dock_camera.toggleViewAction())
        view_menu.addAction(self.dock_filter.toggleViewAction())
        view_menu.addAction(self.dock_color.toggleViewAction())

        # Display info about shell, menu, and view in the status bar
        self.setStatusBar(QStatusBar(self))

    def init_toolbar(self):
        """
        Create toolbar for CVision GUI
        """
        tool_bar = QToolBar("Photo Editor Toolbar")
        tool_bar.setIconSize(QSize(24, 24))
        self.addToolBar(tool_bar)

        # Add actions to toolbar
        tool_bar.addAction(self.act_file_open)
        tool_bar.addAction(self.act_file_close)
        tool_bar.addAction(self.act_file_save)
        tool_bar.addAction(self.act_file_record)
        tool_bar.addAction(self.act_file_print)

        tool_bar.addSeparator()
        tool_bar.addAction(self.act_edit_image)
        tool_bar.addAction(self.act_edit_logo)

        # tool_bar.addAction(self.clear_act)
        tool_bar.addSeparator()
        tool_bar.addAction(self.act_file_exit)

    def open_file(self):
        """
        Open an image file and display its contents in label widget.
        Display error message if image can't be opened.
        """
        file, _ = QFileDialog.getOpenFileName(self, "Open Image", f"{CWD}//data//Sample//",
                                              "Video Files (*.mp4 *.avi );;"
                                              "JPG Files (*.jpeg *.jpg );;"
                                              "PNG Files (*.png);;"
                                              "Bitmap Files (*.bmp);;"
                                              "GIF Files (*.gif);;"
                                              "All Files (*)")
        if file:
            self.select_camera(file)
        else:
            QMessageBox.information(self, "Error", "Unable to open image.", QMessageBox.Ok)

        self.act_file_print.setEnabled(True)

    def add_image(self):
        """
        Open an image file as back ground blending image.
        Display error message if image can't be opened.
        """
        for cam in self.cameras:
            file, _ = QFileDialog.getOpenFileName(self, "Open Image", f"{CWD}//data//Sample//",
                                                  "JPG Files (*.jpeg *.jpg );;"
                                                  "PNG Files (*.png);;"
                                                  "Bitmap Files (*.bmp);;"
                                                  "GIF Files (*.gif)")
            if file:
                cam.image_background = cv2.imread(file)
                cam.register_filters(rotation, arithmetic)  # add image arithmetic algorithm

                self.spinbox_tip_value = [["0: Disable Filter; 1:Active Filter", 1],
                                          ["", 0],
                                          ["Switch foreground/background image", 0],
                                          ["alpha", 127],
                                          ["beta", 50]]
                self.set_spinbox()
            else:
                QMessageBox.information(self, "Error", "Unable to add image.", QMessageBox.Ok)

        self.button_select_filter.setText(f"Select: Add Image")

    def add_logo(self):
        """
        Open an image file as back ground blending image.
        Display error message if image can't be opened.
        """
        for cam in self.cameras:
            file, _ = QFileDialog.getOpenFileName(self, "Open Logo", f"{CWD}//data//Sample//",
                                                  "JPG Files (*.jpeg *.jpg );;"
                                                  "PNG Files (*.png);;"
                                                  "Bitmap Files (*.bmp);;"
                                                  "GIF Files (*.gif)")
            if file:
                cam.image_logo = cv2.imread(file)  # add logo icon
                cam.register_filters(rotation, arithmetic)  # add image arithmetic algorithm

                self.spinbox_tip_value = [["0: Disable Filter; 1:Active Filter", 1],
                                          ["", 0],
                                          ["0:THRESH_BINARY; 1:THRESH_BINARY_INV", 0],
                                          ["threshold", 230],
                                          ["scale", 255]]
                self.set_spinbox()

            else:
                QMessageBox.information(self, "Error", "Unable to open logo image.", QMessageBox.Ok)

            self.button_select_filter.setText(f"Select: Add Logo")

    def close_file(self):
        self.stop_camera()
        self.cameras.clear()

    def save_file(self):
        for cam in self.cameras:
            cam.save_image(cam.filter_image)

    def record_file(self):
        for cam in self.cameras:
            cam.boolean_record = not cam.boolean_record

    def print(self):
        pass

    def exit(self):
        self.close_file()
        self.close()

    def init_camera(self):
        # Camera Control Dock
        layout_vbox_camera = QVBoxLayout()

        slider_spinbox_direction = SliderSpinBox("Angle", 360, self.update_angle)
        slider_spinbox_direction.setStatusTip("Rotate image")

        label_camera = QLabel("Available Cameras")

        # Create instances of radio buttons
        radio_sync = QRadioButton("Sync")
        radio_sync.setChecked(True)
        radio_sync.setStatusTip("Camera Capture in Main() thread")
        radio_sync.toggled.connect(lambda: self.radio_toggle(radio_sync))
        radio_async = QRadioButton("Async")
        radio_async.setStatusTip("Camera Capture in respective thread")
        radio_async.toggled.connect(lambda: self.radio_toggle(radio_async))

        # Set up layout and add child widgets to the layout
        radio_h_box = QHBoxLayout()
        radio_h_box.addWidget(label_camera)
        radio_h_box.addStretch()  # used to help arrange widgets in a layout manager.
        radio_h_box.addWidget(radio_sync)
        radio_h_box.addWidget(radio_async)

        # Set a specific layout manager inside a parent window or widget
        radio_contents = QWidget()
        radio_contents.setLayout(radio_h_box)

        # Create button that will allow user to select camera
        self.button_select_camera.clicked.connect(self.select_camera)

        layout_vbox_camera.addWidget(radio_contents)
        layout_vbox_camera.addWidget(self.list_cameras)
        layout_vbox_camera.addWidget(slider_spinbox_direction)
        layout_vbox_camera.addWidget(self.button_select_camera)

        # Create child widgets and layout
        self.camera_contents.setLayout(layout_vbox_camera)

    def init_filter(self):
        # Camera Control Dock
        layout_vbox_filter = QVBoxLayout()

        label_filter = QLabel("Available Filters")

        # Set up layout and add child widgets to the layout
        label_h_filter = QLabel("Filter parameters")
        filter_h_box = QHBoxLayout()
        filter_h_box.addWidget(label_h_filter)

        # create 5 instances of QSpinBox class to hold camera filter function parameters
        for i in range(5):
            spinbox = QSpinBox()
            spinbox.setMaximum(255)
            spinbox.valueChanged.connect(self.update_filter_param)
            filter_h_box.addWidget(spinbox)
            self.spin_boxes.append(spinbox)

        # Set a specific layout manager inside a parent window or widget
        filter_contents = QWidget()
        filter_contents.setLayout(filter_h_box)

        # Create button that will allow user to select camera filter
        self.button_select_filter.clicked.connect(self.select_filter)
        self.button_select_filter.setDisabled(True)

        layout_vbox_filter.addWidget(label_filter)
        layout_vbox_filter.addWidget(self.list_functions)
        layout_vbox_filter.addWidget(filter_contents)
        # layout_vbox_camera.addWidget(slider_spinbox_filter)
        layout_vbox_filter.addWidget(self.button_select_filter)

        # Create child widgets and layout
        self.filter_contents.setLayout(layout_vbox_filter)

    def init_color(self):
        # Color Control Dock
        layout_vbox_color = QVBoxLayout()

        slider_spinbox_color = SliderSpinBox("Color %: ", 100, self.update_color_param)
        slider_spinbox_color.setStatusTip("Blend image background color")

        # Create instance of QColorDialog widget and pass the image as an argument to RGBSlider
        self.dialog_color.setOption(QColorDialog.NoButtons)
        self.dialog_color.currentColorChanged.connect(self.update_color)

        layout_vbox_color.addWidget(self.dialog_color)
        layout_vbox_color.addWidget(slider_spinbox_color)

        # Create child widgets and layout
        self.color_contents.setLayout(layout_vbox_color)

    def init_model(self):
        # Set up list widget that will display identified
        # models on your computer.
        label_model = QLabel("Available models")

        # Create button that will allow user to select model
        self.button_select_model.clicked.connect(self.select_models)
        self.button_select_model.setDisabled(True)

        # Create child widgets and layout for model controls sub_window
        layout_vbox_model = QVBoxLayout()
        layout_vbox_model.addWidget(label_model)
        layout_vbox_model.addWidget(self.list_models)
        layout_vbox_model.addWidget(self.button_select_model)

        # Create layout for model controls sub_window
        self.gbox_model.setTitle("Model Controls")
        self.gbox_model.setLayout(layout_vbox_model)

    def init_window(self):
        """
        Set up QMdiArea parent and sub_windows.
        Add available cameras on local system as items to
        list widget.
        """
        # Load image in sub_window_view
        self.load_image("images/chameleon.png")
        self.sub_window_view.setWidget(self.label_image)
        self.sub_window_models.setWidget(self.gbox_model)

        # Create QMdiArea widget to manage sub_windows
        mdi_area = QMdiArea()
        mdi_area.tileSubWindows()

        # mdi_area.addSubWindow(self.sub_window_camera)
        mdi_area.addSubWindow(self.sub_window_models)
        mdi_area.addSubWindow(self.sub_window_view)

        # Set up dock widget
        self.dock_camera.setWindowTitle("Camera Control")
        self.dock_camera.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea)
        self.dock_camera.setWidget(self.camera_contents)

        self.dock_filter.setWindowTitle("Camera Filter")
        self.dock_filter.setWidget(self.filter_contents)

        self.dock_color.setWindowTitle("Camera Color")
        self.dock_color.setWidget(self.color_contents)
        self.dock_color.setVisible(False)

        # Set initial location of dock widget in main window
        self.addDockWidget(Qt.RightDockWidgetArea, self.dock_camera)
        self.addDockWidget(Qt.RightDockWidgetArea, self.dock_filter)
        self.addDockWidget(Qt.RightDockWidgetArea, self.dock_color)

        # Set mdi_area widget as the central widget of main window
        self.setCentralWidget(mdi_area)

    def load_image(self, image):
        try:
            with open(image):
                pixmap = QPixmap(image)
                self.label_image.setPixmap(pixmap)
                self.label_image.move(25, 40)
        except FileNotFoundError:
            print("Image not found.")

    def radio_toggle(self, radio):
        if radio.text() == "Sync" and radio.isChecked():
            self.cam_sync = True
        else:
            self.cam_sync = False

    def select_camera(self, name=None):
        """
        Slot for selecting one of the available cameras displayed in list
        widget.
        """
        def camera(device_name):
            webcam = WebCam(device=device_name, sync=self.cam_sync)
            self.cameras.append(webcam)

            for webcam in self.cameras:
                webcam.register_filters(rotation, arithmetic, none)

                # srv = ('127.0.0.1', 61215, '10000000e7268f60')
                # webcam = WebCam(channel=0, service=srv, device=1, sync=False)
                #
                webcam.gui = self
                webcam.start()
                webcam.start_show()

            self.init_list(self.list_functions, [func.__name__ for func in list(self.functions.keys())])
            self.button_select_filter.setEnabled(True)

            self.init_list(self.list_models, [model.name for model in self.models])
            self.button_select_model.setEnabled(True)
            self.load_image("images/chenliru.jpg")

        try:
            for cam in self.cameras:
                cam.stop_show()  # stop camera show if there is a camera instance already
            self.cameras.clear()

            if self.list_cameras.currentItem() is not None and not name:
                name = self.list_cameras.currentRow()
            camera(name)

        except Exception as e:
            print(f"No cameras detected {e}.")

    def stop_camera(self):
        for cam in self.cameras:
            cam.stop_show()  # stop camera show if there is a camera instance already

    def select_models(self):
        """
        Slot for selecting one of the available AI models displayed in list
        widget.
        """
        position = self.list_models.currentRow()
        ai_model = self.models[position]()
        for cam in self.cameras:
            cam.register_models(ai_model)

        self.button_select_model.setText(f"Select: {ai_model.name}")

    def select_filter(self):
        """
        Slot for selecting one of the available camera filters displayed in list
        widget.
        self.filters = ["log", "gamma", "hist", "yarcb"]
        """
        position = self.list_functions.currentRow()
        funcs = [*self.functions.keys()]  # get keys as list
        func = funcs[position]
        for cam in self.cameras:
            cam.register_filters(rotation, arithmetic, func)

        self.spinbox_tip_value = [*self.functions.values()][position]  # get values as list
        self.set_spinbox()

        self.button_select_filter.setText(f"Select: {func.__name__}")

    def set_spinbox(self):
        tip = np.array(self.spinbox_tip_value)[:, 0]
        value = np.array(self.spinbox_tip_value)[:, 1]
        for i, spinbox in enumerate(self.spin_boxes):
            spinbox.setValue(int(value[i]))
            spinbox.setStatusTip(tip[i])
            spinbox.setDisabled(True) if tip[i] == "" else spinbox.setEnabled(True)

    def update_filter_param(self):
        """
        Slot for selecting one of the available camera filters parameters
        """
        # pass
        for cam in self.cameras:
            for i in range(5):
                cam.filter_param[i] = self.spin_boxes[i].value()

    def update_angle(self, value):
        """
        Slot for selecting one of the available camera installation direction
        """
        for cam in self.cameras:
            cam.angle = value

    def update_color_param(self, value):
        """
        Slot for updating camera color parameter.
        """
        for cam in self.cameras:
            cam.color_param = value

    def update_color(self):
        """
        Slot for selecting one of the available camera color
        """
        for cam in self.cameras:
            rgb = list(self.dialog_color.currentColor().getRgb())
            cam.color = rgb