class Camera(QMainWindow):
    def __init__(self, parent=None):
        super(Camera, self).__init__(parent)

        self.ui = Ui_Camera()

        self.camera = None
        self.imageCapture = None
        # self.mediaRecorder = None
        self.isCapturingImage = False
        self.applicationExiting = False

        self.imageSettings = QImageEncoderSettings()
        self.audioSettings = QAudioEncoderSettings()
        # self.videoSettings = QVideoEncoderSettings()
        # self.videoContainerFormat = ''

        self.ui.setupUi(self)

        cameraDevice = QByteArray()

        videoDevicesGroup = QActionGroup(self)
        videoDevicesGroup.setExclusive(True)

        for deviceName in QCamera.availableDevices():
            description = QCamera.deviceDescription(deviceName)
            videoDeviceAction = QAction(description, videoDevicesGroup)
            videoDeviceAction.setCheckable(True)
            videoDeviceAction.setData(deviceName)

            if cameraDevice.isEmpty():
                cameraDevice = deviceName
                videoDeviceAction.setChecked(True)

            self.ui.menuDevices.addAction(videoDeviceAction)

        videoDevicesGroup.triggered.connect(self.updateCameraDevice)
        self.ui.captureWidget.currentChanged.connect(self.updateCaptureMode)

        #self.ui.lockButton.hide()

        self.setCamera(cameraDevice)

    def setCamera(self, cameraDevice):
        if cameraDevice.isEmpty():
            self.camera = QCamera()
        else:
            self.camera = QCamera(cameraDevice)

        self.camera.stateChanged.connect(self.updateCameraState)
        self.camera.error.connect(self.displayCameraError)

        # self.mediaRecorder = QMediaRecorder(self.camera)
        # self.mediaRecorder.stateChanged.connect(self.updateRecorderState)

        self.imageCapture = QCameraImageCapture(self.camera)

        # self.mediaRecorder.durationChanged.connect(self.updateRecordTime)
        # self.mediaRecorder.error.connect(self.displayRecorderError)

        # self.mediaRecorder.setMetaData(QMediaMetaData.Title, "Test Title")

        # self.ui.exposureCompensation.valueChanged.connect(
        #         self.setExposureCompensation)

        self.camera.setViewfinder(self.ui.viewfinder)

        self.updateCameraState(self.camera.state())
        # self.updateLockStatus(self.camera.lockStatus(), QCamera.UserRequest)
        # self.updateRecorderState(self.mediaRecorder.state())

        self.imageCapture.readyForCaptureChanged.connect(self.readyForCapture)
        self.imageCapture.imageCaptured.connect(self.processCapturedImage)
        self.imageCapture.imageSaved.connect(self.imageSaved)

        # self.camera.lockStatusChanged.connect(self.updateLockStatus)

        self.ui.captureWidget.setTabEnabled(
            0, self.camera.isCaptureModeSupported(QCamera.CaptureStillImage))
        self.ui.captureWidget.setTabEnabled(
            1, self.camera.isCaptureModeSupported(QCamera.CaptureVideo))

        self.updateCaptureMode()
        self.camera.start()

    def keyPressEvent(self, event):
        if event.isAutoRepeat():
            return

        if event.key() == Qt.Key_CameraFocus:
            self.displayViewfinder()
            self.camera.searchAndLock()
            event.accept()
        elif event.key() == Qt.Key_Camera:
            if self.camera.captureMode() == QCamera.CaptureStillImage:
                self.takeImage()
            # elif self.mediaRecorder.state() == QMediaRecorder.RecordingState:
            #     self.stop()
            # else:
            #     self.record()

            event.accept()
        else:
            super(Camera, self).keyPressEvent(event)

    def keyReleaseEvent(self, event):
        if event.isAutoRepeat():
            return

        if event.key() == Qt.Key_CameraFocus:
            self.camera.unlock()
        else:
            super(Camera, self).keyReleaseEvent(event)

    # def updateRecordTime(self):
    #     msg = "Recorded %d sec" % (self.mediaRecorder.duration() // 1000)
    #     self.ui.statusbar.showMessage(msg)

    def processCapturedImage(self, requestId, img):
        scaledImage = img.scaled(self.ui.viewfinder.size(), Qt.KeepAspectRatio,
                                 Qt.SmoothTransformation)

        self.ui.lastImagePreviewLabel.setPixmap(QPixmap.fromImage(scaledImage))

        self.displayCapturedImage()
        QTimer.singleShot(4000, self.displayViewfinder)

    def configureCaptureSettings(self):
        if self.camera.captureMode() == QCamera.CaptureStillImage:
            self.configureImageSettings()
        elif self.camera.captureMode() == QCamera.CaptureVideo:
            self.configureVideoSettings()

    # def configureVideoSettings(self):
    #     settingsDialog = VideoSettings(self.mediaRecorder)

    #     settingsDialog.setAudioSettings(self.audioSettings)
    #     settingsDialog.setVideoSettings(self.videoSettings)
    #     settingsDialog.setFormat(self.videoContainerFormat)

    #     if settingsDialog.exec_():
    #         self.audioSettings = settingsDialog.audioSettings()
    #         self.videoSettings = settingsDialog.videoSettings()
    #         self.videoContainerFormat = settingsDialog.format()

    #         self.mediaRecorder.setEncodingSettings(self.audioSettings,
    #                 self.videoSettings, self.videoContainerFormat)
    def configureOpenExcels(self):
        settingsopenexcelDialog = OpenExcels()
        settingsopenexcelDialog.initUI()

    def configureImageSettings(self):
        settingsDialog = ImageSettings(self.imageCapture)

        settingsDialog.setImageSettings(self.imageSettings)

        if settingsDialog.exec_():
            self.imageSettings = settingsDialog.imageSettings()
            self.imageCapture.setEncodingSettings(self.imageSettings)

    # def record(self):
    #     self.mediaRecorder.record()
    #     self.updateRecordTime()

    # def pause(self):
    #     self.mediaRecorder.pause()

    # def stop(self):
    #     self.mediaRecorder.stop()

    # def setMuted(self, muted):
    #     self.mediaRecorder.setMuted(muted)

    def toggleLock(self):
        if self.camera.lockStatus() in (QCamera.Searching, QCamera.Locked):
            self.camera.unlock()
        elif self.camera.lockStatus() == QCamera.Unlocked:
            self.camera.searchAndLock()

    # def updateLockStatus(self, status, reason):
    #     indicationColor = Qt.black

    #     if status == QCamera.Searching:
    #         self.ui.statusbar.showMessage("Focusing...")
    #         self.ui.lockButton.setText("Focusing...")
    #         indicationColor = Qt.yellow
    #     elif status == QCamera.Locked:
    #         self.ui.lockButton.setText("Unlock")
    #         self.ui.statusbar.showMessage("Focused", 2000)
    #         indicationColor = Qt.darkGreen
    #     # elif status == QCamera.Unlocked:
    #     #     self.ui.lockButton.setText("Focus")

    #         if reason == QCamera.LockFailed:
    #             self.ui.statusbar.showMessage("Focus Failed", 2000)
    #             indicationColor = Qt.red

    #     palette = self.ui.lockButton.palette()
    #     palette.setColor(QPalette.ButtonText, indicationColor)
    #     self.ui.lockButton.setPalette(palette)
    def display_absences(self, absences):
        self.ui.absenceNumber.display(absences)

    def takeImage(self):
        self.isCapturingImage = True
        self.imageCapture.capture()

    def startCamera(self):
        self.camera.start()

    def stopCamera(self):
        self.camera.stop()

    def updateCaptureMode(self):
        tabIndex = self.ui.captureWidget.currentIndex()
        captureMode = QCamera.CaptureStillImage if tabIndex == 0 else QCamera.CaptureVideo

        if self.camera.isCaptureModeSupported(captureMode):
            self.camera.setCaptureMode(captureMode)

    def updateCameraState(self, state):
        if state == QCamera.ActiveState:
            self.ui.actionStartCamera.setEnabled(False)
            self.ui.actionStopCamera.setEnabled(True)
            self.ui.captureWidget.setEnabled(True)
            self.ui.actionSettings.setEnabled(True)
        elif state in (QCamera.UnloadedState, QCamera.LoadedState):
            self.ui.actionStartCamera.setEnabled(True)
            self.ui.actionStopCamera.setEnabled(False)
            self.ui.captureWidget.setEnabled(False)
            self.ui.actionSettings.setEnabled(False)

    # def updateRecorderState(self, state):
    #     if state == QMediaRecorder.StoppedState:
    #         # self.ui.recordButton.setEnabled(True)
    #         self.ui.pauseButton.setEnabled(True)
    #         self.ui.stopButton.setEnabled(False)
    #     elif state == QMediaRecorder.PausedState:
    #         self.ui.recordButton.setEnabled(True)
    #         self.ui.pauseButton.setEnabled(False)
    #         self.ui.stopButton.setEnabled(True)
    #     elif state == QMediaRecorder.RecordingState:
    #         self.ui.recordButton.setEnabled(False)
    #         self.ui.pauseButton.setEnabled(True)
    #         self.ui.stopButton.setEnabled(True)

    def setExposureCompensation(self, index):
        self.camera.exposure().setExposureCompensation(index * 0.5)

    # def displayRecorderError(self):
    #     QMessageBox.warning(self, "Capture error",
    #             self.mediaRecorder.errorString())

    def displayCameraError(self):
        QMessageBox.warning(self, "Camera error", self.camera.errorString())

    def updateCameraDevice(self, action):
        self.setCamera(action.data())

    def displayViewfinder(self):
        self.ui.stackedWidget.setCurrentIndex(0)

    def displayCapturedImage(self):
        self.ui.stackedWidget.setCurrentIndex(1)

    def readyForCapture(self, ready):
        self.ui.takeImageButton.setEnabled(ready)

    def imageSaved(self, id, fileName):
        self.isCapturingImage = False

        if self.applicationExiting:
            self.close()

    def closeEvent(self, event):
        if self.isCapturingImage:
            self.setEnabled(False)
            self.applicationExiting = True
            event.ignore()
        else:
            event.accept()
