Exemplo n.º 1
0
class QExampleLabel(QLabel):
    def __init__(self, parentQWidget=None):
        super(QExampleLabel, self).__init__(parentQWidget)
        self.initUI()

    def initUI(self):
        self.setPixmap(QtGui.QPixmap('input.png'))

    def mousePressEvent(self, eventQMouseEvent):
        self.originQPoint = eventQMouseEvent.pos()
        self.currentQRubberBand = QRubberBand(QRubberBand.Rectangle, self)
        self.currentQRubberBand.setGeometry(
            QtCore.QRect(self.originQPoint, QtCore.QSize()))
        self.currentQRubberBand.show()

    def mouseMoveEvent(self, eventQMouseEvent):
        self.currentQRubberBand.setGeometry(
            QtCore.QRect(self.originQPoint,
                         eventQMouseEvent.pos()).normalized())

    def mouseReleaseEvent(self, eventQMouseEvent):
        self.currentQRubberBand.hide()
        currentQRect = self.currentQRubberBand.geometry()
        self.currentQRubberBand.deleteLater()
        cropQPixmap = self.pixmap().copy(currentQRect)
        cropQPixmap.save('output.png')
class QImageEdit(QLabel):
    def __init__(self, parentQWidget=None):
        super(QImageEdit, self).__init__(parentQWidget)
        self.rubberBand = None
        self.move_rubberBand = False
        self.rubberBand_offset = None
        self.originPoint = None

    def setImage(self, image: QPixmap):
        self.setPixmap(image)

    def getImage(self) -> QPixmap:
        if self.rubberBand is not None:
            currentRect = self.rubberBand.geometry()
            return self.pixmap().copy(currentRect)
        else:
            return self.pixmap()

    def clear(self):
        super(QImageEdit, self).clear()
        if self.rubberBand is not None:
            self.rubberBand.deleteLater()
        self.rubberBand = None
        self.move_rubberBand = False
        self.rubberBand_offset = None
        self.originPoint = None

    def mousePressEvent(self, event):
        self.originPoint = event.pos()

        if self.rubberBand is None:
            self.rubberBand = QRubberBand(QRubberBand.Rectangle, self)
            self.rubberBand.setGeometry(QRect(self.originPoint, QSize()))
            self.rubberBand.show()
        else:
            if self.rubberBand.geometry().contains(self.originPoint):
                self.rubberBand_offset = \
                    self.originPoint - self.rubberBand.pos()
                self.move_rubberBand = True
            else:
                self.rubberBand.hide()
                self.rubberBand.deleteLater()
                self.rubberBand = None
                self.move_rubberBand = False
                self.rubberBand_offset = None
                self.mousePressEvent(event)

    def mouseMoveEvent(self, event):
        newPoint = event.pos()
        if self.move_rubberBand:
            self.rubberBand.move(newPoint - self.rubberBand_offset)
        else:
            self.rubberBand.setGeometry(
                QRect(self.originPoint, newPoint).normalized())

    def mouseReleaseEvent(self, event):
        self.move_rubberBand = False
