Example #1
0
class CameraMainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        uic.loadUi('MainWin.ui', self)
        self.setWindowTitle('CamPaint')
        self.setWindowIcon(QIcon('main_icon.ico'))
        self.setCentralWidget(self.tabWidget)
        # Загружаем камеру, холст, sql файл и задаем цвета кнопок
        self.load_cam()
        self.load_painter()
        self.load_sql()
        self.load_colors()

    def load_cam(self):
        self.cam_page.setLayout(self.cam_page_lay)
        self.error_cam.hide()
        self.camera = QCameraInfo.defaultCamera()
        # Проверяем, что камера сущетсвует
        # Если нет, то переключаемся на вторую вкладку
        if self.camera.isNull():
            dialog = QErrorMessage()
            dialog.setWindowTitle('Warning')
            dialog.showMessage(
                'Not enough cameras, the app will only be available in drawing mode'
            )
            dialog.exec()
            self.error_cam.show()
            self.cam_page.setEnabled(False)
            self.tabWidget.setCurrentIndex(1)
        # Если да, то на первую
        else:
            self.tabWidget.setCurrentIndex(0)
            self.camera = QCamera(self.camera)
            self.view_cam = QCameraViewfinder(self)
            self.view_cam.setMediaObject(self.camera)
            self.view_cam.setAutoFillBackground(True)
            self.camera.setViewfinder(self.view_cam)
            self.box_lay = QVBoxLayout(self)
            self.box_lay.addWidget(self.view_cam)
            self.scrolling.setLayout(self.box_lay)
            # Запускаем камеру
            self.camera.start()
            # Подвязываем кнопку к слоту со снимком
            self.bt_cam.clicked.connect(self.make_ph)
            # Можно зумить фотографию
            self.zoom.valueChanged.connect(self.zoom_pict)

    def make_ph(self):
        self.camera.setCaptureMode(QCamera.CaptureStillImage)
        self.capt = QCameraImageCapture(self.camera)
        # Останавливаем съемку
        self.camera.searchAndLock()
        # Вызываем диалог и иохранением файла
        dial = QFileDialog.getSaveFileName(
            self, 'Save file', '',
            'Картинка (*.jpg);;Картинка (*.png);;Все файлы (*)')[0]
        if dial:
            self.capt.capture(dial)
            self.camera.unlock()

    def zoom_pict(self, value):
        # Вычисляем зум камеры по функции zoom=1.0 + value * 3 / 99
        # 1.0 - обязательный параметр
        QCameraFocus.zoomTo(self.camera.focus(), 1.0 + value * 3 / 99, 1.0)

    def load_painter(self):
        # Загружаем холст
        self.paint_page.setLayout(self.paint_page_lay)
        # Текущий цвет - черный, ширина кисти - 10
        self.now_col = QColor(0, 0, 0)
        self.now_width = 10
        self.point_width.setValue(10)
        # Подвязываем кнопку с изменением ширины кисти к соответсвующему слоту
        self.point_width.valueChanged.connect(self.change_width)
        # Создаем холст как экземпляр класса Canvas из доп.модуля Canvas
        self.canvas = Canvas.Canvas(self.main_paint_widg)
        self.canvas.move(1, 1)
        self.canvas.resize(self.main_paint_widg.width() - 1,
                           self.main_paint_widg.height() - 1)
        print(self.main_paint_widg.size(), self.canvas.size(),
              self.border_lab.size())
        # Устанавливаем границы рамки
        self.border_lab.setStyleSheet(
            'border-style: solid; border-width: 2px; border-color: black;')
        self.canvas.setStyleSheet('background-color: white;')
        # Устанавливаем сильный фокус для перехвата всех событий
        # клавиатуры и мыши
        self.setFocusPolicy(Qt.StrongFocus)
        # Подвязываем действия из меню к слотам
        self.actionSave.triggered.connect(self.save_file)
        self.actionSave_as.triggered.connect(self.save_as_file)
        self.actionOpen.triggered.connect(self.open_file)
        self.actionReference.triggered.connect(self.open_reference)
        # и кнопку очистки холста, а также задания цвета кисти
        self.bt_clear.clicked.connect(self.clear_canvas)
        self.bt_set_color.clicked.connect(self.set_color_with_bt)
        # Имя файла изначально не задано, файл не сохранен
        self.file_name = ''
        self.saved = False
        self.resizeEvent(QResizeEvent(self.size(), self.size()))

    def change_width(self, value):
        self.now_width = value

    def keyPressEvent(self, event):
        # Обрабатываем события клавитатуры
        if int(event.modifiers()) == Qt.CTRL and event.key() == Qt.Key_Z:
            # Функция 'назад', удаляем все объекты, которые нарисовали
            if self.canvas.obj:
                del self.canvas.obj[-1]
                self.canvas.update()
        elif int(event.modifiers()) == Qt.CTRL and event.key() == Qt.Key_S:
            # Функция 'сохранить', сохраняем файл, если есть изменения
            if self.canvas.obj:
                self.save_file()
        elif int(event.modifiers()) == Qt.CTRL and event.key() == Qt.Key_O:
            # Функция 'открыть', открываем файл
            self.open_file()
        elif int(event.modifiers()) == Qt.CTRL and event.key() == Qt.Key_H:
            # Функция 'справка', открываем справку
            self.open_reference()

    def resizeEvent(self, event):
        # При изменении размеров окна, устанавливаем соответствующие размеры холста и рамки
        self.canvas.resize(self.main_paint_widg.width() - 1,
                           self.main_paint_widg.height() - 1)
        self.border_lab.resize(self.main_paint_widg.width(),
                               self.main_paint_widg.height())

    def save_as_file(self):
        # Сохранение файла как
        dial = \
            QFileDialog.getSaveFileName(self, 'Save file as', '', 'Картинка (*.jpg);;Картинка (*.png);;Все файлы (*)')[
                0]
        if dial:
            # Захватываем изображжение с холста и сохраняем
            pixmap = QPixmap(self.canvas.grab())
            pixmap.save(dial)
            # Сохраняем имя файла в переменной self.file_name, чтобы использовать в функции save_file
            # Очищаем нарисованные объекты, так как уже их сохранили
            self.file_name = dial
            self.saved = True
            self.canvas.obj = []

    def save_file(self):
        # Если имя файла выбрано, просто сохраняем
        if self.file_name:
            pixmap = QPixmap(self.canvas.grab())
            pixmap.save(self.file_name)
            self.saved = True
            self.canvas.obj = []
        # В ином случае, сохраняем как
        else:
            self.save_as_file()

    def open_file(self):
        # Открываем новый файл
        dial = QFileDialog.getOpenFileName(
            self, 'Open file', '',
            'Картинка (*.jpg);;Картинка (*.png);;Все файлы (*)')[0]
        if dial:
            # Если старый файл не сохранен, предлагаем сохранить его
            if self.canvas.obj and not self.saved:
                dial2 = Dialogs.Message()
                res = dial2.exec()
                if res == dial2.Save:
                    self.save_file()
                if res == dial2.Cancel:
                    pass
            # Сохраняем новое имя файла, вызываем функцию open_file в экземпляре холста
            self.file_name = dial
            self.canvas.obj = []
            self.canvas.open_file()

    def open_reference(self):
        dial = Dialogs.Reference()
        dial.exec()

    def clear_canvas(self):
        # Очищаем нарисованные объекты
        self.canvas.obj.clear()
        self.canvas.update()

    def set_color(self, color):
        # Устанавливаем текущий цвет
        self.now_col = color
        red, green, blue = color.red(), color.green(), color.blue()
        # Подключаемся к базе данных в папке проекта
        # и добавляем его к любимым цветам пользователя
        con = sqlite3.connect('own_colors_db.db')
        cur = con.cursor()
        colors = cur.execute(
            f'''SELECT * from colors WHERE red={red} and green={green} and blue={blue}'''
        ).fetchall()
        if colors:
            id = colors[0][0]
            cur.execute(
                f'''UPDATE colors SET counts=counts + 1 WHERE id={id}''')
        else:
            last_id = cur.execute(
                f'''SELECT id from colors''').fetchall()[-1][0]
            cur.execute(
                f'''INSERT INTO colors VALUES ({last_id + 1}, {red}, {green}, {blue}, 1)'''
            )
        con.commit()
        con.close()

    def set_color_with_bt(self):
        # Слот для кнопки выбора цвета
        color = QColorDialog.getColor()
        self.set_color(color)

    def closeEvent(self, event):
        # Закрываем файл, обнуляя значение зума
        self.zoom.setValue(1)
        # И предлагаем сохранить файл, если он не сохранен
        if self.canvas.obj and not self.saved:
            dial = Dialogs.Message()
            res = dial.exec()
            if res == dial.Save:
                self.save_file()
            if res == dial.Cancel:
                event.ignore()

    def load_sql(self):
        # При отсутствии цветов в базе данных(в первом открытии приложения)
        # добавляем в базу данных новый цвет - черный
        con = sqlite3.connect('own_colors_db.db')
        cur = con.cursor()
        len_sql = len(cur.execute(f'''SELECT * from colors''').fetchall())
        if len_sql == 0:
            cur.execute('''INSERT INTO colors VALUES (1, 0, 0, 0, 1)''')
        con.commit()
        con.close()

    def load_colors(self):
        # Загружаем цвета в кнопки любимых цветов пользователя
        colors = []
        con = sqlite3.connect('own_colors_db.db')
        cur = con.cursor()
        ex_colors = sorted(cur.execute(
            '''SELECT red, green, blue, counts from colors''').fetchall(),
                           key=lambda i: i[3])[:21]
        ex_colors = [(i[0], i[1], i[2]) for i in ex_colors]
        colors.extend(ex_colors)
        # Если цветов недостаточно, заполняем кнопки случайными цветами
        # вдруг какой-нибудь из них ползователю понравится
        if len(colors) < 20:
            for i in range(20 - len(colors)):
                new_color = (randrange(256), randrange(256), randrange(256))
                while new_color in colors:
                    new_color = (randrange(256), randrange(256),
                                 randrange(256))
                colors.append(new_color)
        # Сохраняем цвета кнопок в словарь, где ключ - кнопка, значение - цвет
        # А также подключаем кнопки к слоту и изменением цвета
        self.bt_colors_dict = {}
        for i in range(4):
            for j in range(5):
                exec(
                    f'self.bt{i}{j}.setStyleSheet("background:rgb({colors[0][0]}, {colors[0][1]}, {colors[0][2]});")'
                )
                color = QColor(colors[0][0], colors[0][1], colors[0][2])
                exec(f'self.bt_colors_dict[self.bt{i}{j}] = color')
                exec(f'self.bt{i}{j}.clicked.connect(self.set_color_with_bts)')
                del colors[0]

    def set_color_with_bts(self):
        # Слот для установки цвета кисти
        self.set_color(self.bt_colors_dict[self.sender()])
