PyQt5之QGraphics 011 QGraphicsItem之绘画OpenCV contours

QPainterPath可以画出各种各样的图形,以下就是画OpenCV的findcontours的轮廓线。

左上角显示区域所有contours的数量。

先用findContours找到轮廓线,之后就可以用moveTo一点一点画出来。代码如下:

"""
有趣的事情
没有结束
2020/4/6 15:53
"""
from PyQt5.QtWidgets import (QApplication, QGraphicsItem, QGraphicsScene, QGraphicsView,
                             QPushButton, QLabel, QDialog, QHBoxLayout, QVBoxLayout)
from PyQt5.QtGui import (QBrush, QPen, QPixmap, QPicture, QImage, QPainterPath)
from PyQt5.QtCore import (QPoint, QPointF, QLine, QLineF, QRect, QRectF, Qt)
import numpy as np
import cv2 as cv
import random


class Shape(QGraphicsItem):
    def __init__(self):
        super(Shape, self).__init__()
        self.path = QPainterPath()
        self.ROIx1 = 20
        self.ROIy1 = 30
        self.ROIx2 = 200
        self.ROIy2 = 300
        self.indexStr = "0"
        self.cvimage = cv.imread("d:/pic/lena.jpg", cv.IMREAD_GRAYSCALE)
        width, height = self.cvimage.shape[0:2]
        self.w = width
        self.h = height
        self.setContours()

    def updateCountour(self, x, y):
        if ((self.ROIx1 + x) < 10) | ((self.ROIy1 + y) < 10) | \
                ((self.ROIx2 + x) > self.h - 10) | ((self.ROIy2 + y) > self.w - 10):
            print("out!")
            return
        self.ROIx1 += x
        self.ROIy1 += y
        self.ROIx2 += x
        self.ROIy2 += y
        self.path = QPainterPath()
        self.prepareGeometryChange()
        self.setContours()

    def setContours(self):
        imgROI = self.cvimage[self.ROIx1:self.ROIx2, self.ROIy1:self.ROIy2]
        imgBlur = cv.blur(imgROI, (3, 3))
        ret, thresh = cv.threshold(imgBlur, 127, 255, 0)
        imgCanny = cv.Canny(thresh, 120, 120)
        contours, hierarchy = cv.findContours(imgCanny, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)

        if len(contours) < 1:
            exit(1)

        imgDrawEx = np.empty((self.w, self.h, 3), np.uint8)
        imgDrawEx[:] = 0
        imgDraw = imgDrawEx[self.ROIx1:self.ROIx2, self.ROIy1:self.ROIy2]

        count = 0
        index = []
        for cnt in contours:
            if cv.arcLength(cnt, True) > 30:
                count += 1
                cv.drawContours(imgDraw, [cnt], -1,
                                (random.randint(100, 255), random.randint(100, 255), random.randint(100, 255)), 1)
                index.append(cnt)

        if len(index) < 1:
            exit(1)

        self.indexStr = str(count)

        contoursCount = len(index)

        for selectIndex in range(contoursCount):
            if len(index[selectIndex]) < 1:
                exit(1)

            self.path.moveTo(index[selectIndex][0][0][0]+self.ROIy1, index[selectIndex][0][0][1]+self.ROIx1)
            for i in index[selectIndex]:
                self.path.lineTo(i[0][0]+self.ROIy1, i[0][1]+self.ROIx1)

    def boundingRect(self):
        return QRectF(0, 0, self.w, self.h)

    def paint(self, painter, option, widget=None):
        image = QImage("d:/pic/lena.jpg")
        painter.drawImage(QPoint(0, 0), image)
        painter.setPen(Qt.NoPen)
        painter.setPen(QPen(Qt.green, 1))
        painter.drawPath(self.path)
        painter.setPen(Qt.NoPen)
        painter.setPen(QPen(Qt.black, 2))
        painter.drawText(QPointF(10, 10), "count: " + self.indexStr)


class Scene(QGraphicsScene):
    def __init__(self):
        super(Scene, self).__init__()


class View(QGraphicsView):
    def __init__(self):
        super(View, self).__init__()


class Form(QDialog):
    def __init__(self, parent=None):
        super(Form, self).__init__(parent)
        self.shape = Shape()
        self.scene = Scene()
        self.scene.addItem(self.shape)
        self.view = View()
        self.view.setScene(self.scene)
        self.button1 = QPushButton(self)
        self.button1.setText("X+")
        self.button2 = QPushButton(self)
        self.button2.setText("X-")
        self.button3 = QPushButton(self)
        self.button3.setText("Y+")
        self.button4 = QPushButton(self)
        self.button4.setText("Y-")
        self.button1.clicked.connect(self.clicked_btn1)
        self.button2.clicked.connect(self.clicked_btn2)
        self.button3.clicked.connect(self.clicked_btn3)
        self.button4.clicked.connect(self.clicked_btn4)
        self.buttonLayout = QHBoxLayout()
        self.buttonLayout.addWidget(self.button1)
        self.buttonLayout.addWidget(self.button2)
        self.buttonLayout.addWidget(self.button3)
        self.buttonLayout.addWidget(self.button4)
        self.layout = QVBoxLayout()
        self.layout.addLayout(self.buttonLayout)
        self.layout.addWidget(self.view)
        self.setLayout(self.layout)
        self.setWindowTitle("Contours")

    def clicked_btn1(self):
        self.shape.updateCountour(10, 0)

    def clicked_btn2(self):
        self.shape.updateCountour(-10, 0)

    def clicked_btn3(self):
        self.shape.updateCountour(0, 10)

    def clicked_btn4(self):
        self.shape.updateCountour(0, -10)


if __name__ == "__main__":
    import sys

    app = QApplication(sys.argv)

    form = Form()
    form.show()

    sys.exit(app.exec_())

通过X+,X-,Y+,Y-控制ROI区域,可以显示我们要的地方的轮廓线。

通过改变ROI可以见到如下效果:

多谢,美美。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值