Exemplo n.º 3
0
class QMainLabel(QLabel):
    def __init__(self, parentQWidget):
        super(QMainLabel, self).__init__(parentQWidget)
        self.original_image_pixmap = None
        self.original_mask_pixmap = None
        self.target_size = self.parent().main_label_size

    def set_size(self, size):
        self.target_size = size

    def load_pixmap(self, image, mask=None):
        self.original_image_pixmap = QPixmap(image)

        if mask:
            self.original_mask_pixmap = QPixmap(mask)
            combo = self.merge_image_mask(self.original_image_pixmap,
                                          self.original_mask_pixmap)
            self.setPixmap(combo)
            return

        self.setPixmap(self.original_image_pixmap)

    def merge_image_mask(self, image, mask):

        print(type(image), type(mask))

        if type(image) == QPixmap and type(mask) == QPixmap:
            pil_image = ImageQt.fromqpixmap(image)
            pil_mask = ImageQt.fromqpixmap(mask)
        else:
            pil_image = image
            pil_mask = mask

        np_image = np.array(pil_image)
        np_mask = np.array(pil_mask)

        print(np_image.shape, np_mask.shape)

        prob = np.float32(np_mask) / 255.0
        np_combo = np.uint8(np_image * (1 - prob) +
                            np_mask * prob * np.array([[[0., 1., 0.]]]))

        pil_combo = Image.fromarray(np_combo)
        combo = ImageQt.toqpixmap(pil_combo)

        return combo

    def restore_original(self):
        print('Ctrl+Z')

        image = self.original_image_pixmap
        mask = self.original_mask_pixmap

        if image and mask:
            image = self.merge_image_mask(image, mask)

        self.setPixmap(image)

    def mousePressEvent(self, eventQMouseEvent):
        self.originQPoint = eventQMouseEvent.pos()
        self.currentQRubberBand = QRubberBand(QRubberBand.Rectangle, self)
        self.currentQRubberBand.setGeometry(QRect(self.originQPoint, QSize()))
        self.currentQRubberBand.show()

    def mouseMoveEvent(self, eventQMouseEvent):
        self.currentQRubberBand.setGeometry(
            QRect(self.originQPoint, eventQMouseEvent.pos()).normalized())

    def mouseReleaseEvent(self, eventQMouseEvent):
        self.currentQRubberBand.hide()
        currentQRect = self.currentQRubberBand.geometry()
        self.currentQRubberBand.deleteLater()
        cropQPixmap = self.pixmap().copy(currentQRect)
        # cropQPixmap.save('output.png')

        crop_PIL = ImageQt.fromqpixmap(cropQPixmap)
        crop_PIL = pad_to_square(crop_PIL, self.target_size)
        cropQPixmap = ImageQt.toqpixmap(crop_PIL)
        self.setPixmap(cropQPixmap)