Example #2
0
class QmyMainWindow(QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)  #调用父类构造函数,创建窗体
        self.ui = Ui_MainWindow()  #创建UI对象
        self.ui.setupUi(self)  #构造UI界面

        self.__LabCameraState = QLabel("摄像头state:")
        self.__LabCameraState.setMinimumWidth(150)
        self.ui.statusBar.addWidget(self.__LabCameraState)

        self.__LabImageID = QLabel("图片文件ID:")
        self.__LabImageID.setMinimumWidth(100)
        self.ui.statusBar.addWidget(self.__LabImageID)

        self.__LabImageFile = QLabel("")  #保存的图片文件名
        ##      self.ui.statusBar.addWidget(self.__LabImageFile)
        self.ui.statusBar.addPermanentWidget(self.__LabImageFile)

        self.camera = None  #QCamera对象
        cameras = QCameraInfo.availableCameras()  #list[QCameraInfo]
        if len(cameras) > 0:
            self.__iniCamera()  #初始化摄像头
            self.__iniImageCapture()  #初始化静态画图
            self.camera.start()

##  ==============自定义功能函数========================

    def __iniCamera(self):  ##创建 QCamera对象
        camInfo = QCameraInfo.defaultCamera()  #获取缺省摄像头,QCameraInfo
        self.ui.comboCamera.addItem(camInfo.description())  #摄像头描述
        self.ui.comboCamera.setCurrentIndex(0)

        self.camera = QCamera(camInfo)  #创建摄像头对象
        self.camera.setViewfinder(self.ui.viewFinder)  #设置取景框预览
        ##          camera.setCaptureMode(QCamera.CaptureViewfinder) #预览
        self.camera.setCaptureMode(QCamera.CaptureStillImage)  #设置为抓图
        ##          camera.setCaptureMode(QCamera.CaptureVideo)

        mode = QCamera.CaptureStillImage
        supported = self.camera.isCaptureModeSupported(mode)
        self.ui.checkStillImage.setChecked(supported)  #支持拍照

        supported = self.camera.isCaptureModeSupported(QCamera.CaptureVideo)
        self.ui.checkVideo.setChecked(supported)  #支持视频录制

        supported = self.camera.exposure().isAvailable()
        self.ui.checkExposure.setChecked(supported)  #支持曝光补偿

        supported = self.camera.focus().isAvailable()
        self.ui.checkFocus.setChecked(supported)  #支持变焦

        self.camera.stateChanged.connect(self.do_cameraStateChanged)

    def __iniImageCapture(self):  ##创建 QCameraImageCapture对象
        self.capturer = QCameraImageCapture(self.camera)
        settings = QImageEncoderSettings()  #拍照设置
        settings.setCodec("image/jpeg")  #设置抓图图形编码
        settings.setResolution(640, 480)  #分辨率
        settings.setQuality(QMultimedia.HighQuality)  #图片质量
        self.capturer.setEncodingSettings(settings)

        self.capturer.setBufferFormat(QVideoFrame.Format_Jpeg)  #缓冲区格式

        if self.ui.chkBoxSaveToFile.isChecked():
            dest = QCameraImageCapture.CaptureToFile  #保存到文件
        else:
            dest = QCameraImageCapture.CaptureToBuffer  #保存到缓冲区
        self.capturer.setCaptureDestination(dest)  #保存目标

        self.capturer.readyForCaptureChanged.connect(self.do_imageReady)

        self.capturer.imageCaptured.connect(self.do_imageCaptured)

        self.capturer.imageSaved.connect(self.do_imageSaved)

