微信公眾號:OpenCV開發者聯盟
關注獲取更多計算機視覺與深度學習知識
引言
PyQT5支持的鼠標信號

mouseMoveEventmousePressEventmouseReleaseEventmouseDoubleClickEvent
其中如果想要捕獲鼠標移動(MouseMove)事件必須設置
setMouseTracking(True)才可以實現支持。一個簡單鼠標繪制通常包括三個鼠標事件的處理,分別是:
mousePressEvent鼠標按下 為開始繪制mouseMoveEvent 鼠標移動 繪制中mouseReleaseEvent 鼠標釋放 結束繪制
def mousePressEvent(self, event):def mouseMoveEvent(self, event):def mouseReleaseEvent(self, event):
綜合代碼演示






1class?ImageCanvas(QtWidgets.QWidget):
2????def?__init__(self):
3????????super().__init__()
4????????self.pts?=?[]
5????????self.temp_pts?=?[]
6????????self.start_x?=?-1
7????????self.start_y?=?-1
8????????self.pressed?=?False
9????????self.line_width?=?5
10
11????????#?monitor?key?and?mouse??event...
12????????self.setMouseTracking(True)
13
14????????#?添加菜單
15????????self.save_5_action?=?QtWidgets.QAction("線寬2",?self)
16????????self.save_10_action?=?QtWidgets.QAction("線寬4",?self)
17????????self.save_15_action?=?QtWidgets.QAction("線寬8",?self)
18????????self.clear_action?=?QtWidgets.QAction("清除",?self)
19
20????????self.save_5_action.triggered.connect(self.on_save_5)
21????????self.save_10_action.triggered.connect(self.on_save_10)
22????????self.save_15_action.triggered.connect(self.on_save_15)
23????????self.clear_action.triggered.connect(self.clear_canvas)
24
25????????self.addAction(self.save_5_action)
26????????self.addAction(self.save_10_action)
27????????self.addAction(self.save_15_action)
28????????self.addAction(self.clear_action)
29
30????????#?0?-?圓形,?1?-?矩形,?2?-?直線,?3?-?free-style
31????????self.draw_type?=?0
32????????self.circle?=?[0,?0,?0]
33????????self.box?=?[0,?0,?0,?0]
34????????self.line?=?[0,?0,?0,?0]
35????????#?trick?settings?here!!!
36????????self.setContextMenuPolicy(2)
37
38????def?clear_canvas(self):
39????????self.pts.clear()
40????????self.temp_pts.clear()
41????????self.circle?=?[0,?0,?0]
42????????self.box?=?[0,?0,?0,?0]
43????????self.line?=?[0,?0,?0,?0]
44????????self.repaint()
45
46????def?on_save_5(self,?s):
47????????print(s)
48????????self.line_width?=?2
49
50????def?on_save_10(self,?s):
51????????print(s)
52????????self.line_width?=?4
53
54????def?on_save_15(self,?s):
55????????print(s)
56????????self.line_width?=?8
57
58????def?query_draw_type(self):
59????????if?rbtn1.isChecked():
60????????????self.draw_type?=?0
61????????if?rbtn2.isChecked():
62????????????self.draw_type?=?1
63????????if?rbtn3.isChecked():
64????????????self.draw_type?=?2
65????????if?rbtn4.isChecked():
66????????????self.draw_type?=?3
67
68????def?mousePressEvent(self,?event):
69????????self.query_draw_type()
70????????self.pressed?=?True
71????????self.start_x?=?event.x()
72????????self.start_y?=?event.y()
73????????if?self.draw_type?==?0:
74????????????self.circle?=?[self.start_x,?self.start_y,?0]
75????????if?self.draw_type?==?1:
76????????????self.box?=?[self.start_x,?self.start_y,?0,?0]
77????????if?self.draw_type?==?2:
78????????????self.line?=?[self.start_x,?self.start_y,?0,?0]
79????????if?self.draw_type?==?3:
80????????????self.temp_pts.clear()
81????????????self.temp_pts.append((self.start_x,?self.start_y))
82
83????def?mouseMoveEvent(self,?event):
84????????if?self.pressed?and?self.start_x?>?0?and?self.start_y?>?0:
85????????????x?=?event.x()
86????????????y?=?event.y()
87????????????dx?=?x?-?self.start_x
88????????????dy?=?y?-?self.start_y
89????????????if?self.draw_type?==?0?and?dx?>?0?and?dy?>?0:
90????????????????r?=?int(np.sqrt(dx*dx?+?dy*dy))
91????????????????self.circle?=?[self.start_x,?self.start_y,?r]
92????????????if?self.draw_type?==?1?and?dx?>?0?and?dy?>?0:
93????????????????self.box?=?[self.start_x,?self.start_y,?dx,?dy]
94????????????if?self.draw_type?==?2?and?abs(dx)?>?0?and?abs(dy)?>?0:
95????????????????self.line?=?[self.start_x,?self.start_y,?x,?y]
96????????????if?self.draw_type?==?3:
97????????????????self.temp_pts.append((x,?y))
98????????????self.repaint()
99
100????def?mouseReleaseEvent(self,?event):
101????????x?=?event.x()
102????????y?=?event.y()
103????????dx?=?x?-?self.start_x
104????????dy?=?y?-?self.start_y
105????????if?self.draw_type?==?0?and?dx?>?0?and?dy?>?0:
106????????????r?=?int(np.sqrt(dx?*?dx?+?dy?*?dy))
107????????????self.circle?=?[self.start_x,?self.start_y,?r]
108????????if?self.draw_type?==?1?and?dx?>?0?and?dy?>?0:
109????????????self.box?=?[self.start_x,?self.start_y,?dx,?dy]
110????????if?self.draw_type?==?2?and?abs(dx)?>?0?and?abs(dy)?>?0:
111????????????self.line?=?[self.start_x,?self.start_y,?x,?y]
112????????if?self.draw_type?==?3:
113????????????self.temp_pts.append((x,?y))
114????????????self.pts.append(np.copy(self.temp_pts))
115????????self.pressed?=?False
116????????self.temp_pts.clear()
117????????self.repaint()
118
119????def?paintEvent(self,?event):
120????????painter?=?QtGui.QPainter(self)
121????????painter.fillRect(self.rect(),?QtCore.Qt.black)
122????????pen?=?QtGui.QPen(QtCore.Qt.green,?5,?QtCore.Qt.DashLine)
123????????painter.setPen(pen)
124????????font?=?QtGui.QFont()
125????????font.setBold(True)
126????????font.setPointSizeF(16)
127????????painter.setFont(font)
128????????painter.drawText(QtCore.QPoint(5,?25),?"OpenCV開發者聯盟")
129
130????????pen?=?QtGui.QPen(QtCore.Qt.green,?self.line_width)
131????????painter.setPen(pen)
132????????painter.drawRect(QtCore.QRect(self.box[0],?self.box[1],?self.box[2],?self.box[3]))
133
134????????pen?=?QtGui.QPen(QtCore.Qt.blue,?self.line_width)
135????????painter.setPen(pen)
136????????cx,?cy,?r?=?self.circle
137????????painter.drawEllipse(QtCore.QRect(cx-r,?cy-r,?2*r,?2*r))
138
139????????pen?=?QtGui.QPen(QtCore.Qt.yellow,?self.line_width)
140????????painter.setPen(pen)
141????????painter.drawLine(self.line[0],?self.line[1],?self.line[2],?self.line[3])
142
143????????#?5表示線寬
144????????pen?=?QtGui.QPen(QtCore.Qt.red,?self.line_width,?QtCore.Qt.DashLine)
145????????painter.setPen(pen)
146????????for?c?in?range(0,?len(self.pts),?1):
147????????????one_contours?=?self.pts[c]
148????????????for?i?in?range(0,?len(one_contours)-1,?1):
149????????????????x1?=?one_contours[i][0]
150????????????????y1?=?one_contours[i][1]
151????????????????x2?=?one_contours[i+1][0]
152????????????????y2?=?one_contours[i+1][1]
153????????????????painter.drawLine(x1,?y1,?x2,?y2)
154
155????????for?i?in?range(0,?len(self.temp_pts)?-?1,?1):
156????????????x1?=?self.temp_pts[i][0]
157????????????y1?=?self.temp_pts[i][1]
158????????????x2?=?self.temp_pts[i?+?1][0]
159????????????y2?=?self.temp_pts[i?+?1][1]
160????????????painter.drawLine(x1,?y1,?x2,?y2)掃碼關注
OpenCV開發者聯盟,
專注各種語言的OpenCV開發教程分享
OpenCV周邊開發技術應用!

掃碼查看OpenCV+OpenVIO+Pytorch系統化學習路線圖

?推薦閱讀?
CV全棧開發者說 - 從傳統算法到深度學習怎么修煉
2022入坑深度學習,我選擇Pytorch框架!
Pytorch輕松實現經典視覺任務
教程推薦 | Pytorch框架CV開發-從入門到實戰
OpenCV4 C++學習 必備基礎語法知識三
OpenCV4 C++學習 必備基礎語法知識二
OpenCV4.5.4 人臉檢測+五點landmark新功能測試
OpenCV4.5.4人臉識別詳解與代碼演示
OpenCV二值圖象分析之Blob分析找圓
OpenCV4.5.x DNN + YOLOv5 C++推理
OpenCV4.5.4 直接支持YOLOv5 6.1版本模型推理
OpenVINO2021.4+YOLOX目標檢測模型部署測試
比YOLOv5還厲害的YOLOX來了,官方支持OpenVINO推理