微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用 QPainter 在 QGraphicsView 上拖放点

如何解决使用 QPainter 在 QGraphicsView 上拖放点

我创建了一个简单的 GUI 应用程序,该应用程序在 QGraphicsView显示相机源。我需要使用此视频流上的 4 个点创建一个多边形。到目前为止,我使用 OpenCV 来绘制这些点。但我希望使用 QPainter 来做到这一点。

多边形创建后,用户必须具有从其原始位置drag任何单个点(或者我应该说多边形的角点)和{{1} } 它在其他位置并检索该点新位置的坐标。

代码

drop/place

我想要类似 https://stackoverflow.com/a/52728780/8254422 这个答案的第一部分的内容。唯一的区别是我应该能够移动单个角点,而不是一次移动整个矩形。并且坐标必须按照它们绘制的顺序接收。

是否可以使用 from collections import deque from datetime import datetime import sys from threading import Thread import time import cv2 from PyQt4 import QtCore,QtGui class CameraWidget(QtGui.QGraphicsView): """Independent camera Feed Uses threading to grab IP camera frames in the background @param width - Width of the video frame @param height - Height of the video frame @param stream_link - IP/RTSP/Webcam link @param aspect_ratio - Whether to maintain frame aspect ratio or force into fraame """ def __init__( self,width,height,stream_link=0,aspect_ratio=False,parent=None,deque_size=1,): super(CameraWidget,self).__init__(parent) # Initialize deque used to store frames read from the stream self.deque = deque(maxlen=deque_size) self.screen_width = width self.screen_height = height self.maintain_aspect_ratio = aspect_ratio self.camera_stream_link = stream_link # Flag to check if camera is valid/working self.online = False self.capture = None self.setScene(QtGui.QGraphicsScene(self)) self._pixmap_item = self.scene().addpixmap(QtGui.Qpixmap()) self.all_points = [] self.point = (-1,-1) self.load_network_stream() # Start background frame grabbing self.get_frame_thread = Thread(target=self.get_frame,args=()) self.get_frame_thread.daemon = True self.get_frame_thread.start() # Periodically set video frame to display self.timer = QtCore.QTimer() self.timer.timeout.connect(self.set_frame) self.timer.start(0.5) print("Started camera: {}".format(self.camera_stream_link)) def load_network_stream(self): """Verifies stream link and open new stream if valid""" def load_network_stream_thread(): if self.verify_network_stream(self.camera_stream_link): self.capture = cv2.VideoCapture(self.camera_stream_link) self.online = True self.load_stream_thread = Thread(target=load_network_stream_thread,args=()) self.load_stream_thread.daemon = True self.load_stream_thread.start() def verify_network_stream(self,link): """Attempts to receive a frame from given link""" cap = cv2.VideoCapture(link) if not cap.isOpened(): return False cap.release() return True def get_frame(self): """Reads frame,resizes,and converts image to pixmap""" while True: try: if self.capture.isOpened() and self.online: # Read next frame from stream and insert into deque status,frame = self.capture.read() if status: self.deque.append(frame) else: self.capture.release() self.online = False else: # Attempt to reconnect print("attempting to reconnect",self.camera_stream_link) self.load_network_stream() self.spin(2) self.spin(0.001) except AttributeError: pass def spin(self,seconds): """Pause for set amount of seconds,replaces time.sleep so program doesnt stall""" time_end = time.time() + seconds while time.time() < time_end: QtGui.QApplication.processEvents() def set_frame(self): """Sets pixmap image to video frame""" if not self.online: self.spin(1) return if self.deque and self.online: # Grab latest frame frame = self.deque[-1] if len(self.all_points) <= 4: for n,point in enumerate(self.all_points): cv2.circle(frame,point,5,(0,255),-1) self.frame = cv2.cvtColor(frame,cv2.COLOR_BGR2RGB) h,w,ch = self.frame.shape bytesPerLine = ch * w # Convert to pixmap and set to video frame image = QtGui.QImage(self.frame,h,bytesPerLine,QtGui.QImage.Format_RGB888) pixmap = QtGui.Qpixmap.fromImage(image.copy()) self._pixmap_item.setpixmap(pixmap) self.point = (-1,-1) self.fix_size() def mousepressEvent(self,event): super(CameraWidget,self).mousepressEvent(event) vp = event.pos() it = self.itemAt(vp) if it == self._pixmap_item: sp = self.mapToScene(vp) lp = it.mapFromScene(sp) x = lp.toPoint().x() y = lp.toPoint().y() self.point = (x,y) if len(self.all_points) < 4: self.all_points.append(self.point) def resizeEvent(self,event): self.fix_size() super().resizeEvent(event) def fix_size(self): self.fitInView( self._pixmap_item,QtCore.Qt.KeepAspectRatio if self.maintain_aspect_ratio else QtCore.Qt.IgnoreAspectRatio,) class Window(QtGui.QWidget): def __init__(self,cam=None,parent=None): super(Window,self).__init__(parent) self.showMaximized() self.screen_width = self.width() self.screen_height = self.height() # Create camera widget print("Creating Camera Widget...") self.camera = CameraWidget(self.screen_width,self.screen_height,cam) lay = QtGui.QVBoxLayout(self) lay.setContentsMargins(0,0) lay.setSpacing(0) lay.addWidget(self.camera) camera = 0 #'rtsp://admin:vaaan@123@192.168.1.51/Streaming/Channels/2' if __name__ == "__main__": app = QtGui.QApplication([]) win = Window(camera) sys.exit(app.exec_()) 实现这样的功能

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。