##  ==============event处理函数==========================

##  ==========由connectSlotsByName()自动连接的槽函数============

    @pyqtSlot(bool)  ##设置保存方式
    def on_chkBoxSaveToFile_clicked(self, checked):
        if checked:
            dest = QCameraImageCapture.CaptureToFile  #保存到文件
        else:
            dest = QCameraImageCapture.CaptureToBuffer  #保存到缓冲区
        self.capturer.setCaptureDestination(dest)  #保存目标

    @pyqtSlot()  ##拍照
    def on_actCapture_triggered(self):
        QSound.play("shutter.wav")  #播放快门音效
        self.camera.searchAndLock()  #快门半按下时锁定摄像头参数
        self.capturer.capture()  #拍照
        self.camera.unlock()  #快门按钮释放时解除锁定

    @pyqtSlot()  ##打开摄像头
    def on_actStartCamera_triggered(self):
        self.camera.start()

    @pyqtSlot()  ##关闭摄像头
    def on_actStopCamera_triggered(self):
        self.camera.stop()

    ##  =============自定义槽函数===============================
    def do_cameraStateChanged(self, state):  ##摄像头状态变化
        if (state == QCamera.UnloadedState):
            self.__LabCameraState.setText("摄像头state: UnloadedState")
        elif (state == QCamera.LoadedState):
            self.__LabCameraState.setText("摄像头state: LoadedState")
        elif (state == QCamera.ActiveState):
            self.__LabCameraState.setText("摄像头state: ActiveState")

        self.ui.actStartCamera.setEnabled(state != QCamera.ActiveState)
        self.ui.actStopCamera.setEnabled(state == QCamera.ActiveState)

    def do_imageReady(self, ready):  ##是否可以拍照了
        self.ui.actCapture.setEnabled(ready)

    def do_imageCaptured(self, imageID, preview):  ##图片被抓取到内存
        #preview是 QImage
        H = self.ui.LabImage.height()
        W = self.ui.LabImage.width()

        scaledImage = preview.scaled(W, H, Qt.KeepAspectRatio,
                                     Qt.SmoothTransformation)
        self.ui.LabImage.setPixmap(QPixmap.fromImage(scaledImage))
        self.__LabImageID.setText("图片文件ID:%d" % imageID)
        self.__LabImageFile.setText("图片保存为: ")

    def do_imageSaved(self, imageID, fileName):  ##图片被保存
        self.__LabImageID.setText("图片文件ID:%d" % imageID)
        self.__LabImageFile.setText("图片保存为: " + fileName)