Exemplo n.º 4
0
class ImageViewer(QLabel):
    def __init__(self):
        super(ImageViewer, self).__init__()
        self.crop = Signal()
        #pixmap = QPixmap(640, 640)
        pixmap = QPixmap()
        self.setPixmap(pixmap)

        self.first_x, self.first_y = None, None
        self.last_x, self.last_y = None, None
        self.pen_color = QColor('#000000')
        self.scaleFactor = 0.0
        self.setBackgroundRole(QPalette.Base)
        #self.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored)
        #self.setScaledContents(True)

        #self.setGeometry(QRect(110, 550, 640, 640))
        self.setText("Feature")
        self.setAlignment(Qt.AlignTop | Qt.AlignLeft)
        #self.setAlignment(Qt.AlignCenter)
        self.setWordWrap(False)
        #self.setFixedSize(640,640)
        self.createActions()
        self.show()
        #self.showMaximized()

    def setImage(self, q_img):
        self.setPixmap(q_img)
        self.scaleFactor = 1.0
        #self.fitToWindowAct.setEnabled(True)
        self.updateActions()

        if not self.fitToWindowAct.isChecked():
            self.adjustSize()

    def open(self):
        fileName, _ = QFileDialog.getOpenFileName(self, "Open File",
                                                  QDir.currentPath())
        if fileName:
            image = QImage(fileName)
            if image.isNull():
                QMessageBox.information(self, "Image Viewer",
                                        "Cannot load %s." % fileName)
                return

            self.setPixmap(QPixmap.fromImage(image))
            self.scaleFactor = 1.0

            self.fitToWindowAct.setEnabled(True)
            self.updateActions()

            if not self.fitToWindowAct.isChecked():
                self.adjustSize()

    def zoomIn(self):
        self.scaleImage(1.25)

    def zoomOut(self):
        self.scaleImage(0.8)

    def normalSize(self):
        self.adjustSize()
        self.scaleFactor = 1.0

    def fitToWindow(self):
        fitToWindow = self.fitToWindowAct.isChecked()
        self.scrollArea.setWidgetResizable(fitToWindow)
        if not fitToWindow:
            self.normalSize()

        self.updateActions()

    def createActions(self):
        self.openAct = QAction("&Open...",
                               self,
                               shortcut="Ctrl+O",
                               triggered=self.open)

        self.zoomInAct = QAction("Zoom &In (25%)",
                                 self,
                                 shortcut="Ctrl++",
                                 enabled=False,
                                 triggered=self.zoomIn)

        self.zoomOutAct = QAction("Zoom &Out (25%)",
                                  self,
                                  shortcut="Ctrl+-",
                                  enabled=False,
                                  triggered=self.zoomOut)

        self.normalSizeAct = QAction("&Normal Size",
                                     self,
                                     shortcut="Ctrl+S",
                                     enabled=False,
                                     triggered=self.normalSize)

        self.fitToWindowAct = QAction("&Fit to Window",
                                      self,
                                      enabled=False,
                                      checkable=True,
                                      shortcut="Ctrl+F",
                                      triggered=self.fitToWindow)

    def updateActions(self):
        self.zoomInAct.setEnabled(not self.fitToWindowAct.isChecked())
        self.zoomOutAct.setEnabled(not self.fitToWindowAct.isChecked())
        self.normalSizeAct.setEnabled(not self.fitToWindowAct.isChecked())

    def scaleImage(self, factor):
        self.scaleFactor *= factor
        self.resize(self.scaleFactor * self.pixmap().size())
        self.zoomInAct.setEnabled(self.scaleFactor < 3.0)
        self.zoomOutAct.setEnabled(self.scaleFactor > 0.333)

    def mousePressEvent(self, eventQMouseEvent):
        self.originQPoint = self.mapFrom(self, eventQMouseEvent.pos())
        self.first_x = int(eventQMouseEvent.x())
        self.first_y = int(eventQMouseEvent.y())
        self.currentQRubberBand = QRubberBand(QRubberBand.Rectangle, self)
        self.currentQRubberBand.setGeometry(QRect(self.originQPoint, QSize()))
        self.currentQRubberBand.show()

    def mouseMoveEvent(self, eventQMouseEvent):
        self.x = int(eventQMouseEvent.x())
        self.y = int(eventQMouseEvent.y())
        text1 = str(self.x)
        text2 = str(self.y)
        p = self.mapToGlobal(eventQMouseEvent.pos())
        #QToolTip.showText(eventQMouseEvent.pos() , "X: "+text1+" "+"Y: "+text2,self)
        QToolTip.showText(p, "X: " + text1 + " " + "Y: " + text2, self)
        # print ('mouse QToolTip 1') 전체장에서의 위젯 시작점의 좌표가 오리진 포인트가 되어야 함.
        '''
        if self.currentQRubberBand.isVisible():
            self.currentQRubberBand.setGeometry(QRect(self.originQPoint, eventQMouseEvent.pos()).normalized() & self.pixmap().rect())
        '''
        pos = self.mapFromGlobal(self.mapToGlobal(eventQMouseEvent.pos()))
        #QToolTip.showText(eventQMouseEvent.pos(), "X: {} Y: {}".format(p.x(), p.y()), self)
        if self.currentQRubberBand.isVisible() and self.pixmap() is not None:
            self.currentQRubberBand.setGeometry(
                QRect(self.originQPoint, pos).normalized() & self.rect())

    def mouseReleaseEvent(self, eventQMouseEvent):
        self.last_x = int(eventQMouseEvent.x())
        self.last_y = int(eventQMouseEvent.y())
        '''
        self.currentQRubberBand.hide()
        currentQRect = self.currentQRubberBand.geometry()
        self.currentQRubberBand.deleteLater()
        if self.pixmap() is not None:
            tr = QTransform()
            if self.fitToWindowAct.isChecked():
                tr.scale(self.pixmap().width() / self.scrollArea.width(),
                         self.pixmap().height() / self.scrollArea.height())
            else:
                tr.scale(1 / self.scaleFactor, 1 / self.scaleFactor)
            r = tr.mapRect(currentQRect)
            cropQPixmap = self.pixmap().copy(r)
            cropQPixmap.save('output.png')
        '''

        self.currentQRubberBand.hide()
        currentQRect = self.currentQRubberBand.geometry()
        self.currentQRubberBand.deleteLater()
        cropQPixmap = self.pixmap().copy(currentQRect)
        #size = cropQPixmap.size()
        # 직접변환 해서 저장하는 코드... 나중에
        #s = cropQPixmap.bits().asstring(size.width() * size.height() * image.depth() // 8)  # format 0xffRRGGBB
        #arr = np.fromstring(s, dtype=np.uint8).reshape((size.height(), size.width(), cropQPixmap.depth() // 8))
        #new_image = Image.fromarray(array)
        cropQPixmap.save('output.png')
        img = cv2.imread("output.png", cv2.IMREAD_COLOR)
        h, w = self.cut_imgSize()
        self.crop.cut_signal.emit(img, h, w)

    def cut_imgSize(self):
        h = abs(self.last_y - self.first_y)
        w = abs(self.last_x - self.first_x)
        return h, w
