如何解决使用 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 举报,一经查实,本站将立刻删除。