Пример #2
0
class Camera(QMainWindow):

    def __init__(self, parent=None):
        super(Camera, self).__init__(parent)

        self.ui = Ui_Camera()
        self.camera = None
        self.imageCapture = None
        self.mediaRecorder = None
        self.isCapturingImage = False
        self.applicationExiting = False

        self.imageSettings = QImageEncoderSettings()
        self.audioSettings = QAudioEncoderSettings()
        self.videoSettings = QVideoEncoderSettings()
        self.videoContainerFormat = ''

        self.ui.setupUi(self)

        cameraDevice = QByteArray()

        videoDevicesGroup = QActionGroup(self)
        videoDevicesGroup.setExclusive(True)

        for deviceName in QCamera.availableDevices():
            description = QCamera.deviceDescription(deviceName)
            videoDeviceAction = QAction(description, videoDevicesGroup)
            videoDeviceAction.setCheckable(True)
            videoDeviceAction.setData(deviceName)

            if cameraDevice.isEmpty():
                cameraDevice = deviceName
                videoDeviceAction.setChecked(True)

            self.ui.menuDevices.addAction(videoDeviceAction)

        videoDevicesGroup.triggered.connect(self.updateCameraDevice)
        self.ui.captureWidget.currentChanged.connect(self.updateCaptureMode)

        self.ui.lockButton.hide()

        self.setCamera(cameraDevice)

    def setCamera(self, cameraDevice):
        if cameraDevice.isEmpty():
            self.camera = QCamera()
        else:
            self.camera = QCamera(cameraDevice)

        self.camera.stateChanged.connect(self.updateCameraState)
        self.camera.error.connect(self.displayCameraError)

        self.mediaRecorder = QMediaRecorder(self.camera)
        self.mediaRecorder.stateChanged.connect(self.updateRecorderState)

        self.imageCapture = QCameraImageCapture(self.camera)

        self.mediaRecorder.durationChanged.connect(self.updateRecordTime)
        self.mediaRecorder.error.connect(self.displayRecorderError)

        self.mediaRecorder.setMetaData(QMediaMetaData.Title, "Test Title")

        self.ui.exposureCompensation.valueChanged.connect(
                self.setExposureCompensation)

        self.camera.setViewfinder(self.ui.viewfinder)

        self.updateCameraState(self.camera.state())
        self.updateLockStatus(self.camera.lockStatus(), QCamera.UserRequest)
        self.updateRecorderState(self.mediaRecorder.state())

        self.imageCapture.readyForCaptureChanged.connect(self.readyForCapture)
        self.imageCapture.imageCaptured.connect(self.processCapturedImage)
        self.imageCapture.imageSaved.connect(self.imageSaved)

        self.camera.lockStatusChanged.connect(self.updateLockStatus)

        self.ui.captureWidget.setTabEnabled(0,
                self.camera.isCaptureModeSupported(QCamera.CaptureStillImage))
        self.ui.captureWidget.setTabEnabled(1,
                self.camera.isCaptureModeSupported(QCamera.CaptureVideo))

        self.updateCaptureMode()
        self.camera.start()

    def keyPressEvent(self, event):
        if event.isAutoRepeat():
            return

        if event.key() == Qt.Key_CameraFocus:
            self.displayViewfinder()
            self.camera.searchAndLock()
            event.accept()
        elif event.key() == Qt.Key_Camera:
            if self.camera.captureMode() == QCamera.CaptureStillImage:
                self.takeImage()
            elif self.mediaRecorder.state() == QMediaRecorder.RecordingState:
                self.stop()
            else:
                self.record()

            event.accept()
        else:
            super(Camera, self).keyPressEvent(event)

    def keyReleaseEvent(self, event):
        if event.isAutoRepeat():
            return

        if event.key() == Qt.Key_CameraFocus:
            self.camera.unlock()
        else:
            super(Camera, self).keyReleaseEvent(event)

    def updateRecordTime(self):
        msg = "Recorded %d sec" % self.mediaRecorder.duration() // 1000
        self.ui.statusbar.showMessage(msg)

    def processCapturedImage(self, requestId, img):
        scaledImage = img.scaled(self.ui.viewfinder.size(), Qt.KeepAspectRatio,
                Qt.SmoothTransformation)

        self.ui.lastImagePreviewLabel.setPixmap(QPixmap.fromImage(scaledImage))

        self.displayCapturedImage()
        QTimer.singleShot(4000, self.displayViewfinder)

    def configureCaptureSettings(self):
        if self.camera.captureMode() == QCamera.CaptureStillImage:
            self.configureImageSettings()
        elif self.camera.captureMode() == QCamera.CaptureVideo:
            self.configureVideoSettings()

    def configureVideoSettings(self):
        settingsDialog = VideoSettings(self.mediaRecorder)

        settingsDialog.setAudioSettings(self.audioSettings)
        settingsDialog.setVideoSettings(self.videoSettings)
        settingsDialog.setFormat(self.videoContainerFormat)

        if settingsDialog.exec_():
            self.audioSettings = settingsDialog.audioSettings()
            self.videoSettings = settingsDialog.videoSettings()
            self.videoContainerFormat = settingsDialog.format()

            self.mediaRecorder.setEncodingSettings(self.audioSettings,
                    self.videoSettings, self.videoContainerFormat)

    def configureImageSettings(self):
        settingsDialog = ImageSettings(self.imageCapture)

        settingsDialog.setImageSettings(self.imageSettings)

        if settingsDialog.exec_():
            self.imageSettings = settingsDialog.imageSettings()
            imageCapture.setEncodingSettings(self.imageSettings)

    def record(self):
        self.mediaRecorder.record()
        self.updateRecordTime()

    def pause(self):
        self.mediaRecorder.pause()

    def stop(self):
        self.mediaRecorder.stop()

    def setMuted(self, muted):
        self.mediaRecorder.setMuted(muted)

    def toggleLock(self):
        if self.camera.lockStatus() in (QCamera.Searching, QCamera.Locked):
            self.camera.unlock()
        elif self.camera.lockStatus() == QCamera.Unlocked:
            self.camera.searchAndLock()

    def updateLockStatus(self, status, reason):
        indicationColor = Qt.black

        if status == QCamera.Searching:
            self.ui.statusbar.showMessage("Focusing...")
            self.ui.lockButton.setText("Focusing...")
            indicationColor = Qt.yellow
        elif status == QCamera.Locked:
            self.ui.lockButton.setText("Unlock")
            self.ui.statusbar.showMessage("Focused", 2000)
            indicationColor = Qt.darkGreen
        elif status == QCamera.Unlocked:
            self.ui.lockButton.setText("Focus")

            if reason == QCamera.LockFailed:
                self.ui.statusbar.showMessage("Focus Failed", 2000)
                indicationColor = Qt.red

        palette = self.ui.lockButton.palette()
        palette.setColor(QPalette.ButtonText, indicationColor)
        self.ui.lockButton.setPalette(palette)

    def takeImage(self):
        self.isCapturingImage = True
        self.imageCapture.capture()

    def startCamera(self):
        self.camera.start()

    def stopCamera(self):
        self.camera.stop()

    def updateCaptureMode(self):
        tabIndex = self.ui.captureWidget.currentIndex()
        captureMode = QCamera.CaptureStillImage if tabIndex == 0 else QCamera.CaptureVideo

        if self.camera.isCaptureModeSupported(captureMode):
            self.camera.setCaptureMode(captureMode)

    def updateCameraState(self, state):
        if state == QCamera.ActiveState:
            self.ui.actionStartCamera.setEnabled(False)
            self.ui.actionStopCamera.setEnabled(True)
            self.ui.captureWidget.setEnabled(True)
            self.ui.actionSettings.setEnabled(True)
        elif state in (QCamera.UnloadedState, QCamera.LoadedState):
            self.ui.actionStartCamera.setEnabled(True)
            self.ui.actionStopCamera.setEnabled(False)
            self.ui.captureWidget.setEnabled(False)
            self.ui.actionSettings.setEnabled(False)

    def updateRecorderState(self, state):
        if state == QMediaRecorder.StoppedState:
            self.ui.recordButton.setEnabled(True)
            self.ui.pauseButton.setEnabled(True)
            self.ui.stopButton.setEnabled(False)
        elif state == QMediaRecorder.PausedState:
            self.ui.recordButton.setEnabled(True)
            self.ui.pauseButton.setEnabled(False)
            self.ui.stopButton.setEnabled(True)
        elif state == QMediaRecorder.RecordingState:
            self.ui.recordButton.setEnabled(False)
            self.ui.pauseButton.setEnabled(True)
            self.ui.stopButton.setEnabled(True)

    def setExposureCompensation(self, index):
        self.camera.exposure().setExposureCompensation(index * 0.5)

    def displayRecorderError(self):
        QMessageBox.warning(self, "Capture error",
                self.mediaRecorder.errorString())

    def displayCameraError(self):
        QMessageBox.warning(self, "Camera error", self.camera.errorString())

    def updateCameraDevice(self, action):
        self.setCamera(action.data())

    def displayViewfinder(self):
        self.ui.stackedWidget.setCurrentIndex(0)

    def displayCapturedImage(self):
        self.ui.stackedWidget.setCurrentIndex(1)

    def readyForCapture(self, ready):
        self.ui.takeImageButton.setEnabled(ready)

    def imageSaved(self, id, fileName):
        self.isCapturingImage = False

        if self.applicationExiting:
            self.close()

    def closeEvent(self, event):
        if self.isCapturingImage:
            self.setEnabled(False)
            self.applicationExiting = True
            event.ignore()
        else:
            event.accept()