Example #3
0
def main():
    app = QApplication(
        sys.argv
    )  # must be called in order to be able to use all the stuff below(!)
    print("The application is executed on: %s" % app.platformName())
    l_cameras = QCameraInfo.availableCameras()
    if len(l_cameras) == 0:
        print("ERROR: no cameras found")
        sys.exit(-1)
    else:
        print("INFO: found %i camera(s)" % len(l_cameras))
        print()

    for i_idx, oc_caminfo in enumerate(l_cameras):
        # QCameraInfo - derived properties
        print("Camera #%i:" % i_idx)
        print("\t deviceName: %s" % oc_caminfo.deviceName())
        print("\t description: %s" % oc_caminfo.description())
        print("\t isNull: %s" % oc_caminfo.isNull())
        print("\t orientation: %s" % oc_caminfo.orientation())
        print("\t position: %s" % oc_caminfo.position())

        # QCamera - derived properties
        oc_camera = QCamera(i_idx)
        camera_sync_load_and_start(oc_camera)

        oc_camera_exposure = oc_camera.exposure()
        print("\t captureMode: %s" % captureMode2str(oc_camera.captureMode()))
        print("\t exposure:")
        print("\t\t isAvailabe: %s" % oc_camera_exposure.isAvailable())
        if oc_camera_exposure.isAvailable():
            print("\t\t aperture: %s" % oc_camera_exposure.aperture())
            # TODO test this, add more entries

        oc_camera_focus = oc_camera.focus()
        print("\t focus:")
        print("\t\t isAvailabe: %s" % oc_camera_focus.isAvailable())
        if oc_camera_focus.isAvailable():
            print("\t\t aperture: %f" % oc_camera_focus.digitalZoom())
            # TODO test this, add more entries

        oc_cam_img_proc = oc_camera.imageProcessing()
        print("\t imageProcessing:")
        print("\t\t isAvailabe: %s" % oc_cam_img_proc.isAvailable())
        if oc_cam_img_proc.isAvailable():
            print("\t\t brightness: %f" % oc_cam_img_proc.brightness())
            print("\t\t contrast: %f" % oc_cam_img_proc.contrast())
            print("\t\t denoisingLevel: %f" % oc_cam_img_proc.denoisingLevel())
            print("\t\t manualWhiteBalance: %f" %
                  oc_cam_img_proc.manualWhiteBalance())
            print("\t\t saturation: %f" % oc_cam_img_proc.saturation())
            print("\t\t sharpeningLevel: %f" %
                  oc_cam_img_proc.sharpeningLevel())

        print("\t isVideoCaptureSupported: %s" %
              oc_camera.isCaptureModeSupported(QCamera.CaptureVideo))
        print("\t lockStatus: %s" % lockStatus2str(oc_camera.lockStatus()))
        print("\t requestedLocks: %s" %
              lockType2str(oc_camera.requestedLocks()))
        print("\t state: %s" % state2str(oc_camera.state()))
        print("\t status: %s" % status2str(oc_camera.status()))
        print("\t supportedLocks: %s" %
              lockType2str(oc_camera.supportedLocks()))
        print(
            "\t supportedViewfinderFrameRateRanges: %s" %
            frameRateRange2str(oc_camera.supportedViewfinderFrameRateRanges()))
        print("\t supportedViewfinderPixelFormats: %s" %
              repr(oc_camera.supportedViewfinderPixelFormats()))
        print("\t supportedViewfinderResolutions: \n\t\t%s" %
              frameResolution2str(oc_camera.supportedViewfinderResolutions()))
        print("\t len(supportedViewfinderSettings): %s" %
              len(oc_camera.supportedViewfinderSettings()))

        # QCameraViewfinderSettings - derived properties
        oc_vf_settings = oc_camera.viewfinderSettings()
        if oc_vf_settings.isNull():
            print("\t viewfinderSettings: not supported")
            camera_sync_stop_and_unload(oc_camera)
            print()
            continue
        print("\t maximumFrameRate: %f" % oc_vf_settings.maximumFrameRate())
        print("\t minimumFrameRate: %f" % oc_vf_settings.minimumFrameRate())
        print("\t resolution: %s" %
              frameResolution2str([oc_vf_settings.resolution()]))
        # TODO the rest of methods...
        camera_sync_stop_and_unload(oc_camera)
        print()