예제 #1
0
class CroppableCameraView(QGraphicsView):
    rectChanged = Signal(QRect)
    imageDisplayed = Signal(np.ndarray)
    videoStarted = Signal()
    mouseMoved = Signal(QMouseEvent)
    mousePressed = Signal(QMouseEvent)
    mouseReleased = Signal(QMouseEvent)

    def __init__(self, camera, **settings):
        super(CroppableCameraView, self).__init__()
        self.setRenderHint(QPainter.Antialiasing)
        self.cam = camera
        self.is_live = False
        self._cmin = 0
        self._cmax = None
        self.settings = settings
        self._selecting = False
        self.needs_resize = False
        self.latest_array = None

        self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.scene = QGraphicsScene()
        #self.setFrameStyle(QFrame.NoFrame)
        self.setScene(self.scene)
        self.pixmapitem = self.scene.addPixmap(QPixmap())
        self._uncropped_pixmap = None

        self.setMouseTracking(True)

        self.start = None
        c1 = QColor(0, 100, 220, 150)
        self.c2 = QColor(0, 100, 220, 50)
        self.c3 = QColor(0, 100, 220, 0)
        pen = QPen(c1, 2)

        self.selrect = self.scene.addRect(1, 1, 1, 1, pen, self.c3)
        self.selrect.setZValue(100)
        self.selrect.hide()

    def enable_selecting(self):
        print("Selection enabled")
        self._selecting = True

    def disable_selecting(self):
        self._selecting = False

    def mousePressEvent(self, event):
        if self._selecting:
            print("Mouse pressed")
            if not self.selrect.isVisible():
                self.selrect.show()

            if event.button() == Qt.LeftButton:
                sp = self.mapToScene(event.pos())
                self.start = (sp.x(), sp.y())
                self.selrect.setRect(sp.x(), sp.y(), 0, 0)
                self.selrect.setBrush(self.c2)

        self.mousePressed.emit(event)

    def mouseMoveEvent(self, event):
        if self.start:
            x1, y1 = self.start
            sp = self.mapToScene(event.pos())

            # Image width, height in scene coords
            ir = self.pixmapitem.boundingRect()
            sr = self.pixmapitem.sceneTransform().mapRect(ir)

            size = self.pixmapitem.pixmap().size()
            x2 = max(sr.left(), min(sr.right()-1, sp.x()))
            y2 = max(sr.top(), min(sr.bottom()-1, sp.y()))
            x1, x2 = sorted((x1, x2))
            y1, y2 = sorted((y1, y2))
            self.selrect.setRect(x1, y1, x2-x1, y2-y1)

        self.mouseMoved.emit(event)

    def mouseReleaseEvent(self, event):
        if self.start and event.button() == Qt.LeftButton:
            self.start = None
            self.selrect.setBrush(self.c3)
            self.rectChanged.emit(self.selrect.rect().toRect())

        self.mouseReleased.emit(event)

    def update_rect(self, x, y, w, h):
        self.selrect.setRect(x, y, w, h)
        self.rectChanged.emit(self.selrect.rect().toRect())

    def hideRect(self):
        self.selrect.hide()

    def showRect(self):
        self.selrect.show()

    def setRectVisible(self, visible):
        self.selrect.setVisible(visible)

    def isRectVisible(self):
        return self.selrect.isVisible()

    def rect(self):
        """QRect of the selection in camera coordinates"""
        # selrect in _image_ (pixmap) coordinates
        i_selrect = self.pixmapitem.sceneTransform().inverted()[0].mapRect(self.selrect.rect())
        current_left = self.settings.get('left', 0)
        current_top = self.settings.get('top', 0)
        return i_selrect.toRect().translated(current_left, current_top)

    def crop_to_rect(self):
        was_live = self.is_live
        if was_live:
            self.stop_video()

        self.hideRect()

        rect = self.rect()
        self.settings['left'] = rect.left()
        self.settings['right'] = rect.right()
        self.settings['top'] = rect.top()
        self.settings['bot'] = rect.bottom()

        if was_live:
            self.start_video()
        else:
            if not self._uncropped_pixmap:
                self._uncropped_pixmap = self.pixmapitem.pixmap()
            self.pixmapitem.setPixmap(self._uncropped_pixmap.copy(rect))
            self.setFixedSize(rect.width(), rect.height())

    def uncrop(self):
        was_live = self.is_live
        if was_live:
            self.stop_video()

        for key in ['left', 'right', 'top', 'bot']:
            if key in self.settings:
                del self.settings[key]

        if was_live:
            self.start_video()
        else:
            pixmap = self._uncropped_pixmap
            self.pixmapitem.setPixmap(pixmap)

        ir = self.pixmapitem.boundingRect()
        sr = self.pixmapitem.sceneTransform().mapRect(ir)
        self.scene.setSceneRect(sr)
        self.setFixedSize(sr.width(), sr.height())

    def mapSceneToPixmap(self, pt):
        transform = self.pixmapitem.sceneTransform().inverted()[0]
        return transform.mapRect(pt) if isinstance(pt, (QRect, QRectF)) else transform.map(pt)

    def mapViewToPixmap(self, view_pt):
        scene_pt = self.mapToScene(view_pt)
        return self.mapSceneToPixmap(scene_pt)

    def mapPixmapToScene(self, pixmap_pt):
        transform = self.pixmapitem.sceneTransform()
        map_func = transform.mapRect if isinstance(pixmap_pt, (QRect, QRectF)) else transform.map
        return map_func(pixmap_pt)

    def mapSceneToCamera(self, sc_pt):
        px_pt = self.mapSceneToPixmap(sc_pt)
        return QPoint(px_pt.x() + self.settings.get('left', 0),
                      px_pt.y() + self.settings.get('top', 0))

    def set_image(self, image_arr):
        pixmap = QPixmap(self._array_to_qimage(image_arr))
        if not self.pixmapitem:
            self.pixmapitem = self.scene.addPixmap(pixmap)
        else:
            self.pixmapitem.setPixmap(pixmap)

        if self.needs_resize:
            self._autoresize_viewport()
            self.needs_resize = False

    def _autoresize_viewport(self):
        ir = self.pixmapitem.boundingRect()
        sr = self.pixmapitem.sceneTransform().mapRect(ir)
        self.scene.setSceneRect(sr)
        #self.setFixedSize(sr.width(), sr.height())
        self.resize(sr.width(), sr.height())
        #self.viewport().setMaximumSize(sr.width(), sr.height())
        d = self.style().pixelMetric(QStyle.PM_DefaultFrameWidth)
        self.setMaximumSize(sr.width() + 2*d, sr.height() + 2*d)

    def grab_image(self):
        arr = self.cam.grab_image(**self.settings)
        self.set_image(arr)
        self.latest_array = arr
        self.imageDisplayed.emit(arr)

    def start_video(self):
        timer = QTimer()
        self.timer = timer
        timer.timeout.connect(self._wait_for_frame)
        self.cam.start_live_video(**self.settings)
        timer.start(0)  # Run full throttle
        self.is_live = True
        self.needs_resize = True
        self.videoStarted.emit()

    def stop_video(self):
        self.timer.stop()
        self.cam.stop_live_video()
        self.is_live = False

    def _wait_for_frame(self):
        frame_ready = self.cam.wait_for_frame(timeout='0 ms')
        if frame_ready:
            arr = self.cam.latest_frame(copy=True)
            self.set_image(arr)
            self.latest_array = arr
            self.imageDisplayed.emit(arr)

    def _scale_image(self, arr):
        """Return a bytescaled copy of the image array"""
        if not self._cmax:
            self._cmax = arr.max()  # Set cmax once from first image
        return scipy.misc.bytescale(arr, self._cmin, self._cmax)

    def _lut_scale_image(self, arr):
        if not self._cmax:
            self._cmax = arr.max()
        lut = scipy.misc.bytescale(np.arange(2**16), self._cmin, self._cmax)
        return lut[arr]

    def _create_lut(self, k):
        A = 2**15
        B = 100  # k's scaling factor
        g = lambda i, k: A*((k-B)*i) / ((2*k)*x - (k+B)*A)

    def _array_to_qimage(self, arr):
        bpl = arr.strides[0]
        is_rgb = len(arr.shape) == 3

        if is_rgb and arr.dtype == np.uint8:
            format = QImage.Format_RGB32
            image = QImage(arr.data, self.cam.width, self.cam.height, bpl, format)
        elif not is_rgb and arr.dtype == np.uint8:
            # TODO: Somehow need to make sure data is ordered as I'm assuming
            format = QImage.Format_Indexed8
            image = QImage(arr.data, self.cam.width, self.cam.height, bpl, format)
            self._saved_img = arr
        elif not is_rgb and arr.dtype == np.uint16:
            arr = self._scale_image(arr)
            format = QImage.Format_Indexed8
            w, h = self.cam.width, self.cam.height
            image = QImage(arr.data, w, h, w, format)
            self._saved_img = arr  # Save a reference to keep Qt from crashing
        else:
            raise Exception("Unsupported color mode")

        return image