Пример #3
0
class CQCameraPreviewWindow(QtWidgets.QMainWindow):
    closeSignal = QtCore.pyqtSignal()
    ioctlRequest = QtCore.pyqtSignal(dict)

    def __init__(self, *args, **kwargs):
        super(CQCameraPreviewWindow, self).__init__(*args, **kwargs)

        self._MIN_WIN_WIDTH = 640
        self.oc_camera_info = None
        self.oc_camera = None
        self.b_guard = False
        self.toolbar = QtWidgets.QToolBar("Preview")

        self.cbox_resolution = CLabeledComboBox("Resolution:")
        self.cbox_resolution.cbox.currentIndexChanged.connect(self.__cb_on_resolution_cbox_index_changed)
        self.toolbar.addWidget(self.cbox_resolution)
        self.toolbar.addSeparator()

        self.cbox_frame_rate = CLabeledComboBox("Frame Rate:")
        self.cbox_frame_rate.cbox.currentIndexChanged.connect(self.__cb_on_frame_rate_cbox_index_changed)
        self.toolbar.addWidget(self.cbox_frame_rate)
        self.addToolBar(self.toolbar)
        self.toolbar.addSeparator()

        self.oc_view_finder = QCameraViewfinder()
        self.setCentralWidget(self.oc_view_finder)

    def __cb_on_resolution_cbox_index_changed(self, i_idx):
        if self.oc_camera is None:
            self.fatal_error("Unallocated camera object detected")
        if self.b_guard: return
        l_res = self.cbox_resolution.cbox.itemText(i_idx).split(" x ")
        oc_vf_settings = self.oc_camera.viewfinderSettings()
        if oc_vf_settings.isNull():
            self.fatal_error("Unable to retrieve camera settings")
        i_w, i_h = int(l_res[0]), int(l_res[1])
        oc_vf_settings.setResolution(i_w, i_h)
        self.oc_camera.setViewfinderSettings(oc_vf_settings)
        self.oc_view_finder.setFixedSize(i_w, i_h)
        if i_w >= self._MIN_WIN_WIDTH:
            self.adjustSize()
            self.setFixedSize(self.sizeHint())

    def __cb_on_frame_rate_cbox_index_changed(self, i_idx):
        if self.oc_camera is None:
            self.fatal_error("Unallocated camera object detected")
        if self.b_guard: return
        f_res = float(self.cbox_frame_rate.cbox.itemText(i_idx))
        oc_vf_settings = self.oc_camera.viewfinderSettings()
        if oc_vf_settings.isNull():
            self.fatal_error("Unable to retrieve camera settings")
        oc_vf_settings.setMinimumFrameRate(f_res)
        oc_vf_settings.setMaximumFrameRate(f_res)
        self.oc_camera.setViewfinderSettings(oc_vf_settings)

    def __camera_sync_start(self):
        i_sec_cnt = 0
        self.oc_camera.start()
        while True:
            cam_status = self.oc_camera.status()
            if cam_status == QCamera.ActiveStatus: break
            else:
                time.sleep(1)
                i_sec_cnt += 1
                if i_sec_cnt >= 10: self.fatal_error("Unable to start the camera")

    def __update_UI(self):
        # retrieve all supported resolutions and populate the resolution combo box
        l_resolutions = self.oc_camera.supportedViewfinderResolutions()
        if len(l_resolutions) > 0:
            l_res = []
            for oc_res in l_resolutions:
                l_res.append("%i x %i" % (oc_res.width(), oc_res.height()))
            self.cbox_resolution.cbox.clear()
            self.cbox_resolution.cbox.addItems(l_res)

        oc_vf_settings = self.oc_camera.viewfinderSettings()
        if oc_vf_settings.isNull():
            self.fatal_error("Unable to retrieve camera settings")

        # set current item index in the resolution combo box
        # according to the current resolution of our camera
        oc_curr_res = oc_vf_settings.resolution()
        s_res_hash = "%i x %i" % (oc_curr_res.width(), oc_curr_res.height())
        for i_idx in range(self.cbox_resolution.cbox.count()):
            if self.cbox_resolution.cbox.itemText(i_idx) == s_res_hash:
                self.cbox_resolution.cbox.setCurrentIndex(i_idx)

        # retrieve all supported frame rates and populate the frame rate combo box
        l_frates = self.oc_camera.supportedViewfinderFrameRateRanges()
        if len(l_frates) > 0:
            l_res = []
            for oc_frate in l_frates:
                l_res.append("%f" % oc_frate.minimumFrameRate)
            self.cbox_frame_rate.cbox.clear()
            self.cbox_frame_rate.cbox.addItems(l_res)

        # set current item index in the frame rate combo box
        # according to the current frame rate of our camera
        i_curr_frate = int(oc_vf_settings.minimumFrameRate())
        for i_idx in range(self.cbox_frame_rate.cbox.count()):
            if int(float(self.cbox_frame_rate.cbox.itemText(i_idx))) == i_curr_frate:
                self.cbox_frame_rate.cbox.setCurrentIndex(i_idx)

    def fatal_error(self, s_msg):
        if self.oc_camera is not None: self.oc_camera.stop()
        QtWidgets.QMessageBox.critical(None, "Fatal Error", "%s\nThe application will exit now." % s_msg)
        sys.exit(-1)

    def start_preview(self, oc_camera_info, oc_frame_cap_thread):
        if self.oc_camera is not None:
            self.fatal_error("Preallocated camera object detected")

        self.oc_camera_info = oc_camera_info
        self.oc_camera = QCamera(self.oc_camera_info)

        self.oc_camera.setViewfinder(self.oc_view_finder)
        self.oc_camera.setCaptureMode(QCamera.CaptureVideo)
        self.oc_camera.error.connect(lambda: self.show_error_message(self.oc_camera.errorString()))

        self.b_guard = True
        self.__camera_sync_start()
        self.__update_UI()
        self.b_guard = False

        self.setWindowTitle(self.oc_camera_info.description())
        self.adjustSize()
        self.setFixedSize(self.sizeHint())

    def stop_preview(self):
        if self.oc_camera is None:
            return # this is correct logic, no error here
        self.oc_camera.stop()
        self.oc_camera.unload()
        self.oc_camera = None
        self.oc_camera_info = None

    def is_save_state_needed(self):
        return False

    def save_state(self):
        pass

    def show_error_message(self, s_msg):
        err = QtWidgets.QErrorMessage(self)
        err.showMessage(s_msg)

    def closeEvent(self, event):
        if self.is_save_state_needed():
            self.save_state()
        self.stop_preview()
        self.closeSignal.emit()