Exemplo n.º 5
0
class ImageDisplay(QGraphicsScene):
    """
    A class to control the image display in the IPView GUI.
    """
    # used to inform mouse event methods which button type is desired (i.e. mouse move or release)
    CROP_IMAGE = Qt.LeftButton
    PIXEL_FETCH = Qt.RightButton
    IMAGE_REVERT = 'PASS'

    ####################################################################################################################
    def __init__(self, ui: ipview_ui.IPViewWindow):
        """
        """
        self.ui = ui
        super(ImageDisplay, self).__init__()
        # self.__scene = QGraphicsScene()
        self.ui.image_display.setScene(self)
        self.__q_graphics_view = self.ui.image_display

        # image currently on display
        self.__displayed_image = None
        self.__displayed_image_orig = None

        # data members reserved for mouse events and the sharing of data between override methods.
        self.__orig_pos_scene = None
        self.__orig_pos_screen = None
        self.__current_rubber_band = None
        self.__cropped_image_rect = None
        self.__button_clicked_type = None

        self.stream_display = StreamDisplay.StreamDisplay(ui=self.ui)

    ####################################################################################################################
    def next_image(self) -> None:
        """
        Method for a signal from the next push button.
        """
        image = self.ui.app_data.get_next_image()
        self.__displayed_image_orig = image
        self.__display_image(image=image)

        return

    ####################################################################################################################
    def previous_image(self) -> None:
        """
        Method for a signal from the previous push button.
        """
        image = self.ui.app_data.get_previous_image()
        self.__displayed_image_orig = image
        self.__display_image(image=image)

        return

    ####################################################################################################################
    def clear_display(self) -> None:
        """
         Method to clear the image display.
        """
        self.clear()
        self.ui.image_display.show()
        self.__displayed_image = None  # reset image held in object
        self.__displayed_image_orig = None  # reset original image held in object
        self.__cropped_image_rect = None
        self.__button_clicked_type = None

        return

    ####################################################################################################################
    def get_displayed_image(self) -> im.Image:
        """
        :return: Image currently on display.
        """
        return self.__displayed_image

    ####################################################################################################################
    def mousePressEvent(self, event: QGraphicsSceneMouseEvent):
        """
        Override method of a mouse click event in QGraphicsView.
        - Left button provides the cropping feature.
        - Right button provides the pixel value.
        """
        if self.__displayed_image is None:
            return

        xy = event.scenePos().toPoint()

        height = self.ui.image_display.sceneRect().height()
        width = self.ui.image_display.sceneRect().width()

        if event.button() == ImageDisplay.CROP_IMAGE:
            self.__button_clicked_type = ImageDisplay.CROP_IMAGE

            # cursor location
            self.__orig_pos_scene = xy
            self.__orig_pos_screen = event.screenPos()

            # rubber band for zoom feature
            self.__current_rubber_band = QRubberBand(QRubberBand.Rectangle)
            self.__current_rubber_band.setGeometry(
                QRect(self.__orig_pos_screen, self.__orig_pos_screen))
            self.__current_rubber_band.show()

        elif event.button() == ImageDisplay.PIXEL_FETCH:
            self.__button_clicked_type = ImageDisplay.PIXEL_FETCH

            # return if click is not in image scene
            if xy.x() < 0 or xy.x() >= width or xy.y() < 0 or xy.y() >= height:
                return

            self.stream_display.append_row(
                'Pixel: row[{0:.2f}], col[{1:.2f}]'.format(xy.y(), xy.x()))

        return

    ####################################################################################################################
    def mouseMoveEvent(self, event: QGraphicsSceneMouseEvent) -> None:
        """
        Override method to move rubber band while mouse button is pressed.
        """
        if self.__button_clicked_type == ImageDisplay.CROP_IMAGE:
            xy = event.screenPos()
            current_pos_screen = QPoint(int(xy.x()), int(xy.y()))
            q_rect = self.__get_q_rect_from_corners(
                corner_one=self.__orig_pos_screen,
                corner_two=current_pos_screen,
                scene_coordinates=False)
            self.__current_rubber_band.setGeometry(q_rect)

        return

    ####################################################################################################################
    def mouseReleaseEvent(self, event: QGraphicsSceneMouseEvent) -> None:
        """
        Override method to complete crop of image.
        """
        if self.__button_clicked_type == ImageDisplay.CROP_IMAGE:
            self.__current_rubber_band.hide()
            self.__cropped_image_rect = self.__get_q_rect_from_corners(
                corner_one=self.__orig_pos_scene,
                corner_two=event.scenePos().toPoint(),
                scene_coordinates=True)
            self.__crop_info_to_stream()
            self.__current_rubber_band.deleteLater()
            cropped_image = self.__displayed_image.copy(
                self.__cropped_image_rect)
            self.__display_image(image=cropped_image)

        return

    ####################################################################################################################
    def mouseDoubleClickEvent(self, event: QGraphicsSceneMouseEvent):
        """
        Override method to display original image.
        """
        self.__button_clicked_type = ImageDisplay.IMAGE_REVERT
        self.__display_image(image=self.__displayed_image_orig)
        self.stream_display.clear_text()
        self.stream_display.append_row("Image reverted to original")

        return

    ####################################################################################################################
    def __display_image(self, image: im.Image) -> None:
        """
        """
        if image is not None:
            self.clear()
            self.__displayed_image = image  # set reference to image in object
            self.addPixmap(QPixmap.fromImage(self.__displayed_image))
            self.ui.image_display.setSceneRect(
                QRectF(self.__displayed_image.rect()))

            # ensures scene rectangle (rect) fits in view port.
            self.ui.image_display.fitInView(self.ui.image_display.sceneRect(),
                                            Qt.KeepAspectRatio)
            self.ui.image_display.show()

        return

    ####################################################################################################################
    def __get_q_rect_from_corners(self,
                                  corner_one: QPoint,
                                  corner_two: QPoint,
                                  scene_coordinates: bool = False) -> QRect:
        """
        Method to return QRect box compatible with image indexing. The need for this function is to allow capabilities
        of zoom to be captured from a box creation in any direction, instead of forcing an upper-left to lower-right
        box creation.
        :param corner_one: a corner of either screen or scene
        :param corner_two: a corner opposite of corner_one
        :param scene_coordinates: True if corners are in scene coordinates. NOTE: If they are, QRect returned will be
            within scene QRect.
        :return: QRect in the format (QPoint [upper-left], QPoint[lower-right]) in input coordinates.
        Note: coordinate system is row -> y, col -> x
        """
        row_1 = corner_one.y()
        col_1 = corner_one.x()
        row_2 = corner_two.y()
        col_2 = corner_two.x()

        row_min = min(row_1, row_2)
        row_max = max(row_1, row_2)
        col_min = min(col_1, col_2)
        col_max = max(col_1, col_2)

        # force corners to be within image if corners are in scene coordinates.
        if scene_coordinates:
            height = self.ui.image_display.sceneRect().height()
            width = self.ui.image_display.sceneRect().width()

            if row_min < 0:
                row_min = 0
            if col_min < 0:
                col_min = 0
            if row_max >= height:
                row_max = height - 1
            if col_max >= width:
                col_max = width - 1

        upper_left = QPoint(col_min, row_min)
        lower_right = QPoint(col_max, row_max)

        return QRect(upper_left, lower_right)

    ####################################################################################################################
    def __crop_info_to_stream(self) -> None:
        """
        Method to write image crop information to stream.
        """
        self.stream_display.append_row('Image Cropped, New Parameters: ')
        self.stream_display.append_row(
            'Rows: {0:.2f}, Columns: {1:.2f}'.format(
                self.__cropped_image_rect.height(),
                self.__cropped_image_rect.width()))