0

Image does not show up when trying to draw a rectangle over QLabelimage. I want to be able to draw a rectangle over the photo and be able to keep the rectangle/hide it. Here's what I tried after checking suggestions here:

from PyQt5.QtGui import QPixmap, QImage, QPainter, QBrush, QColor
from PyQt5.QtWidgets import QMainWindow, QApplication, QDesktopWidget, QVBoxLayout, QWidget, QLabel
from PyQt5.QtCore import QPoint, QRect
import sys
import cv2


class TestRect(QLabel):
    def __init__(self):
        super().__init__()
        self.begin = QPoint()
        self.end = QPoint()

    def paintEvent(self, event):
        qp = QPainter(self)
        br = QBrush(QColor(100, 10, 10, 40))
        qp.setBrush(br)
        qp.drawRect(QRect(self.begin, self.end))

    def mousePressEvent(self, event):
        self.begin = event.pos()
        self.end = event.pos()
        self.update()

    def mouseMoveEvent(self, event):
        self.end = event.pos()
        self.update()

    def mouseReleaseEvent(self, event):
        self.begin = event.pos()
        self.end = event.pos()
        self.update()


class TestWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.current_image = None
        win_rectangle = self.frameGeometry()
        center_point = QDesktopWidget().availableGeometry().center()
        win_rectangle.moveCenter(center_point)
        self.move(win_rectangle.topLeft())
        self.main_layout = QVBoxLayout()
        self.central_widget = QWidget(self)
        self.test_image()
        self.show()

    def test_image(self):
        self.central_widget.setLayout(self.main_layout)
        self.setCentralWidget(self.central_widget)
        image = TestRect()
        self.main_layout.addWidget(image)
        uploaded = cv2.imread('test.jpg')
        resized = cv2.resize(uploaded, (500, 500))
        height, width = 500, 500
        self.current_image = QImage(resized, height, width, QImage.Format_RGB888)
        image.setPixmap(QPixmap(self.current_image))


if __name__ == '__main__':
    test = QApplication(sys.argv)
    test_window = TestWindow()
    sys.exit(test.exec_())
eyllanesc
  • 235,170
  • 19
  • 170
  • 241

1 Answers1

0

If you override a method without calling the parent's implementation through super then the previous behavior will not be used, and that is what happens in your case: The normal behavior of QLabel is to draw but to override and not to call super it was eliminated . The solution is:

def paintEvent(self, event):
    super().paintEvent(event)
    qp = QPainter(self)
    br = QBrush(QColor(100, 10, 10, 40))
    qp.setBrush(br)
    qp.drawRect(QRect(self.begin, self.end))
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
  • Thanks, is there a way to keep the rectangle(s) drawn on the image showing after the mouse being released and have some control over showing/hiding it? I'm thinking of saving the coordinates and update the image by drawing a rectangle using cv2 but I think there might be a better less complicated way. –  Feb 29 '20 at 18:50
  • @sK500 1) Your question leaves the subject of your question, this time I will point out the solution, 2) Why is it necessary to use opencv? – eyllanesc Feb 29 '20 at 19:00
  • This will serve as an object detection labeling tool where you draw boxes over the objects of interest in the image and save the coordinates. So i'm thinking what if someone misplaced a box, there must be some easy way to fix it and the ability to see the drawn boxes to avoid duplication/hide them if someone wants to see the image without the drawn boxes, that's why I need some control over the drawn rectangles, and i'm not sure how to fix the misplaced rectangle after being drawn by the qpainter so i thought of using cv2 and displaying another cv2 processed image after drawing/hiding the box –  Feb 29 '20 at 19:07
  • @sK500 From what I understand: you are trying to create a SW that has as data images that will be processed by opencv obtaining rectangles that must be shown on the image. Am I correct? If I am correct then the user will not use the mouse to draw the rectangles manually? – eyllanesc Feb 29 '20 at 19:18
  • No, the user will be manually drawing boxes and these boxes are to be left on the screen for the purpose of the user keeping track of the drawn boxes in case of multiple objects in the same image, to get an idea about what I'm talking about here's a similar image labeling tool https://github.com/tzutalin/labelImg and here's my current version of what I'm doing(but still working on it) https://github.com/emadboctorx/image_labeler and here's a video demonstration: https://www.youtube.com/watch?v=_FC6mr7k694&t=5s –  Feb 29 '20 at 19:23
  • @sK500 I suspected it, some time ago I implemented a similar SW and my recommendation is to use Qt GraphicsView with items since the handling will be easier. As the subject moves away from your original question then I will not answer it, but in a few moments I will share a link where is an outline of my SW – eyllanesc Feb 29 '20 at 19:29