예제 #2
0
class CroppableCameraView(QGraphicsView):
    rectChanged = Signal(QRect)
    imageDisplayed = Signal(np.ndarray)
    videoStarted = Signal()
    mouseMoved = Signal(QMouseEvent)
    mousePressed = Signal(QMouseEvent)
    mouseReleased = Signal(QMouseEvent)

    def __init__(self, camera, **settings):
        super(CroppableCameraView, self).__init__()
        self.setRenderHint(QPainter.Antialiasing)
        self.cam = camera
        self.is_live = False
        self._cmin = 0
        self._cmax = None
        self.settings = settings
        self._selecting = False
        self.needs_resize = False
        self.latest_array = None

        self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.scene = QGraphicsScene()
        #self.setFrameStyle(QFrame.NoFrame)
        self.setScene(self.scene)
        self.pixmapitem = self.scene.addPixmap(QPixmap())
        self._uncropped_pixmap = None

        self.setMouseTracking(True)

        self.start = None
        c1 = QColor(0, 100, 220, 150)
        self.c2 = QColor(0, 100, 220, 50)
        self.c3 = QColor(0, 100, 220, 0)
        pen = QPen(c1, 2)

        self.selrect = self.scene.addRect(1, 1, 1, 1, pen, self.c3)
        self.selrect.setZValue(100)
        self.selrect.hide()

    def enable_selecting(self):
        print("Selection enabled")
        self._selecting = True

    def disable_selecting(self):
        self._selecting = False

    def mousePressEvent(self, event):
        if self._selecting:
            print("Mouse pressed")
            if not self.selrect.isVisible():
                self.selrect.show()

            if event.button() == Qt.LeftButton:
                sp = self.mapToScene(event.pos())
                self.start = (sp.x(), sp.y())
                self.selrect.setRect(sp.x(), sp.y(), 0, 0)
                self.selrect.setBrush(self.c2)

        self.mousePressed.emit(event)

    def mouseMoveEvent(self, event):
        if self.start:
            x1, y1 = self.start
            sp = self.mapToScene(event.pos())

            # Image width, height in scene coords
            ir = self.pixmapitem.boundingRect()
            sr = self.pixmapitem.sceneTransform().mapRect(ir)

            size = self.pixmapitem.pixmap().size()
            x2 = max(sr.left(), min(sr.right() - 1, sp.x()))
            y2 = max(sr.top(), min(sr.bottom() - 1, sp.y()))
            x1, x2 = sorted((x1, x2))
            y1, y2 = sorted((y1, y2))
            self.selrect.setRect(x1, y1, x2 - x1, y2 - y1)

        self.mouseMoved.emit(event)

    def mouseReleaseEvent(self, event):
        if self.start and event.button() == Qt.LeftButton:
            self.start = None
            self.selrect.setBrush(self.c3)
            self.rectChanged.emit(self.selrect.rect().toRect())

        self.mouseReleased.emit(event)

    def update_rect(self, x, y, w, h):
        self.selrect.setRect(x, y, w, h)
        self.rectChanged.emit(self.selrect.rect().toRect())

    def hideRect(self):
        self.selrect.hide()

    def showRect(self):
        self.selrect.show()

    def setRectVisible(self, visible):
        self.selrect.setVisible(visible)

    def isRectVisible(self):
        return self.selrect.isVisible()

    def rect(self):
        """QRect of the selection in camera coordinates"""
        # selrect in _image_ (pixmap) coordinates
        i_selrect = self.pixmapitem.sceneTransform().inverted()[0].mapRect(
            self.selrect.rect())
        current_left = self.settings.get('left', 0)
        current_top = self.settings.get('top', 0)
        return i_selrect.toRect().translated(current_left, current_top)

    def crop_to_rect(self):
        was_live = self.is_live
        if was_live:
            self.stop_video()

        self.hideRect()

        rect = self.rect()
        self.settings['left'] = rect.left()
        self.settings['right'] = rect.right()
        self.settings['top'] = rect.top()
        self.settings['bot'] = rect.bottom()

        if was_live:
            self.start_video()
        else:
            if not self._uncropped_pixmap:
                self._uncropped_pixmap = self.pixmapitem.pixmap()
            self.pixmapitem.setPixmap(self._uncropped_pixmap.copy(rect))
            self.setFixedSize(rect.width(), rect.height())

    def uncrop(self):
        was_live = self.is_live
        if was_live:
            self.stop_video()

        for key in ['left', 'right', 'top', 'bot']:
            if key in self.settings:
                del self.settings[key]

        if was_live:
            self.start_video()
        else:
            pixmap = self._uncropped_pixmap
            self.pixmapitem.setPixmap(pixmap)

        ir = self.pixmapitem.boundingRect()
        sr = self.pixmapitem.sceneTransform().mapRect(ir)
        self.scene.setSceneRect(sr)
        self.setFixedSize(sr.width(), sr.height())

    def mapSceneToPixmap(self, pt):
        transform = self.pixmapitem.sceneTransform().inverted()[0]
        return transform.mapRect(pt) if isinstance(
            pt, (QRect, QRectF)) else transform.map(pt)

    def mapViewToPixmap(self, view_pt):
        scene_pt = self.mapToScene(view_pt)
        return self.mapSceneToPixmap(scene_pt)

    def mapPixmapToScene(self, pixmap_pt):
        transform = self.pixmapitem.sceneTransform()
        map_func = transform.mapRect if isinstance(pixmap_pt,
                                                   (QRect,
                                                    QRectF)) else transform.map
        return map_func(pixmap_pt)

    def mapSceneToCamera(self, sc_pt):
        px_pt = self.mapSceneToPixmap(sc_pt)
        return QPoint(px_pt.x() + self.settings.get('left', 0),
                      px_pt.y() + self.settings.get('top', 0))

    def set_image(self, image_arr):
        pixmap = QPixmap(self._array_to_qimage(image_arr))
        if not self.pixmapitem:
            self.pixmapitem = self.scene.addPixmap(pixmap)
        else:
            self.pixmapitem.setPixmap(pixmap)

        if self.needs_resize:
            self._autoresize_viewport()
            self.needs_resize = False

    def _autoresize_viewport(self):
        ir = self.pixmapitem.boundingRect()
        sr = self.pixmapitem.sceneTransform().mapRect(ir)
        self.scene.setSceneRect(sr)
        #self.setFixedSize(sr.width(), sr.height())
        self.resize(sr.width(), sr.height())
        #self.viewport().setMaximumSize(sr.width(), sr.height())
        d = self.style().pixelMetric(QStyle.PM_DefaultFrameWidth)
        self.setMaximumSize(sr.width() + 2 * d, sr.height() + 2 * d)

    def grab_image(self):
        arr = self.cam.grab_image(**self.settings)
        self.set_image(arr)
        self.latest_array = arr
        self.imageDisplayed.emit(arr)

    def start_video(self):
        timer = QTimer()
        self.timer = timer
        timer.timeout.connect(self._wait_for_frame)
        self.cam.start_live_video(**self.settings)
        timer.start(0)  # Run full throttle
        self.is_live = True
        self.needs_resize = True
        self.videoStarted.emit()

    def stop_video(self):
        self.timer.stop()
        self.cam.stop_live_video()
        self.is_live = False

    def _wait_for_frame(self):
        frame_ready = self.cam.wait_for_frame(timeout='0 ms')
        if frame_ready:
            arr = self.cam.latest_frame(copy=True)
            self.set_image(arr)
            self.latest_array = arr
            self.imageDisplayed.emit(arr)

    def _scale_image(self, arr):
        """Return a bytescaled copy of the image array"""
        if not self._cmax:
            self._cmax = arr.max()  # Set cmax once from first image
        return scipy.misc.bytescale(arr, self._cmin, self._cmax)

    def _lut_scale_image(self, arr):
        if not self._cmax:
            self._cmax = arr.max()
        lut = scipy.misc.bytescale(np.arange(2**16), self._cmin, self._cmax)
        return lut[arr]

    def _create_lut(self, k):
        A = 2**15
        B = 100  # k's scaling factor
        g = lambda i, k: A * ((k - B) * i) / ((2 * k) * x - (k + B) * A)

    def _array_to_qimage(self, arr):
        bpl = arr.strides[0]
        is_rgb = len(arr.shape) == 3

        if is_rgb and arr.dtype == np.uint8:
            format = QImage.Format_RGB32
            image = QImage(arr.data, self.cam.width, self.cam.height, bpl,
                           format)
        elif not is_rgb and arr.dtype == np.uint8:
            # TODO: Somehow need to make sure data is ordered as I'm assuming
            format = QImage.Format_Indexed8
            image = QImage(arr.data, self.cam.width, self.cam.height, bpl,
                           format)
            self._saved_img = arr
        elif not is_rgb and arr.dtype == np.uint16:
            arr = self._scale_image(arr)
            format = QImage.Format_Indexed8
            w, h = self.cam.width, self.cam.height
            image = QImage(arr.data, w, h, w, format)
            self._saved_img = arr  # Save a reference to keep Qt from crashing
        else:
            raise Exception("Unsupported color mode")

        return image