Пример #4
0
class Camera(QMainWindow):
    def __init__(self, parent=None):
        super(Camera, self).__init__(parent)

        self.ui = Ui_Camera()
        self.camera = None
        self.imageCapture = None
        self.mediaRecorder = None
        self.isCapturingImage = False
        self.applicationExiting = False

        self.imageSettings = QImageEncoderSettings()
        self.audioSettings = QAudioEncoderSettings()
        self.videoSettings = QVideoEncoderSettings()
        self.videoContainerFormat = ''

        self.ui.setupUi(self)

        cameraDevice = QByteArray()

        videoDevicesGroup = QActionGroup(self)
        videoDevicesGroup.setExclusive(True)

        for deviceName in QCamera.availableDevices():
            description = QCamera.deviceDescription(deviceName)
            videoDeviceAction = QAction(description, videoDevicesGroup)
            videoDeviceAction.setCheckable(True)
            videoDeviceAction.setData(deviceName)

            if cameraDevice.isEmpty():
                cameraDevice = deviceName
                videoDeviceAction.setChecked(True)

            self.ui.menuDevices.addAction(videoDeviceAction)

        videoDevicesGroup.triggered.connect(self.updateCameraDevice)
        self.ui.captureWidget.currentChanged.connect(self.updateCaptureMode)

        self.ui.lockButton.hide()

        self.setCamera(cameraDevice)

    def setCamera(self, cameraDevice):
        if cameraDevice.isEmpty():
            self.camera = QCamera()
        else:
            self.camera = QCamera(cameraDevice)

        self.camera.stateChanged.connect(self.updateCameraState)
        self.camera.error.connect(self.displayCameraError)

        self.mediaRecorder = QMediaRecorder(self.camera)
        self.mediaRecorder.stateChanged.connect(self.updateRecorderState)

        self.imageCapture = QCameraImageCapture(self.camera)

        self.mediaRecorder.durationChanged.connect(self.updateRecordTime)
        self.mediaRecorder.error.connect(self.displayRecorderError)

        self.mediaRecorder.setMetaData(QMediaMetaData.Title, "Test Title")

        self.ui.exposureCompensation.valueChanged.connect(
            self.setExposureCompensation)

        self.camera.setViewfinder(self.ui.viewfinder)

        self.updateCameraState(self.camera.state())
        self.updateLockStatus(self.camera.lockStatus(), QCamera.UserRequest)
        self.updateRecorderState(self.mediaRecorder.state())

        self.imageCapture.readyForCaptureChanged.connect(self.readyForCapture)
        self.imageCapture.imageCaptured.connect(self.processCapturedImage)
        self.imageCapture.imageSaved.connect(self.imageSaved)

        self.camera.lockStatusChanged.connect(self.updateLockStatus)

        self.ui.captureWidget.setTabEnabled(
            0, self.camera.isCaptureModeSupported(QCamera.CaptureStillImage))
        self.ui.captureWidget.setTabEnabled(
            1, self.camera.isCaptureModeSupported(QCamera.CaptureVideo))

        self.updateCaptureMode()
        self.camera.start()

    def keyPressEvent(self, event):
        if event.isAutoRepeat():
            return

        if event.key() == Qt.Key_CameraFocus:
            self.displayViewfinder()
            self.camera.searchAndLock()
            event.accept()
        elif event.key() == Qt.Key_Camera:
            if self.camera.captureMode() == QCamera.CaptureStillImage:
                self.takeImage()
            elif self.mediaRecorder.state() == QMediaRecorder.RecordingState:
                self.stop()
            else:
                self.record()

            event.accept()
        else:
            super(Camera, self).keyPressEvent(event)

    def keyReleaseEvent(self, event):
        if event.isAutoRepeat():
            return

        if event.key() == Qt.Key_CameraFocus:
            self.camera.unlock()
        else:
            super(Camera, self).keyReleaseEvent(event)

    def updateRecordTime(self):
        msg = "Recorded %d sec" % (self.mediaRecorder.duration() // 1000)
        self.ui.statusbar.showMessage(msg)

###############################################################################

    def detectChars(self, qImg):
        incomingImage = qImg.convertToFormat(4)

        width = incomingImage.width()
        height = incomingImage.height()

        ptr = incomingImage.bits()
        ptr.setsize(incomingImage.byteCount())
        cvImg = np.array(ptr).reshape(height, width, 4)  # Copies the data
        ######################
        centerx = int(cvImg.shape[1] / 2)
        centery = int(cvImg.shape[0] / 2)
        half_width = 200
        half_height = 100
        y = centery - half_height
        x = centerx - half_width
        print(type(cvImg))
        cvImgCroped = cvImg[y:y + half_height * 2, x:x + half_width *
                            2]  # Crop from x, y, w, h -> 100, 200, 300, 400
        cvImgCContinues = np.zeros(cvImgCroped.shape, np.uint8)
        cvImgCContinues = cvImgCroped.copy()
        # NOTE: its img[y: y + h, x: x + w] and *not* img[x: x + w, y: y + h]
        # cvImgCroped = cv2.rectangle(cvImgCroped,
        #               (centerx - half_width, centery - half_height),
        #               (centerx + half_width, centery + half_height),
        #               (0, 0, 255),
        #               2)

        ######################

        # Convert to RGB for QImage.
        cvImgCContinues = cv2.cvtColor(cvImgCContinues, cv2.COLOR_BGR2RGB)
        # cv2.imshow("",cvImgCContinues)
        # cv2.waitKey(0)
        height, width, bytesPerComponent = cvImgCContinues.shape
        bytesPerLine = bytesPerComponent * width
        self.image = QImage(cvImgCContinues.data, width, height, bytesPerLine,
                            QImage.Format_RGB888)
        return self.image

###############################################################################

    def processCapturedImage(self, requestId, img):
        detectedImage = self.detectChars(img)
        scaledImage = detectedImage.scaled(self.ui.viewfinder.size(),
                                           Qt.KeepAspectRatio,
                                           Qt.SmoothTransformation)
        self.ui.lastImagePreviewLabel.setPixmap(QPixmap.fromImage(scaledImage))

        self.displayCapturedImage()
        QTimer.singleShot(40000, self.displayViewfinder)


###############################################################################

    def configureCaptureSettings(self):
        if self.camera.captureMode() == QCamera.CaptureStillImage:
            self.configureImageSettings()
        elif self.camera.captureMode() == QCamera.CaptureVideo:
            self.configureVideoSettings()

    def configureVideoSettings(self):
        settingsDialog = VideoSettings(self.mediaRecorder)

        settingsDialog.setAudioSettings(self.audioSettings)
        settingsDialog.setVideoSettings(self.videoSettings)
        settingsDialog.setFormat(self.videoContainerFormat)

        if settingsDialog.exec_():
            self.audioSettings = settingsDialog.audioSettings()
            self.videoSettings = settingsDialog.videoSettings()
            self.videoContainerFormat = settingsDialog.format()

            self.mediaRecorder.setEncodingSettings(self.audioSettings,
                                                   self.videoSettings,
                                                   self.videoContainerFormat)

    def configureImageSettings(self):
        settingsDialog = ImageSettings(self.imageCapture)

        settingsDialog.setImageSettings(self.imageSettings)

        if settingsDialog.exec_():
            self.imageSettings = settingsDialog.imageSettings()
            self.imageCapture.setEncodingSettings(self.imageSettings)

    def record(self):
        self.mediaRecorder.record()
        self.updateRecordTime()

    def pause(self):
        self.mediaRecorder.pause()

    def stop(self):
        self.mediaRecorder.stop()

    def setMuted(self, muted):
        self.mediaRecorder.setMuted(muted)

    def toggleLock(self):
        if self.camera.lockStatus() in (QCamera.Searching, QCamera.Locked):
            self.camera.unlock()
        elif self.camera.lockStatus() == QCamera.Unlocked:
            self.camera.searchAndLock()

    def updateLockStatus(self, status, reason):
        indicationColor = Qt.black

        if status == QCamera.Searching:
            self.ui.statusbar.showMessage("Focusing...")
            self.ui.lockButton.setText("Focusing...")
            indicationColor = Qt.yellow
        elif status == QCamera.Locked:
            self.ui.lockButton.setText("Unlock")
            self.ui.statusbar.showMessage("Focused", 2000)
            indicationColor = Qt.darkGreen
        elif status == QCamera.Unlocked:
            self.ui.lockButton.setText("Focus")

            if reason == QCamera.LockFailed:
                self.ui.statusbar.showMessage("Focus Failed", 2000)
                indicationColor = Qt.red

        palette = self.ui.lockButton.palette()
        palette.setColor(QPalette.ButtonText, indicationColor)
        self.ui.lockButton.setPalette(palette)

    def takeImage(self):
        self.isCapturingImage = True
        self.imageCapture.capture()

    def startCamera(self):
        self.camera.start()

    def stopCamera(self):
        self.camera.stop()

    def updateCaptureMode(self):
        tabIndex = self.ui.captureWidget.currentIndex()
        captureMode = QCamera.CaptureStillImage if tabIndex == 0 else QCamera.CaptureVideo

        if self.camera.isCaptureModeSupported(captureMode):
            self.camera.setCaptureMode(captureMode)

    def updateCameraState(self, state):
        if state == QCamera.ActiveState:
            self.ui.actionStartCamera.setEnabled(False)
            self.ui.actionStopCamera.setEnabled(True)
            self.ui.captureWidget.setEnabled(True)
            self.ui.actionSettings.setEnabled(True)
        elif state in (QCamera.UnloadedState, QCamera.LoadedState):
            self.ui.actionStartCamera.setEnabled(True)
            self.ui.actionStopCamera.setEnabled(False)
            self.ui.captureWidget.setEnabled(False)
            self.ui.actionSettings.setEnabled(False)

    def updateRecorderState(self, state):
        if state == QMediaRecorder.StoppedState:
            self.ui.recordButton.setEnabled(True)
            self.ui.pauseButton.setEnabled(True)
            self.ui.stopButton.setEnabled(False)
        elif state == QMediaRecorder.PausedState:
            self.ui.recordButton.setEnabled(True)
            self.ui.pauseButton.setEnabled(False)
            self.ui.stopButton.setEnabled(True)
        elif state == QMediaRecorder.RecordingState:
            self.ui.recordButton.setEnabled(False)
            self.ui.pauseButton.setEnabled(True)
            self.ui.stopButton.setEnabled(True)

    def setExposureCompensation(self, index):
        self.camera.exposure().setExposureCompensation(index * 0.5)

    def displayRecorderError(self):
        QMessageBox.warning(self, "Capture error",
                            self.mediaRecorder.errorString())

    def displayCameraError(self):
        QMessageBox.warning(self, "Camera error", self.camera.errorString())

    def updateCameraDevice(self, action):
        self.setCamera(action.data())

    def displayViewfinder(self):
        self.ui.stackedWidget.setCurrentIndex(0)

    def displayCapturedImage(self):
        self.ui.stackedWidget.setCurrentIndex(1)

    def readyForCapture(self, ready):
        self.ui.takeImageButton.setEnabled(ready)

    def imageSaved(self, id, fileName):
        self.isCapturingImage = False

        if self.applicationExiting:
            self.close()

    def closeEvent(self, event):
        if self.isCapturingImage:
            self.setEnabled(False)
            self.applicationExiting = True
            event.ignore()
        else:
            event.accept()
Пример #5
0
class CMainWindow(QtWidgets.QMainWindow):
    def __init__(self, *args, **kwargs):
        super(CMainWindow, self).__init__(*args, **kwargs)
        self.oc_camera = None
        self.l_cameras = QCameraInfo.availableCameras()
        if len(self.l_cameras) == 0:
            self.fatal_error("No cameras found!")

        # Top tool-bar
        self.oc_toolbar = QtWidgets.QToolBar("Video source selector")
        self.oc_toolbar.setMovable(False)

        lbl = QtWidgets.QLabel("Select video source:")
        self.oc_toolbar.addWidget(lbl)

        camera_selector = QtWidgets.QComboBox()
        camera_selector.addItems([ "[ %i ] %s" % (i_idx, oc_cam.description()) for i_idx, oc_cam in enumerate(self.l_cameras)])
        camera_selector.currentIndexChanged.connect( self.start_preview )

        self.oc_toolbar.addWidget(camera_selector)
        self.oc_toolbar.layout().setSpacing(5)
        self.oc_toolbar.layout().setContentsMargins(5, 5, 5, 5)
        self.addToolBar(self.oc_toolbar)

        # Central part (video frame)
        self.oc_viewfinder = QCameraViewfinder()
        self.setCentralWidget(self.oc_viewfinder)

        # Bottom status bar
        self.status = QtWidgets.QStatusBar()
        self.setStatusBar(self.status)

        self.setWindowTitle("CamView")
        self.start_preview(0)

    def fatal_error(self, s_msg):
        QtWidgets.QMessageBox.critical(None, "Fatal Error", "%s\nThe application will exit now." % s_msg)
        sys.exit(-1)

    def start_preview(self, i_cam_idx):
        if self.oc_camera is not None:
            self.oc_camera.stop()
            del self.oc_camera
        self.oc_camera = QCamera(self.l_cameras[i_cam_idx])
        self.oc_camera.setViewfinder(self.oc_viewfinder)
        self.oc_camera.setCaptureMode(QCamera.CaptureVideo)
        self.oc_camera.error.connect(lambda: self.show_error(self.oc_camera.errorString()))
        self.oc_camera.start()

    def stop_preview(self):
        if self.oc_camera is None:
            return # this is correct logic, no error here
        self.oc_camera.stop()
        self.oc_camera.unload()
        self.oc_camera = None

    def show_error(self, s):
        err = QtWidgets.QErrorMessage(self)
        err.showMessage(s)

    def closeEvent(self, event):
        self.stop_preview()
class UiMainWindow(QWidget):
    """Main UI window of the application.

	Attributes:
	----------
	window_width: int
		Width of the window
	window_height: int
		Height of the window
	button_width: int
		Width of buttons
	button_height: int
		Height of buttons
	dist: int
		Distance to the edge of Widgets(Window/Button/Label...)
	model_selected: bool
		Shows whether a model is selected or not
	"""
    window_height = 650
    window_width = 800
    button_width = 180
    button_height = 50
    dist = 30
    model_selected = False
    textbox_height = 25
    small_button_width = 100
    small_button_height = 30
    debug_height = 200
    debug_mode = False
    accepted_download = False
    current_city = ""

    def __init__(self, parent) -> None:
        super().__init__(parent)

        main_window.setObjectName("main_window")
        main_window.resize(self.window_width, self.window_height)
        self.centralwidget = QWidget(main_window)
        self.centralwidget.setObjectName("centralwidget")
        self.detector = Detection()

        self.Box_Stadt = QComboBox(self.centralwidget)
        self.Box_Stadt.setGeometry(
            QRect(self.dist, self.dist, self.button_width, self.button_height))
        self.Box_Stadt.setObjectName("Box_Stadt")
        self.Box_Stadt.activated.connect(self.on_dropdown_selected)
        # dynamic city updates
        supported_cities_updater = Thread(target=update_dropdown,
                                          daemon=True,
                                          args=(self.Box_Stadt, ))
        supported_cities_updater.start()

        self.Text_City = QLineEdit(self.centralwidget)
        self.Text_City.setGeometry(
            QRect(self.dist + self.dist + self.button_width, self.dist + 10,
                  self.button_width, self.textbox_height))
        self.Text_City.setObjectName("Text_City")
        self.Text_City.setToolTip(
            'Enter a city you wish to detect sights in that you cannot find in the dropdown on the left after updating.'
        )

        self.Button_City = QPushButton(self.centralwidget)
        self.Button_City.setGeometry(
            QRect(
                int(2.3 * self.dist) + self.button_width + self.button_width,
                self.dist + 8, self.small_button_width,
                self.small_button_height))
        self.Button_City.setObjectName("Button_City")
        self.Button_City.clicked.connect(self.request_city)

        self.Button_Detection = QPushButton(self.centralwidget)
        self.Button_Detection.setGeometry(
            QRect(
                self.window_width - (self.dist + self.button_width),
                self.window_height - (self.dist + self.button_height + 20),
                self.button_width,
                self.button_height,
            ))
        self.Button_Detection.setObjectName("Button_Detection")
        self.Button_Detection.clicked.connect(self.detect_sights)

        self.Button_Bild = QPushButton(self.centralwidget)
        self.Button_Bild.setGeometry(
            QRect(
                self.dist,
                self.window_height - (self.dist + self.button_height + 20),
                self.button_width,
                self.button_height,
            ))
        self.Button_Bild.setObjectName("Button_Bild")
        self.Button_Bild.clicked.connect(lambda: self.camera_viewfinder.hide())
        self.Button_Bild.clicked.connect(
            lambda: self.Box_Camera_selector.setCurrentIndex(0))
        self.Button_Bild.clicked.connect(
            lambda: self.stacked_widget.setCurrentIndex(0))
        self.Button_Bild.clicked.connect(lambda: self.Label_Bild.show())
        self.Button_Bild.clicked.connect(self.dragdrop)

        self.available_cameras = QCameraInfo.availableCameras()

        self.Box_Camera_selector = QComboBox(self.centralwidget)
        self.Box_Camera_selector.setGeometry(
            QRect(
                self.window_width - (self.dist + self.button_width),
                self.dist,
                self.button_width,
                self.button_height,
            ))
        self.Box_Camera_selector.setObjectName("Box_Camera_selector")
        self.Box_Camera_selector.addItem("")
        # self.Box_Camera_selector.addItems([camera.description() for camera in self.available_cameras])
        self.Box_Camera_selector.addItems([
            "Camera " + str(i) + ": " +
            str(self.available_cameras[i].description())
            for i in range(len(self.available_cameras))
        ])
        self.Box_Camera_selector.currentIndexChanged.connect(
            self.select_camera)

        self.stacked_widget = QStackedWidget(self.centralwidget)
        label_height = (self.window_height - self.dist - self.button_height -
                        self.dist) - (self.dist + self.button_height +
                                      self.dist)
        label_start_y = self.dist + self.button_height + self.dist
        self.stacked_widget.setGeometry(
            QRect(
                self.dist,
                label_start_y,
                self.window_width - (self.dist * 2),
                label_height,
            ))

        self.camera_viewfinder = QCameraViewfinder()

        self.Label_Bild = ImageLabel(self)
        self.Label_Bild.setGeometry(
            QRect(0, 0, self.window_width - (self.dist * 2), label_height))

        self.checkBoxImprove = QCheckBox(
            "Help improving SightScan's detection quality", self.centralwidget)
        self.checkBoxImprove.setObjectName(u"improvement")
        self.checkBoxImprove.setGeometry(QRect(self.dist, 5, 350, 20))
        self.checkBoxImprove.setChecked(False)
        self.checkBoxImprove.stateChanged.connect(self.set_improve_quality_var)

        self.checkBox = QCheckBox("Debug", self.centralwidget)
        self.checkBox.setObjectName(u"checkBox")
        self.checkBox.setGeometry(
            QRect(self.window_width - (self.dist + 50),
                  self.window_height - (self.dist + 20), 70, 20))
        self.checkBox.setChecked(False)
        self.checkBox.stateChanged.connect(self.debug_click)

        # Setup logging
        fn = "logs/" + datetime.now().strftime(
            '%d_%m_%Y__%H_%M_%S') + 'log.log'
        if not os.path.exists("logs"):
            os.mkdir("logs")
        f = '%(asctime)s :: %(levelname)s :: %(filename)s :: %(funcName)s :: %(lineno)d :: %(message)s'
        self.textDebug = QTextEditLogger(self.centralwidget)
        self.textDebug.setFormatter(logging.Formatter(f))
        logging.basicConfig(filename=fn, format=f, level=logging.DEBUG)
        logging.getLogger().addHandler(self.textDebug)

        # Log Text Box in GUI
        self.textDebug.widget.setObjectName(u"textEdit")
        self.textDebug.widget.setEnabled(False)
        self.textDebug.widget.setGeometry(
            QRect(self.dist, self.window_height,
                  self.window_width - 2 * self.dist,
                  self.debug_height - self.dist))
        size_policy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Expanding)
        size_policy.setHorizontalStretch(0)
        size_policy.setVerticalStretch(0)
        size_policy.setHeightForWidth(
            self.textDebug.widget.sizePolicy().hasHeightForWidth())
        self.textDebug.widget.setSizePolicy(size_policy)
        self.textDebug.widget.setReadOnly(True)

        self.stacked_widget.addWidget(self.Label_Bild)
        self.stacked_widget.addWidget(self.camera_viewfinder)

        main_window.setCentralWidget(self.centralwidget)
        self.menubar = QMenuBar(main_window)
        self.menubar.setGeometry(QRect(0, 0, 678, 21))
        self.menubar.setObjectName("menubar")
        main_window.setMenuBar(self.menubar)

        self.statusbar = QStatusBar(main_window)
        self.statusbar.setObjectName("statusbar")
        main_window.setStatusBar(self.statusbar)

        main_window.setWindowIcon(QIcon(logo_without_text))

        self.retranslateUi(main_window)
        QMetaObject.connectSlotsByName(main_window)

    def set_improve_quality_var(self):
        self.improve_checkbox_enabled = self.checkBoxImprove.isChecked()

    def retranslateUi(self, main_window: QMainWindow) -> None:
        """Set the text initially for all items.

		Parameters
		----------
		main_window: QMainWindow
		    The instance of the prepared application window
		"""
        _translate = QCoreApplication.translate
        main_window.setWindowTitle(_translate(WINDOW, "SightScan"))
        self.Box_Stadt.addItems(['Choose City'] + initialize_cities())
        self.Box_Camera_selector.setItemText(
            0, _translate(WINDOW, "Choose Webcam"))
        self.Button_Detection.setText(_translate(WINDOW, START))
        self.Button_Bild.setText(_translate(WINDOW, ENABLE))
        self.Button_City.setText(_translate(WINDOW, "Add City"))

    def on_dropdown_selected(self) -> None:
        """Shows a pop-up for confirming the download of the selected city."""
        city_pretty_print = self.Box_Stadt.currentText()
        city = self.Box_Stadt.currentText().replace(' ', '_').upper()

        if city != "CHOOSE_CITY":
            self.current_city = self.Box_Stadt.currentText()
            # if no connection to dos
            if get_supported_cities() == []:
                latest_version = "couldn't get the latest version"
                downloaded_version = "couldn't get the downloaded version"
                print('no connection to dos')

            # if connection to dos
            else:
                downloaded_version = -1  # initialization

                Path("weights").mkdir(mode=0o700, exist_ok=True)

                if not os.path.exists("weights/versions.txt"):
                    with open('weights/versions.txt',
                              'w'):  # creating a version file
                        pass

                with open("weights/versions.txt", "r") as file:
                    for line in file:
                        elements = line.split("=")
                        if elements[0].upper() == city:
                            downloaded_version = int(elements[1])
                            break

                latest_version = get_dwh_model_version(city)

                if downloaded_version == -1:
                    msg = QMessageBox()
                    msg.setWindowTitle("Download City")
                    msg.setWindowIcon(QIcon(logo_without_text))
                    msg.setText("Do you want to download " +
                                city_pretty_print + "?")
                    msg.setIcon(QMessageBox.Question)
                    msg.setStandardButtons(QMessageBox.Cancel | QMessageBox.Ok)
                    msg.setDefaultButton(QMessageBox.Ok)
                    msg.setInformativeText("When downloaded, sights of " +
                                           city_pretty_print +
                                           " can be detected.")
                    msg.buttonClicked.connect(self.handover_city)

                    msg.exec_()

                elif latest_version > downloaded_version:
                    update_msg = QMessageBox()
                    update_msg.setWindowTitle("Update available")
                    update_msg.setWindowIcon(QIcon(logo_without_text))
                    update_msg.setText(
                        "Do you want to download an update for " + city + "?")
                    update_msg.setIcon(QMessageBox.Question)
                    update_msg.setStandardButtons(QMessageBox.Cancel
                                                  | QMessageBox.Ok)
                    update_msg.setDefaultButton(QMessageBox.Ok)
                    update_msg.setInformativeText(
                        "Updated cities can detect sights faster and more accurately. If you choose not to download, the "
                        + "detection will still work.")
                    update_msg.buttonClicked.connect(self.handover_city)

                    update_msg.exec_()
            if self.accepted_download is True or latest_version == downloaded_version:
                self.accepted_download = False
                self.show_download_result()
            self.model_selected = True
        else:
            self.model_selected = False

    def handover_city(self, button) -> None:
        """Starts the download of the pre-trained model of the selected city.

		Parameters
		----------
		button:
			Pushed button inside the popup.
		"""

        if "OK" in button.text().upper():
            city = self.Box_Stadt.currentText().replace(' ', '_').upper()
            self.model_selected = True
            model = get_downloaded_model(city)
            if model is not None:
                with open("weights/" + city + ".pt", "wb+") as file:
                    file.write(model)
            self.accepted_download = True
        elif "CANCEL" in button.text().upper():
            self.Box_Stadt.setCurrentIndex(0)

    def detect_sights(self) -> None:
        """Starts detection for the dropped image or shown webcam video
		with the downloaded model and displays the results in the label."""
        city = self.Box_Stadt.currentText().replace(' ', '_').upper()
        print("Detection Status: " + str(self.detector.detection))

        if self.model_selected is False:
            self.show_missing_model_popup()
        else:
            # start drag&drop image detection
            if self.stacked_widget.currentIndex() == 0 and self.Button_Bild.text() == DISABLE and \
              self.Label_Bild.image != logo_with_text:
                print(f"Starting detection of {self.Label_Bild.image}")
                wipe_prediction_input_images(INPUT_PREDICTION_DIR)
                shutil.copy2(self.Label_Bild.image, INPUT_PREDICTION_DIR)
                self.detector.enable_detection()
                self.detector.detect(self,
                                     weights='weights/' + city + '.pt',
                                     debug=self.debug_mode)
            # stop video detection
            elif self.stacked_widget.currentIndex(
            ) == 0 and self.Button_Detection.text() == STOP:
                self.stop_video_detection()
                time.sleep(2)
                self.reactivate_cam()
            # if webcam activated
            elif self.stacked_widget.currentIndex() == 1:
                if self.Button_Detection.text() == START:
                    self.Button_Detection.setText(
                        QCoreApplication.translate(WINDOW, STOP))
                    self.Label_Bild.setStyleSheet("""
					""")
                    print("Video Detection Started")
                    self.prep_video_detection()
                    source = self.Box_Camera_selector.currentIndex()
                    self.detector.enable_detection()
                    self.detection_thread = Thread(target=self.detector.detect,
                                                   args=(self, ),
                                                   kwargs={
                                                       'weights':
                                                       'weights/' + city +
                                                       '.pt',
                                                       'source':
                                                       str(source - 1),
                                                       'image_size':
                                                       704,
                                                       'debug':
                                                       self.debug_mode
                                                   })
                    self.detection_thread.start()
            else:
                print("Drop a File or select a Webcam!")

    def show_missing_model_popup(self) -> None:
        # Show Pop Up to choose a city
        emsg = QMessageBox()
        emsg.setWindowTitle("No city chosen")
        emsg.setWindowIcon(QIcon(logo_without_text))
        emsg.setText(
            "You need to choose a city before the detection can start.")
        emsg.setIcon(QMessageBox.Warning)
        emsg.setStandardButtons(QMessageBox.Ok)
        emsg.setDefaultButton(QMessageBox.Ok)

        emsg.exec_()

    def show_download_result(self) -> None:
        # city_pretty_print = self.Box_Stadt.currentText()

        self.model_selected = True
        newest_vers_msg = QMessageBox()
        newest_vers_msg.setWindowTitle("Ready for Detection!")
        newest_vers_msg.setWindowIcon(QIcon(logo_without_text))
        newest_vers_msg.setText("You can start detecting sights in " +
                                self.current_city + "!")
        newest_vers_msg.setStandardButtons(QMessageBox.Ok)
        newest_vers_msg.setDefaultButton(QMessageBox.Ok)

        newest_vers_msg.exec_()

    def request_city(self) -> None:
        # Send entered city to dwh and show confirmation popup if the city name is known
        city_input = self.Text_City.text()
        city_request = city_input.upper()
        if len(filter_city(city_input)) == 1:
            send_city_request(city_request)

            cmsg = QMessageBox()
            cmsg.setWindowTitle("Request confirmed")
            cmsg.setWindowIcon(QIcon(logo_without_text))
            cmsg.setText("Your request to add support for " + city_input +
                         " has been sent to our backend.")
            cmsg.setStandardButtons(QMessageBox.Ok)
            cmsg.setDefaultButton(QMessageBox.Ok)
            cmsg.exec_()
        else:
            cmsg = QMessageBox()
            cmsg.setWindowTitle("Unknown city name")
            cmsg.setWindowIcon(QIcon(logo_without_text))
            cmsg.setText(
                "The typed city name is not known. Please check the spelling.")
            cmsg.setIcon(QMessageBox.Warning)
            cmsg.setStandardButtons(QMessageBox.Ok)
            cmsg.setDefaultButton(QMessageBox.Ok)
            cmsg.exec_()

    def dragdrop(self) -> None:
        """Enables / disables Drag&Drop of images."""
        if self.Button_Bild.text() == ENABLE:
            # stop video detection if active
            if self.Button_Detection.text() == STOP:
                self.Button_Detection.setText(
                    QCoreApplication.translate(WINDOW, START))
                self.detector.disable_detection()
            self.Label_Bild.setAcceptDrops(True)
            self.Label_Bild.setText("\n\n Drop Image here \n\n")
            self.Label_Bild.setStyleSheet("""
				QLabel{
					border: 4px dashed #aaa
				}
			""")
            self.Button_Bild.setText(
                QCoreApplication.translate(WINDOW, DISABLE))
        elif self.Button_Bild.text() == DISABLE:
            self.Label_Bild.setAcceptDrops(False)
            self.Label_Bild.setText("")
            self.Label_Bild.setStyleSheet("")
            self.Label_Bild.image = logo_with_text
            self.Label_Bild.setPixmap(QPixmap(self.Label_Bild.image))
            self.Button_Bild.setText(QCoreApplication.translate(
                WINDOW, ENABLE))

    def select_camera(self, i):
        """Starts the selected camera. If "Choose webcam" is selected, it stops the camera.

		Parameters
		----------
		i:
			Index of the chosen camera.
		"""
        self.Label_Bild.image = logo_with_text
        self.Label_Bild.setPixmap(QPixmap(self.Label_Bild.image))
        if i == 0:
            self.camera.stop()
            self.detector.disable_detection()
            self.Button_Detection.setText(
                QCoreApplication.translate(WINDOW, START))
            self.stacked_widget.setCurrentIndex(0)
            self.camera_viewfinder.hide()
            self.Label_Bild.show()
            time.sleep(2)
            self.Label_Bild.image = logo_with_text
            self.Label_Bild.setPixmap(QPixmap(self.Label_Bild.image))
            self.Label_Bild.setStyleSheet("""
			""")
        else:
            self.camera_viewfinder.show()
            self.stacked_widget.setCurrentIndex(1)
            self.Label_Bild.hide()
            self.camera = QCamera(self.available_cameras[i - 1])
            self.camera.setViewfinder(self.camera_viewfinder)
            self.camera.error.connect(
                lambda: self.alert(self.camera.errorString()))
            self.camera.start()
            self.Button_Bild.setText(QCoreApplication.translate(
                WINDOW, ENABLE))

    def prep_video_detection(self) -> None:
        self.camera.stop()
        self.camera_viewfinder.hide()
        self.stacked_widget.setCurrentIndex(0)
        self.Label_Bild.image = loading_image
        self.Label_Bild.setPixmap(QPixmap(self.Label_Bild.image))
        self.Label_Bild.show()

    def stop_video_detection(self) -> None:
        self.Button_Detection.setText(QCoreApplication.translate(
            WINDOW, START))
        self.detector.disable_detection()
        self.stacked_widget.setCurrentIndex(1)
        self.Label_Bild.hide()
        self.camera_viewfinder.show()

    def debug_click(self, state):
        self.debug_mode = bool(state)

        if state:
            main_window.resize(self.window_width,
                               self.window_height + self.debug_height)
            self.textDebug.widget.setEnabled(True)
        else:
            main_window.resize(self.window_width, self.window_height)
            self.textDebug.widget.setEnabled(False)

    def reactivate_cam(self) -> None:
        self.Label_Bild.image = logo_with_text
        self.Label_Bild.setPixmap(QPixmap(self.Label_Bild.image))
        self.camera.start()

    def close_all(self) -> None:
        if self.Button_Detection.text() == STOP:
            self.detector.disable_detection()
            self.stop_video_detection()