class Image_Note(QMainWindow, gui_window.Ui_MainWindow):
    def __init__(self, parent=None):
        super(Image_Note, self).__init__(parent)
        self.setupUi(self)
        self.button_browse.clicked.connect(self.browse_file)
        self.button_browse_pdf.clicked.connect(self.browse_pdf_file)

        self.slider.setMinimum(0)
        self.slider.setMaximum(100)
        self.slider.setValue(40)
        self.button_reset.clicked.connect(self.reset)
        self.slider.valueChanged.connect(self.sensitivity_slider)
        self.button_delete.clicked.connect(self.remove_residual_images)
        self.button_save.clicked.connect(self.save_image)
        self.button_pdf_save.clicked.connect(self.save_pdf)
        self.visibility_widgets()

    def visibility_widgets(self, disable: bool = False):
        self.all_widgets = [
            self.button_delete, self.button_pdf_save, self.button_reset,
            self.button_save, self.slider
        ]

        for widget in self.all_widgets:
            widget.setEnabled(disable)
            print(type(widget))

    def sensitivity_slider(self):
        value = self.slider.value()
        print(value)
        self.thumbnail_image = Image.open(self.thumbnail_address)
        self.thumbnail_address_converted = \
            file_handler.filepath_modified_suffix(
                self.thumbnail_address)
        convert_util.convert_sample(self.thumbnail_address,
                                    self.thumbnail_address_converted, value)
        self.load_graphics_image(self.thumbnail_address_converted)

    def reset(self):
        self.slider.setValue(40)
        self.thumbnail_image = Image.open(self.thumbnail_address)
        self.load_graphics_image(self.thumbnail_address)

    def remove_residual_images(self):
        file_handler.remove_file(self.thumbnail_address)
        file_handler.remove_file(self.thumbnail_address_converted)

    def save_image(self):
        value = self.slider.value()
        convert_util.convert_full_image(self.file_address,
                                        self.modified_image_address, value)

    def save_pdf(self):
        import os
        if not os.path.exists(self.modified_image_address):
            self.save_image()
        convert_util.convert_image_to_pdf(
            self.modified_image_address,
            file_handler.change_path_extension(self.modified_image_address,
                                               ".pdf"))

    # def pdf_convert(self):
    #     self.save_image()
    #     convert_util.convert_image_to_pdf(self.modified_image_address,
    #                                       file_handler.change_path_extension(  # noqa
    #                                           self.modified_image_address,
    #                                           ".pdf"))

    def browse_pdf_file(self):
        self.pdf_file_address = QFileDialog.getOpenFileName(
            self, 'Open PDF File')[0]
        # print(self.pdf_file_address[0])
        self.file_address = file_handler.change_path_extension(
            self.pdf_file_address, ".png")
        convert_util.convert_pdf_to_image(self.pdf_file_address,
                                          self.file_address)
        self.process_file()

    def browse_file(self):

        response = QFileDialog.getOpenFileName(self, 'Open Image File')
        self.file_address = response[0]
        if not os.path.exists(self.file_address):
            return
        # return
        self.process_file()

    def process_file(self):
        self.thumbnail_address: str = file_handler.filepath_modified_suffix(
            self.file_address, "_thumbnail")
        self.modified_image_address: str = \
            file_handler.filepath_modified_suffix(
                self.file_address)
        image_handler.save_thumbnail(Image.open(self.file_address),
                                     self.thumbnail_address)
        self.visibility_widgets(True)
        self.load_graphics_image(self.thumbnail_address)

    def load_graphics_image(self, image_address: str):
        self.graphics_scene = QGraphicsScene()
        self.graphics_scene.addPixmap(QPixmap(image_address))
        self.graphicsView.setScene(self.graphics_scene)