Пример #7
0
class Camera(QWidget):
    def __init__(self, parent=None, standalone=False):
        super(Camera, self).__init__(parent)

        # This prevents doing unneeded initialization
        # when QtDesginer loads the plugin.
        if parent is None and not standalone:
            return

        if not multimedia_available:
            return

        self.ui = uic.loadUi(os.path.join(WIDGET_PATH, "camera.ui"), self)

        self.camera = None
        self.imageCapture = None
        self.mediaRecorder = None
        self.isCapturingImage = False
        self.applicationExiting = False

        self.imageSettings = QImageEncoderSettings()
        self.audioSettings = QAudioEncoderSettings()
        self.videoSettings = QVideoEncoderSettings()
        self.videoContainerFormat = ''

        camera_device = QByteArray()

        videoDevicesGroup = QActionGroup(self)

        videoDevicesGroup.setExclusive(True)

        if not QCamera.availableDevices():
            self.ui.devicesCombo.addItem("No Device")
        else:
            for deviceName in QCamera.availableDevices():
                description = QCamera.deviceDescription(deviceName)
                self.ui.devicesCombo.addItem(description)

                videoDeviceAction = QAction(description, videoDevicesGroup)
                videoDeviceAction.setCheckable(True)
                videoDeviceAction.setData(deviceName)

                if camera_device.isEmpty():
                    cameraDevice = deviceName
                    videoDeviceAction.setChecked(True)

                self.ui.devicesCombo.addAction(videoDeviceAction)

        videoDevicesGroup.triggered.connect(self.updateCameraDevice)

        self.ui.captureWidget.currentChanged.connect(self.updateCaptureMode)

        self.ui.devicesCombo.currentIndexChanged.connect(
            self.get_device_action)

        self.ui.lockButton.hide()

        # Start camera 2s after the UI has loaded
        QTimer.singleShot(2000, lambda: self.setCamera(camera_device))

    def setCamera(self, cameraDevice):
        try:
            if cameraDevice.isEmpty():
                self.camera = QCamera()
            else:
                self.camera = QCamera(cameraDevice)

            self.camera.stateChanged.connect(self.updateCameraState)
            self.camera.error.connect(self.displayCameraError)

            self.mediaRecorder = QMediaRecorder(self.camera)
            self.mediaRecorder.stateChanged.connect(self.updateRecorderState)

            self.imageCapture = QCameraImageCapture(self.camera)

            self.mediaRecorder.durationChanged.connect(self.updateRecordTime)
            self.mediaRecorder.error.connect(self.displayRecorderError)

            self.mediaRecorder.setMetaData(QMediaMetaData.Title,
                                           "Camera Widget")

            self.ui.exposureCompensation.valueChanged.connect(
                self.setExposureCompensation)

            self.camera.setViewfinder(self.ui.viewfinder)

            self.updateCameraState(self.camera.state())
            self.updateLockStatus(self.camera.lockStatus(),
                                  QCamera.UserRequest)
            self.updateRecorderState(self.mediaRecorder.state())

            self.imageCapture.readyForCaptureChanged.connect(
                self.readyForCapture)
            self.imageCapture.imageCaptured.connect(self.processCapturedImage)
            self.imageCapture.imageSaved.connect(self.imageSaved)

            self.camera.lockStatusChanged.connect(self.updateLockStatus)

            self.ui.captureWidget.setTabEnabled(
                0,
                self.camera.isCaptureModeSupported(QCamera.CaptureStillImage))
            self.ui.captureWidget.setTabEnabled(
                1, self.camera.isCaptureModeSupported(QCamera.CaptureVideo))

            self.updateCaptureMode()
            self.camera.start()
        except:
            pass

    def keyPressEvent(self, event):
        if event.isAutoRepeat():
            return

        if event.key() == Qt.Key_CameraFocus:
            self.displayViewfinder()
            self.camera.searchAndLock()
            event.accept()
        elif event.key() == Qt.Key_Camera:
            if self.camera.captureMode() == QCamera.CaptureStillImage:
                self.takeImage()
            elif self.mediaRecorder.state() == QMediaRecorder.RecordingState:
                self.stop()
            else:
                self.record()

            event.accept()
        else:
            super(Camera, self).keyPressEvent(event)

    def keyReleaseEvent(self, event):
        if event.isAutoRepeat():
            return

        if event.key() == Qt.Key_CameraFocus:
            self.camera.unlock()
        else:
            super(Camera, self).keyReleaseEvent(event)

    def updateRecordTime(self):
        msg = "Recorded {} sec".format(self.mediaRecorder.duration())
        self.ui.timeLabel.text = msg
        print(msg)

    def processCapturedImage(self, requestId, img):
        scaledImage = img.scaled(self.ui.viewfinder.size(), Qt.KeepAspectRatio,
                                 Qt.SmoothTransformation)

        self.ui.lastImagePreviewLabel.setPixmap(QPixmap.fromImage(scaledImage))

        self.displayCapturedImage()
        QTimer.singleShot(4000, self.displayViewfinder)

    def configureSettings(self):

        settings_dialog = Settings(self.mediaRecorder, self.imageCapture)

        settings_dialog.setImageSettings(self.imageSettings)
        settings_dialog.setAudioSettings(self.audioSettings)
        settings_dialog.setVideoSettings(self.videoSettings)

        settings_dialog.setFormat(self.videoContainerFormat)
        # settings_dialog.setStreamingSettings(self.streamingSettings)

        if settings_dialog.exec_():
            self.imageSettings = settings_dialog.imageSettings()
            self.audioSettings = settings_dialog.audioSettings()
            self.videoSettings = settings_dialog.videoSettings()
            self.videoContainerFormat = settings_dialog.format()

            self.imageCapture.setEncodingSettings(self.imageSettings)
            self.mediaRecorder.setEncodingSettings(self.audioSettings,
                                                   self.videoSettings,
                                                   self.videoContainerFormat)

    def record(self):
        self.mediaRecorder.record()
        self.updateRecordTime()

    def pause(self):
        self.mediaRecorder.pause()

    def stop(self):
        self.mediaRecorder.stop()

    def setMuted(self, muted):
        self.mediaRecorder.setMuted(muted)

    def toggleLock(self):
        if self.camera.lockStatus() in (QCamera.Searching, QCamera.Locked):
            self.camera.unlock()
        elif self.camera.lockStatus() == QCamera.Unlocked:
            self.camera.searchAndLock()

    def updateLockStatus(self, status, reason):
        indicationColor = Qt.black

        if status == QCamera.Searching:
            self.ui.statusbar.showMessage("Focusing...")
            self.ui.lockButton.setText("Focusing...")
            indicationColor = Qt.yellow
        elif status == QCamera.Locked:
            self.ui.lockButton.setText("Unlock")
            self.ui.statusbar.showMessage("Focused", 2000)
            indicationColor = Qt.darkGreen
        elif status == QCamera.Unlocked:
            self.ui.lockButton.setText("Focus")

            if reason == QCamera.LockFailed:
                self.ui.statusbar.showMessage("Focus Failed", 2000)
                indicationColor = Qt.red

        palette = self.ui.lockButton.palette()
        palette.setColor(QPalette.ButtonText, indicationColor)
        self.ui.lockButton.setPalette(palette)

    def takeImage(self):
        self.isCapturingImage = True
        self.imageCapture.capture()

    def startCamera(self):
        self.camera.start()

    def stopCamera(self):
        self.camera.stop()

    def updateCaptureMode(self):
        tabIndex = self.ui.captureWidget.currentIndex()
        captureMode = QCamera.CaptureStillImage if tabIndex == 0 else QCamera.CaptureVideo

        if self.camera.isCaptureModeSupported(captureMode):
            self.camera.setCaptureMode(captureMode)

    def updateCameraState(self, state):
        if state == QCamera.ActiveState:
            self.ui.actionStartCamera.setEnabled(False)
            self.ui.actionStopCamera.setEnabled(True)
            self.ui.captureWidget.setEnabled(True)
            self.ui.actionSettings.setEnabled(True)
        elif state in (QCamera.UnloadedState, QCamera.LoadedState):
            self.ui.actionStartCamera.setEnabled(True)
            self.ui.actionStopCamera.setEnabled(False)
            self.ui.captureWidget.setEnabled(False)
            self.ui.actionSettings.setEnabled(False)

    def updateRecorderState(self, state):
        if state == QMediaRecorder.StoppedState:
            self.ui.recordButton.setEnabled(True)
            self.ui.pauseButton.setEnabled(True)
            self.ui.stopButton.setEnabled(False)
        elif state == QMediaRecorder.PausedState:
            self.ui.recordButton.setEnabled(True)
            self.ui.pauseButton.setEnabled(False)
            self.ui.stopButton.setEnabled(True)
        elif state == QMediaRecorder.RecordingState:
            self.ui.recordButton.setEnabled(False)
            self.ui.pauseButton.setEnabled(True)
            self.ui.stopButton.setEnabled(True)

    def setExposureCompensation(self, index):
        self.camera.exposure().setExposureCompensation(index * 0.5)

    def displayRecorderError(self):
        QMessageBox.warning(self, "Capture error",
                            self.mediaRecorder.errorString())

    def displayCameraError(self):
        QMessageBox.warning(self, "Camera error", self.camera.errorString())

    def get_device_action(self, index):
        self.ui.devicesCombo.actions()[index].trigger()

    def updateCameraDevice(self, action):
        self.setCamera(action.data())

    def displayViewfinder(self):
        self.ui.stackedWidget.setCurrentIndex(0)

    def displayCapturedImage(self):
        self.ui.stackedWidget.setCurrentIndex(1)

    def readyForCapture(self, ready):
        self.ui.takeImageButton.setEnabled(ready)

    def imageSaved(self, id, fileName):
        self.isCapturingImage = False

        if self.applicationExiting:
            self.close()

    def closeEvent(self, event):
        if self.isCapturingImage:
            self.setEnabled(False)
            self.applicationExiting = True
            event.ignore()
        else:
            event.accept()