最近写了一个python提取论文图片波形数据的脚本,代码如下。
涉及新知识点:pyautogui键盘移动鼠标,跨模块全局变量使用,cv2局部放大窗口,matplotlib图片在pyQT5lable显示,坐标变换,多线程同时使用。搜索相关关键字去对应代码区看注释就可以了。
gui窗口:
1 # -*- coding: utf-8 -*- 2 3 # Form implementation generated from reading ui file 'caiyagui.ui' 4 # 5 # Created by: PyQt5 UI code generator 5.14.2 6 # 7 # WARNING! All changes made in this file will be lost! 8 9 10 from PyQt5 import QtCore, QtGui, QtWidgets 11 12 13 class Ui_MainWindow(object): 14 def setupUi(self, MainWindow): 15 MainWindow.setObjectName("MainWindow") 16 MainWindow.resize(905, 472) 17 self.centralwidget = QtWidgets.QWidget(MainWindow) 18 self.centralwidget.setObjectName("centralwidget") 19 self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget) 20 self.verticalLayout.setObjectName("verticalLayout") 21 self.label_12 = QtWidgets.QLabel(self.centralwidget) 22 self.label_12.setAlignment(QtCore.Qt.AlignCenter) 23 self.label_12.setObjectName("label_12") 24 self.verticalLayout.addWidget(self.label_12) 25 self.gridLayout = QtWidgets.QGridLayout() 26 self.gridLayout.setObjectName("gridLayout") 27 self.label_6 = QtWidgets.QLabel(self.centralwidget) 28 self.label_6.setObjectName("label_6") 29 self.gridLayout.addWidget(self.label_6, 2, 5, 1, 1) 30 self.lineEdit_7 = QtWidgets.QLineEdit(self.centralwidget) 31 self.lineEdit_7.setObjectName("lineEdit_7") 32 self.gridLayout.addWidget(self.lineEdit_7, 1, 7, 1, 1) 33 self.lineEdit_8 = QtWidgets.QLineEdit(self.centralwidget) 34 self.lineEdit_8.setObjectName("lineEdit_8") 35 self.gridLayout.addWidget(self.lineEdit_8, 2, 4, 1, 1) 36 self.label_2 = QtWidgets.QLabel(self.centralwidget) 37 self.label_2.setObjectName("label_2") 38 self.gridLayout.addWidget(self.label_2, 1, 5, 1, 1) 39 self.lineEdit_2 = QtWidgets.QLineEdit(self.centralwidget) 40 self.lineEdit_2.setObjectName("lineEdit_2") 41 self.gridLayout.addWidget(self.lineEdit_2, 1, 6, 1, 1) 42 self.lineEdit_6 = QtWidgets.QLineEdit(self.centralwidget) 43 self.lineEdit_6.setObjectName("lineEdit_6") 44 self.gridLayout.addWidget(self.lineEdit_6, 1, 4, 1, 1) 45 self.label_3 = QtWidgets.QLabel(self.centralwidget) 46 self.label_3.setObjectName("label_3") 47 self.gridLayout.addWidget(self.label_3, 1, 2, 1, 1) 48 self.lineEdit_3 = QtWidgets.QLineEdit(self.centralwidget) 49 self.lineEdit_3.setObjectName("lineEdit_3") 50 self.gridLayout.addWidget(self.lineEdit_3, 1, 3, 1, 1) 51 self.lineEdit_4 = QtWidgets.QLineEdit(self.centralwidget) 52 self.lineEdit_4.setObjectName("lineEdit_4") 53 self.gridLayout.addWidget(self.lineEdit_4, 2, 6, 1, 1) 54 self.lineEdit_5 = QtWidgets.QLineEdit(self.centralwidget) 55 self.lineEdit_5.setObjectName("lineEdit_5") 56 self.gridLayout.addWidget(self.lineEdit_5, 2, 3, 1, 1) 57 self.lineEdit_9 = QtWidgets.QLineEdit(self.centralwidget) 58 self.lineEdit_9.setObjectName("lineEdit_9") 59 self.gridLayout.addWidget(self.lineEdit_9, 2, 7, 1, 1) 60 self.label_5 = QtWidgets.QLabel(self.centralwidget) 61 self.label_5.setObjectName("label_5") 62 self.gridLayout.addWidget(self.label_5, 2, 2, 1, 1) 63 self.label_7 = QtWidgets.QLabel(self.centralwidget) 64 sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed) 65 sizePolicy.setHorizontalStretch(0) 66 sizePolicy.setVerticalStretch(0) 67 sizePolicy.setHeightForWidth(self.label_7.sizePolicy().hasHeightForWidth()) 68 self.label_7.setSizePolicy(sizePolicy) 69 self.label_7.setAlignment(QtCore.Qt.AlignCenter) 70 self.label_7.setObjectName("label_7") 71 self.gridLayout.addWidget(self.label_7, 0, 4, 1, 1) 72 self.label_8 = QtWidgets.QLabel(self.centralwidget) 73 sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed) 74 sizePolicy.setHorizontalStretch(0) 75 sizePolicy.setVerticalStretch(0) 76 sizePolicy.setHeightForWidth(self.label_8.sizePolicy().hasHeightForWidth()) 77 self.label_8.setSizePolicy(sizePolicy) 78 self.label_8.setAlignment(QtCore.Qt.AlignCenter) 79 self.label_8.setObjectName("label_8") 80 self.gridLayout.addWidget(self.label_8, 0, 3, 1, 1) 81 self.label_9 = QtWidgets.QLabel(self.centralwidget) 82 sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed) 83 sizePolicy.setHorizontalStretch(0) 84 sizePolicy.setVerticalStretch(0) 85 sizePolicy.setHeightForWidth(self.label_9.sizePolicy().hasHeightForWidth()) 86 self.label_9.setSizePolicy(sizePolicy) 87 self.label_9.setAlignment(QtCore.Qt.AlignCenter) 88 self.label_9.setObjectName("label_9") 89 self.gridLayout.addWidget(self.label_9, 0, 6, 1, 1) 90 self.label_10 = QtWidgets.QLabel(self.centralwidget) 91 sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed) 92 sizePolicy.setHorizontalStretch(0) 93 sizePolicy.setVerticalStretch(0) 94 sizePolicy.setHeightForWidth(self.label_10.sizePolicy().hasHeightForWidth()) 95 self.label_10.setSizePolicy(sizePolicy) 96 self.label_10.setAlignment(QtCore.Qt.AlignCenter) 97 self.label_10.setObjectName("label_10") 98 self.gridLayout.addWidget(self.label_10, 0, 7, 1, 1) 99 self.verticalLayout.addLayout(self.gridLayout) 100 self.line_5 = QtWidgets.QFrame(self.centralwidget) 101 self.line_5.setFrameShape(QtWidgets.QFrame.HLine) 102 self.line_5.setFrameShadow(QtWidgets.QFrame.Sunken) 103 self.line_5.setObjectName("line_5") 104 self.verticalLayout.addWidget(self.line_5) 105 spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) 106 self.verticalLayout.addItem(spacerItem) 107 self.line_2 = QtWidgets.QFrame(self.centralwidget) 108 self.line_2.setFrameShape(QtWidgets.QFrame.HLine) 109 self.line_2.setFrameShadow(QtWidgets.QFrame.Sunken) 110 self.line_2.setObjectName("line_2") 111 self.verticalLayout.addWidget(self.line_2) 112 self.horizontalLayout_3 = QtWidgets.QHBoxLayout() 113 self.horizontalLayout_3.setObjectName("horizontalLayout_3") 114 self.label_13 = QtWidgets.QLabel(self.centralwidget) 115 self.label_13.setObjectName("label_13") 116 self.horizontalLayout_3.addWidget(self.label_13) 117 self.label = QtWidgets.QLabel(self.centralwidget) 118 self.label.setObjectName("label") 119 self.horizontalLayout_3.addWidget(self.label) 120 self.lineEdit = QtWidgets.QLineEdit(self.centralwidget) 121 self.lineEdit.setObjectName("lineEdit") 122 self.horizontalLayout_3.addWidget(self.lineEdit) 123 self.pushButton_3 = QtWidgets.QPushButton(self.centralwidget) 124 self.pushButton_3.setObjectName("pushButton_3") 125 self.horizontalLayout_3.addWidget(self.pushButton_3) 126 self.verticalLayout.addLayout(self.horizontalLayout_3) 127 self.horizontalLayout_2 = QtWidgets.QHBoxLayout() 128 self.horizontalLayout_2.setObjectName("horizontalLayout_2") 129 self.label_14 = QtWidgets.QLabel(self.centralwidget) 130 sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) 131 sizePolicy.setHorizontalStretch(0) 132 sizePolicy.setVerticalStretch(0) 133 sizePolicy.setHeightForWidth(self.label_14.sizePolicy().hasHeightForWidth()) 134 self.label_14.setSizePolicy(sizePolicy) 135 self.label_14.setObjectName("label_14") 136 self.horizontalLayout_2.addWidget(self.label_14) 137 self.label_4 = QtWidgets.QLabel(self.centralwidget) 138 self.label_4.setObjectName("label_4") 139 self.horizontalLayout_2.addWidget(self.label_4) 140 self.pushButton_4 = QtWidgets.QPushButton(self.centralwidget) 141 sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) 142 sizePolicy.setHorizontalStretch(0) 143 sizePolicy.setVerticalStretch(0) 144 sizePolicy.setHeightForWidth(self.pushButton_4.sizePolicy().hasHeightForWidth()) 145 self.pushButton_4.setSizePolicy(sizePolicy) 146 self.pushButton_4.setObjectName("pushButton_4") 147 self.horizontalLayout_2.addWidget(self.pushButton_4) 148 self.verticalLayout.addLayout(self.horizontalLayout_2) 149 self.line = QtWidgets.QFrame(self.centralwidget) 150 self.line.setFrameShape(QtWidgets.QFrame.HLine) 151 self.line.setFrameShadow(QtWidgets.QFrame.Sunken) 152 self.line.setObjectName("line") 153 self.verticalLayout.addWidget(self.line) 154 spacerItem1 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) 155 self.verticalLayout.addItem(spacerItem1) 156 self.line_4 = QtWidgets.QFrame(self.centralwidget) 157 self.line_4.setFrameShape(QtWidgets.QFrame.HLine) 158 self.line_4.setFrameShadow(QtWidgets.QFrame.Sunken) 159 self.line_4.setObjectName("line_4") 160 self.verticalLayout.addWidget(self.line_4) 161 self.horizontalLayout_5 = QtWidgets.QHBoxLayout() 162 self.horizontalLayout_5.setObjectName("horizontalLayout_5") 163 self.textBrowser = QtWidgets.QTextBrowser(self.centralwidget) 164 sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) 165 sizePolicy.setHorizontalStretch(0) 166 sizePolicy.setVerticalStretch(0) 167 sizePolicy.setHeightForWidth(self.textBrowser.sizePolicy().hasHeightForWidth()) 168 self.textBrowser.setSizePolicy(sizePolicy) 169 self.textBrowser.setObjectName("textBrowser") 170 self.horizontalLayout_5.addWidget(self.textBrowser) 171 self.label_11 = QtWidgets.QLabel(self.centralwidget) 172 sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) 173 sizePolicy.setHorizontalStretch(0) 174 sizePolicy.setVerticalStretch(0) 175 sizePolicy.setHeightForWidth(self.label_11.sizePolicy().hasHeightForWidth()) 176 self.label_11.setSizePolicy(sizePolicy) 177 self.label_11.setAlignment(QtCore.Qt.AlignCenter) 178 self.label_11.setObjectName("label_11") 179 self.horizontalLayout_5.addWidget(self.label_11) 180 self.verticalLayout.addLayout(self.horizontalLayout_5) 181 self.line_3 = QtWidgets.QFrame(self.centralwidget) 182 self.line_3.setFrameShape(QtWidgets.QFrame.HLine) 183 self.line_3.setFrameShadow(QtWidgets.QFrame.Sunken) 184 self.line_3.setObjectName("line_3") 185 self.verticalLayout.addWidget(self.line_3) 186 spacerItem2 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) 187 self.verticalLayout.addItem(spacerItem2) 188 self.horizontalLayout = QtWidgets.QHBoxLayout() 189 self.horizontalLayout.setObjectName("horizontalLayout") 190 self.pushButton = QtWidgets.QPushButton(self.centralwidget) 191 self.pushButton.setText("") 192 self.pushButton.setObjectName("pushButton") 193 self.horizontalLayout.addWidget(self.pushButton) 194 self.checkBox_2 = QtWidgets.QCheckBox(self.centralwidget) 195 self.checkBox_2.setObjectName("checkBox_2") 196 self.horizontalLayout.addWidget(self.checkBox_2) 197 self.checkBox = QtWidgets.QCheckBox(self.centralwidget) 198 self.checkBox.setObjectName("checkBox") 199 self.horizontalLayout.addWidget(self.checkBox) 200 spacerItem3 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) 201 self.horizontalLayout.addItem(spacerItem3) 202 self.pushButton_5 = QtWidgets.QPushButton(self.centralwidget) 203 self.pushButton_5.setObjectName("pushButton_5") 204 self.horizontalLayout.addWidget(self.pushButton_5) 205 self.pushButton_6 = QtWidgets.QPushButton(self.centralwidget) 206 self.pushButton_6.setObjectName("pushButton_6") 207 self.horizontalLayout.addWidget(self.pushButton_6) 208 self.pushButton_2 = QtWidgets.QPushButton(self.centralwidget) 209 self.pushButton_2.setObjectName("pushButton_2") 210 self.horizontalLayout.addWidget(self.pushButton_2) 211 self.verticalLayout.addLayout(self.horizontalLayout) 212 MainWindow.setCentralWidget(self.centralwidget) 213 self.statusbar = QtWidgets.QStatusBar(MainWindow) 214 self.statusbar.setObjectName("statusbar") 215 MainWindow.setStatusBar(self.statusbar) 216 217 self.retranslateUi(MainWindow) 218 QtCore.QMetaObject.connectSlotsByName(MainWindow) 219 220 def retranslateUi(self, MainWindow): 221 _translate = QtCore.QCoreApplication.translate 222 MainWindow.setWindowTitle(_translate("MainWindow", "caiya tools")) 223 self.label_12.setText(_translate("MainWindow", "图像数据提取工具")) 224 self.label_6.setText(_translate("MainWindow", "Y1")) 225 self.label_2.setText(_translate("MainWindow", "X1")) 226 self.label_3.setText(_translate("MainWindow", "X0")) 227 self.label_5.setText(_translate("MainWindow", "Y0")) 228 self.label_7.setText(_translate("MainWindow", "y")) 229 self.label_8.setText(_translate("MainWindow", "x")) 230 self.label_9.setText(_translate("MainWindow", "x")) 231 self.label_10.setText(_translate("MainWindow", "y")) 232 self.label_13.setText(_translate("MainWindow", "保存路径:")) 233 self.label.setText(_translate("MainWindow", "目录")) 234 self.pushButton_3.setText(_translate("MainWindow", "Browse")) 235 self.label_14.setText(_translate("MainWindow", "导入路径:")) 236 self.label_4.setText(_translate("MainWindow", "文件路径")) 237 self.pushButton_4.setText(_translate("MainWindow", "Open File")) 238 self.label_11.setText(_translate("MainWindow", "处理波形显示")) 239 self.checkBox_2.setText(_translate("MainWindow", "x轴对数分度坐标")) 240 self.checkBox.setText(_translate("MainWindow", "y轴对数分度坐标")) 241 self.pushButton_5.setText(_translate("MainWindow", "校准坐标")) 242 self.pushButton_6.setText(_translate("MainWindow", "标记数据点")) 243 self.pushButton_2.setText(_translate("MainWindow", "Save"))
全局变量部分:
#跨模块全局变量 #模态运行标志位 punlic_flag=10 #坐标校准点 public_coord=[(0,0),(0,0),(0,0),(0,0)] #图片尺寸 public_size=(0,0) #坐标轴绘制点 public_cood_data=[(0,0),(0,0),(0,0),(0,0)] #坐标原点 public_cood_origin=(0,0) #提取点数坐标 public_data_point=[]
cv2图片处理部分:
import os import cv2 import pyautogui import FlagUse import pandas as pd def save_excel(path_in,data_in): try: if os.path.exists(path_in)==True: os.remove(path_in) except Exception as exc: error_str=str(exc) return error_str else: try: data_save=pd.DataFrame(data_in) data_save.to_excel(path_in,index=False) except Exception as exc: error_str = str(exc) return error_str else: return "Done!" # 定义标注窗口的默认名称 WINDOW_NAME = 'image curve data get' # 定义画面刷新的大概帧率(是否能达到取决于电脑性能) FPS = 30 # ESC键对应的cv.waitKey()的返回值 # 注意这个值根据操作系统不同有不同 KEY_ESC = 27 # 定义物体框标注工具类 class SimpleBBoxLabeling: def __init__(self, inage, fps=FPS, window_name=None): self. inage= inage self.fps = fps self.window_name = window_name if window_name else WINDOW_NAME # pt0是正在画的左上角坐标,pt1是鼠标所在坐标 self._pt0 = None #h 高度,w宽度 h,w=self.inage.shape[:2] self._pt1 = (int(h/2),int(w/2)) FlagUse.public_size=(h,w) # 表明当前是否正在画框的状态标记 self._drawing = False # 当前标注物体的名称 self._cur_label = None # 当前图像对应的曲线的点 self._bboxes = [] # 当前图像坐标校准的点 self._bboxes_coord = [] #放大窗口 self.dx = 30 self.y0_last = self._pt1[1] - self.dx self.y1_last = self._pt1[1] + self.dx self.x0_last = self._pt1[0] - self.dx self.x1_last = self._pt1[0] + self.dx self.yy0_last = 0;self.yy1_last = 0;self.xx0_last = 0;self.xx1_last = 0 # 鼠标回调函数 def _mouse_ops(self, event, x, y, flags, param): # 按下左键时,坐标为左上角,同时表明开始画框,改变drawing标记为True if event == cv2.EVENT_LBUTTONDOWN: self._drawing = True self._pt0 = (x, y) # 左键抬起,表明当前框画完了,坐标记为右下角,并保存,同时改变drawing标记为False elif event == cv2.EVENT_LBUTTONUP: self._drawing = False self._pt1 = (x, y) #坐标轴校准 if FlagUse.punlic_flag==0: if self._pt1[0] == self._pt0[0] and self._pt1[1] == self._pt0[1]:#不是在画框 if len(self._bboxes_coord)<4:#最大只能4个点 self._bboxes_coord.append((self._cur_label, self._pt0)) if len(self._bboxes_coord)==4:#校准点画满,更新全局变量 for i in range(len(self._bboxes_coord)): FlagUse.public_coord[i]=self._bboxes_coord[i][1] #数据点提取 elif FlagUse.punlic_flag==1: if self._pt1[0]!=self._pt0[0] and self._pt1[1]!=self._pt0[1]:#不是在画框 if self._pt1[0] >= self._pt0[0] and self._pt1[1] >= self._pt0[1]:#判断不是反向画框 if len(self._bboxes)!=0:#数据点存在 inx=[] for i in range(len(self._bboxes)):#找到哪些点在方框中 if self._bboxes[i][1][0]>self._pt0[0] and self._bboxes[i][1][0]<self._pt1[0] and self._bboxes[i][1][1]>self._pt0[1] and self._bboxes[i][1][1]<self._pt1[1]: inx.append(i) inx.sort(reverse=True)#删除框选的点 for i in inx: self._bboxes.pop(i) else:#添加数据点 self._bboxes.append((self._cur_label, self._pt0)) FlagUse.public_data_point=[] for i in self._bboxes: FlagUse.public_data_point.append(i[1]) # 实时更新右下角坐标方便画框 elif event == cv2.EVENT_MOUSEMOVE: self._pt1 = (x, y) # 鼠标右键删除最近画好的框 elif event == cv2.EVENT_RBUTTONUP: if FlagUse.punlic_flag == 0: if self._bboxes_coord: self._bboxes_coord.pop() elif FlagUse.punlic_flag == 1: if self._bboxes: self._bboxes.pop() # 清除所有标注框和当前状态 def _clean_bbox(self): self._pt0 = None self._pt1 = None self._drawing = False self._bboxes = [] # 画标注框和当前信息的函数 def _draw_bbox(self, img): canvas = cv2.copyMakeBorder(img, 0, 0, 0, 0, cv2.BORDER_CONSTANT, value=(255, 0, 0))#新建画布 # 画出已经标好的点和对应名字 i=0 for label, bpt0 in self._bboxes: cv2.circle(canvas, bpt0,5, (0, 0, 255), -1) #字体 font=cv2.FONT_HERSHEY_SIMPLEX #标记点 cv2.putText(canvas,"a%s"%i,bpt0,font,1,(200,50,0),2) i=i+1 i=0 for label, bpt0 in self._bboxes_coord: cv2.circle(canvas, bpt0,5, (0, 0, 255), -1) #字体 font=cv2.FONT_HERSHEY_SIMPLEX #标记点 if i==0 or i==1: cv2.putText(canvas,"X%s-%s"%(i,bpt0[1]),bpt0,font,1,(200,50,0),2) else: cv2.putText(canvas, "Y%s-%s" % (i-2,bpt0[0]), bpt0, font, 1, (200, 50, 0), 2) i=i+1 if FlagUse.punlic_flag==2:#显示坐标轴 cv2.line(canvas, FlagUse.public_cood_data[0], FlagUse.public_cood_data[1], (255,0, 255), 2) cv2.line(canvas, FlagUse.public_cood_data[2], FlagUse.public_cood_data[3], (255, 0, 255), 2) font = cv2.FONT_HERSHEY_SIMPLEX cv2.putText(canvas, "(%s,%s)" % (FlagUse.public_cood_origin[0],FlagUse.public_cood_origin[1]), FlagUse.public_cood_origin, font, 1, (200, 50, 0), 2) # 画正在标注的框和对应名字 if self._drawing: if self._pt1[0] >= self._pt0[0] and self._pt1[1] >= self._pt0[1]: cv2.rectangle(canvas, self._pt0, self._pt1, (0, 255, 0), thickness=2) #实时刷新显示鼠标像素坐标 font = cv2.FONT_HERSHEY_SIMPLEX cv2.putText(canvas, "(%s,%s)" % (self._pt1[0],self._pt1[1]), self._pt1, font, 1, (200, 50, 0), 2) return canvas # 画放大窗口 def _draw_bbox1(self, img): h, w = img.shape[:2] #边界附近处理 if self._pt1[1]<h and self._pt1[1]>0 and self._pt1[0]<w and self._pt1[0]>0: y0=self._pt1[1]-self.dx;y1 = self._pt1[1] +self.dx;x0 = self._pt1[0] - self.dx;x1 = self._pt1[0] +self.dx yy0=0;yy1=0;xx0=0;xx1=0 if y0<0: y0=0 yy0=self.dx-self._pt1[1] if y1>h: y1=h yy1=self._pt1[1] +self.dx-h if x0<0: x0=0 xx0=self.dx-self._pt1[0] if x1>w: x1=w xx1=self._pt1[0] +self.dx-w self.y0_last = y0;self.y1_last = y1;self.x0_last = x0;self.x1_last = x1 self.yy0_last = yy0;self.yy1_last = yy1;self.xx0_last =xx0;self.xx1_last = xx1 useimg=self.inage[y0:y1,x0:x1] canvas = cv2.copyMakeBorder(useimg, yy0, yy1, xx0, xx1, cv2.BORDER_CONSTANT, value=(255, 255, 255)) else: useimg = self.inage[self.y0_last:self.y1_last, self.x0_last:self.x1_last] canvas = cv2.copyMakeBorder(useimg, self.yy0_last, self.yy1_last, self.xx0_last, self.xx1_last, cv2.BORDER_CONSTANT, value=(255, 255,255)) # 画十字标 cv2.line(canvas,(0,self.dx),(self.dx*2,self.dx),(0,165,255),1) cv2.line(canvas, (self.dx, 0), (self.dx, self.dx*2), (0, 165, 255), 1) return canvas # 开始OpenCV窗口循环的方法,定义了程序的主逻辑 def start(self): # 定义窗口和鼠标回调 cv2.namedWindow(self.window_name,0) cv2.namedWindow("Magnifier",0) cv2.setMouseCallback(self.window_name, self._mouse_ops) key = 0 # 定义每次循环的持续时间 delay = int(1000 / FPS) img = self.inage # 只要没有按下Esc键或者窗口关闭,就持续循环 while key != KEY_ESC and cv2.getWindowProperty(self.window_name,cv2.WND_PROP_AUTOSIZE)==0.0 and cv2.getWindowProperty("Magnifier",cv2.WND_PROP_AUTOSIZE)==0.0: # 主窗口刷新显示 canvas = self._draw_bbox(img) cv2.imshow(self.window_name, canvas) #当大窗口刷新显示 canvas1=self._draw_bbox1(img) cv2.imshow("Magnifier",canvas1) key = cv2.waitKey(delay) #按键移动鼠标,使用pyautogui模块 if key==119: pyautogui.move(0,-1) elif key==115: pyautogui.move(0,1) elif key==97: pyautogui.move(-1,0) elif key==100: pyautogui.move(1,0) cv2.destroyAllWindows() return 'Finished!' if __name__ == '__main__': img = cv2.imread('11.png') labeling_task = SimpleBBoxLabeling(img) labeling_task.start()
主程序部分:
import os import sys from sys import argv import qtawesome from PyQt5.QtGui import QPixmap, QImage from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas import caiya from PyQt5 import QtCore from PyQt5.QtCore import QThread from PyQt5.QtWidgets import QApplication, QMainWindow, QFileDialog import caiyagui import cv2 import FlagUse import math import matplotlib.pyplot as plt plt.switch_backend('agg') class my_mainwindow(): def __init__(self): # PyQt5中,每个应用程序都必须实例化一个QApplication(): app = QApplication(argv) app.setWindowIcon(qtawesome.icon("fa.github-alt",color="green")) self.my_MainWindow = QMainWindow() self.my_ui = caiyagui.Ui_MainWindow() self.my_ui.setupUi(self.my_MainWindow) #################################################################### self.my_ui.textBrowser.document().setMaximumBlockCount(10000) self.my_ui.pushButton.setStyleSheet('''QPushButton{background:#6DDF6D;border-radius:5px;}''') self.my_ui.pushButton.setDisabled(True) self.my_ui.lineEdit.setPlaceholderText("xlsx") self.my_ui.pushButton_5.setStyleSheet('''QPushButton{background:#00ff00;}QPushButton:hover{background:yellow;}''') self.my_ui.pushButton_6.setStyleSheet( '''QPushButton{background:#00ff00;}QPushButton:hover{background:yellow;}''') self.my_ui.checkBox_2.setDisabled(True) self.my_ui.checkBox.setDisabled(True) self.my_ui.pushButton_2.setStyleSheet( '''QPushButton{background:#DDA0DD;}QPushButton:hover{background:#90EE90;}''') #################################################################### #子进程运行 self.key_flag = 1 #坐标轴校准 self.align_flag = 0 # 坐标系建立ok self.use_falg = 0 # 数据选择ok self.datapoint_falg = 0 # 坐标系旋转角度 self.thate = 0 # 坐标翻转 self.cood_turn = 0 # 最终坐标平移原点 self.my_orign = (0, 0) # 缩放比例 self.zoom = [0, 0] #保存数据 self.data = {"x": [], "y": []} self.name_data = list(self.data.keys()) #图片 fig = plt.figure() plt.plot([1, 2, 3], [4, 5, 6], color='r', linestyle='-') canvas = FigureCanvas(fig) # 渲染画面 canvas.draw() width, height = canvas.get_width_height() # 转化为QImage im = QImage(canvas.buffer_rgba(), width, height, QImage.Format_ARGB32) # 转化为QPixmap self.png = QPixmap(im) self.my_ui.label_11.setPixmap(self.png) # 设置文本标签的图形 #坐标轴信息 self.ax0=(0,0) self.ax1 = (0, 0) self.ay0 = (0, 0) self.ay1 = (0, 0) self.a0 = (0, 0) self.a1 = (0, 0) self.y0 = (0, 0) self.y1 = (0, 0) self.origin=(0,0) #要提取的点 self.datapoint=[] #线程传递信息 self.send_lint=[] self.openfile_name=None self.savefile_name=None self.my_ui.textBrowser.append("放大窗口微调:A-LEFT|D-RIGHT|W-UP|S-DOWN") self.my_ui.textBrowser.append("鼠标右键-删除最近标记点|鼠标左键长按拖动-批量删除数据提取标记点") self.mywork=myworkthread(self.send_lint) self.mywork.finishsignal.connect(self.workend) self.click_pushbutton(self.my_MainWindow) ##################################################################### self.my_MainWindow.show() sys.exit(app.exec_()) def click_pushbutton(self,my_MainWindow): self.my_ui.pushButton_2.clicked.connect(self.save_data) self.my_ui.pushButton_3.clicked.connect(lambda:self.savefile(my_MainWindow)) self.my_ui.pushButton_4.clicked.connect(lambda: self.openfile(my_MainWindow)) self.my_ui.pushButton_5.clicked.connect(self.align) self.my_ui.pushButton_6.clicked.connect(self.data_point) def data_point(self): if self.use_falg==0: self.my_ui.textBrowser.append("坐标系未建立") return if self.datapoint_falg==0: FlagUse.punlic_flag=1 self.datapoint_falg=1 self.my_ui.pushButton_6.setStyleSheet( '''QPushButton{background:red;}QPushButton:hover{background:yellow;}''') self.my_ui.textBrowser.append("标记提取点") elif self.datapoint_falg==1: self.datapoint=[] #提取数据点 for i in FlagUse.public_data_point: self.datapoint.append(i) self.data = {"x": [], "y": []} self.name_data = list(self.data.keys()) #数据点坐标转换 for i in range(len(self.datapoint)): self.datapoint[i]=self.Coordinate_trans(self.origin, self.thate, self.datapoint[i], True, True, True, True) #x从小到大排序 self.datapoint.sort(reverse=False) #存入保存字典 for i in range(len(self.datapoint)): datamy = [self.datapoint[i][0],self.datapoint[i][1]] for j in range(len(datamy)): self.data[self.name_data[j]].append(datamy[j]) self.my_ui.textBrowser.append("数据提取OK") self.datapoint_falg=0 self.my_ui.pushButton_6.setStyleSheet( '''QPushButton{background:#00ff00;}QPushButton:hover{background:yellow;}''') FlagUse.punlic_flag = 10 #matplotlib图片在lable显示 fig = plt.figure() plt.plot(self.data[self.name_data[0]], self.data[self.name_data[1]], color='r', linestyle='-') canvas = FigureCanvas(fig) # 渲染画面 canvas.draw() width, height = canvas.get_width_height() # 转化为QImage im = QImage(canvas.buffer_rgba(), width, height, QImage.Format_ARGB32) # 转化为QPixmap self.png = QPixmap(im) self.my_ui.label_11.setPixmap(self.png) # 设置文本标签的图形 def Coordinate_trans(self,origin,thate,s_point,TURN,MOVE,ZOOM,LOG_FLAG): datapoint=[0,0] # 平移变换 datapoint[0] = s_point[0] - origin[0] datapoint[1] = s_point[1] - origin[1] # 旋转变换 datapoint[0] = datapoint[0] * math.cos(thate) + datapoint[1] * math.sin(thate) datapoint[1] = datapoint[1] * math.cos(thate) - datapoint[0] * math.sin(thate) #坐标翻转 if TURN: if self.cood_turn|0x02==0x03: datapoint[0]=-datapoint[0] if self.cood_turn|0x01==0x03: datapoint[1] = -datapoint[1] #坐标缩放 if ZOOM: datapoint[0]=datapoint[0]/self.zoom[0] datapoint[1] = datapoint[1] / self.zoom[1] #坐标最终平移 if MOVE: datapoint[0] = datapoint[0] + self.my_orign[0] datapoint[1] = datapoint[1] + self.my_orign[1] #对数分度转化 if LOG_FLAG: if self.my_ui.checkBox_2.isChecked(): # 变换x datapoint[0] = 10**datapoint[0] if self.my_ui.checkBox.isChecked(): # 变换y datapoint[1]=10**datapoint[1] return datapoint def openfile(self,my_MainWindow): if self.key_flag==1: # 打开对话框, "打开文件"(对话框的名字), '.'(打开当前的路径), '图像文件(*.jpg *.png)'(打开文件的格式) openfile_name_back=QFileDialog.getOpenFileName(my_MainWindow,"选择路径",'.', '图像文件(*.jpg *.png)') if len(openfile_name_back[0])==0: return else: self.openfile_name=openfile_name_back[0] self.my_ui.label_4.setText(self.openfile_name) # 新建线程开始计算 self.send_lint=[] self.send_lint.append(self.openfile_name) self.send_lint.append(1) self.mywork = myworkthread(self.send_lint) self.mywork.finishsignal.connect(self.workend) self.mywork.start() self.key_flag=0 self.my_ui.textBrowser.append("请校准坐标系") self.my_ui.pushButton.setStyleSheet('''QPushButton{background:#D23550;border-radius:5px;}''') else: self.my_ui.textBrowser.append("还有未完成任务") def align(self): if self.align_flag==0 and self.key_flag==0: FlagUse.punlic_flag=0 self.my_ui.pushButton_5.setStyleSheet( '''QPushButton{background:red;}QPushButton:hover{background:yellow;}''') self.align_flag=1 self.my_ui.textBrowser.append("开始校准") self.my_ui.checkBox_2.setDisabled(False) self.my_ui.checkBox.setDisabled(False) elif self.key_flag==1: self.my_ui.textBrowser.append("暂无任务") elif self.align_flag==1: try: # 输入参数 self.x0 = (float(self.my_ui.lineEdit_3.text()), float(self.my_ui.lineEdit_6.text())) self.x1 = (float(self.my_ui.lineEdit_2.text()), float(self.my_ui.lineEdit_7.text())) self.y0 = (float(self.my_ui.lineEdit_5.text()), float(self.my_ui.lineEdit_8.text())) self.y1 = (float(self.my_ui.lineEdit_4.text()), float(self.my_ui.lineEdit_9.text())) #对数转换 if self.my_ui.checkBox_2.isChecked():#变换x self.x0 = (math.log10(self.x0[0]), self.x0[1]) self.x1 = (math.log10(self.x1[0]), self.x1[1]) self.y0 = (math.log10(self.y0[0]), self.y0[1]) self.y1 = (math.log10(self.y1[0]), self.y1[1]) if self.my_ui.checkBox.isChecked():#变换y self.x0 = (self.x0[0], math.log10(self.x0[1])) self.x1 = (self.x1[0], math.log10(self.x1[1])) self.y0 = (self.y0[0], math.log10(self.y0[1])) self.y1 = (self.y1[0], math.log10(self.y1[1])) except Exception as exc: error_str = str(exc) self.my_ui.textBrowser.append(error_str) else: #判断坐标校准点是否设置完 for i in FlagUse.public_coord: if i==(0,0): self.my_ui.textBrowser.append("坐标轴定义不全") return self.ax0 = FlagUse.public_coord[0] self.ax1 = FlagUse.public_coord[1] self.ay0 = FlagUse.public_coord[2] self.ay1 = FlagUse.public_coord[3] #这一段是获取坐标轴在图像上绘制的两个端点 if(self.ax0[0]-self.ax1[0])!=0: k1=(self.ax0[1]-self.ax1[1])/(self.ax0[0]-self.ax1[0]) if abs(k1) == 0: k1 = 1 * 10 ** -6 else: k1=1*10**6 b1 = self.ax1[1] - k1 * self.ax1[0] kx1=b1 kx2=k1*FlagUse.public_size[1]+b1 kx3=-b1/k1 kx4=(FlagUse.public_size[0]-b1)/k1 mx=[] mx.append((0,int(kx1))) mx.append((FlagUse.public_size[1],int(kx2))) mx.append((int(kx3),0)) mx.append((int(kx4),FlagUse.public_size[0])) flag_x=0 m1=(0,0) m2=(0,0) if kx1>0 and kx1<FlagUse.public_size[0]: m1=mx[0] flag_x=flag_x+1 if kx2>0 and kx2<FlagUse.public_size[0]: if flag_x!=0: m2=mx[1] else: m1=mx[1] flag_x = flag_x + 1 if kx3>0 and kx3<FlagUse.public_size[1]: if flag_x != 0: m2 = mx[2] else: m1 = mx[2] flag_x = flag_x + 1 if kx4>0 and kx4<FlagUse.public_size[1]: if flag_x != 0: m2 = mx[3] else: m1 = mx[3] flag_x = flag_x + 1 if flag_x!=2: self.my_ui.textBrowser.append("坐标轴定义错误") return else: FlagUse.public_cood_data[0]=m1 FlagUse.public_cood_data[1] = m2 if (self.ay0[0] - self.ay1[0]) != 0: k2 = (self.ay0[1] - self.ay1[1]) / (self.ay0[0] - self.ay1[0]) if abs(k1) == 0: k2 = 1 * 10 ** -6 else: k2 = 1 * 10 ** 6 b2 = self.ay1[1] - k2 * self.ay1[0] ky1 = b2 ky2 = k2 * FlagUse.public_size[1] + b2 ky3 = -b2 / k2 ky4 = (FlagUse.public_size[0] - b2) / k2 my = [] my.append((0, int(ky1))) my.append((FlagUse.public_size[1], int(ky2))) my.append((int(ky3), 0)) my.append((int(ky4), FlagUse.public_size[0])) flag_y = 0 m3 = (0, 0) m4 = (0, 0) if ky1 > 0 and ky1 < FlagUse.public_size[0]: m3 = my[0] flag_y = flag_y + 1 if ky2 > 0 and ky2 < FlagUse.public_size[0]: if flag_y != 0: m4 = my[1] else: m3 = my[1] flag_y = flag_y + 1 if ky3 > 0 and ky3 < FlagUse.public_size[1]: if flag_y != 0: m4 = my[2] else: m3 = my[2] flag_y = flag_y + 1 if ky4 > 0 and ky4 < FlagUse.public_size[1]: if flag_y != 0: m4 = my[3] else: m3 = my[3] flag_y = flag_y + 1 if flag_y != 2: self.my_ui.textBrowser.append("坐标轴定义错误") return else: FlagUse.public_cood_data[2] = m3 FlagUse.public_cood_data[3] = m4 if k1*k2+1>0.1: if abs(k1-k2)<1*10**3: self.my_ui.textBrowser.append("暂不支持非直角坐标系") return #获取坐标原点坐标 orign_x=(b2-b1)/(k1-k2) orign_y=k1*orign_x+b1 self.origin=(int(orign_x),int(orign_y)) #获取坐标轴旋转角度 self.thate=math.atan(k1) FlagUse.public_cood_origin=self.origin # 判断是否翻转 use_x0=self.Coordinate_trans(self.origin,self.thate,self.ax0,False,False,False,False) use_x1 = self.Coordinate_trans(self.origin, self.thate, self.ax1,False,False,False,False) use_y0 = self.Coordinate_trans(self.origin, self.thate, self.ay0,False,False,False,False) use_y1 = self.Coordinate_trans(self.origin, self.thate, self.ay1,False,False,False,False) if (use_x0[0] - use_x1[0]) * (self.x0[0] -self.x1[0])<0: self.cood_turn=self.cood_turn|0x01 if (use_y0[1] - use_y1[1]) * (self.y0[1] -self.y1[1])<0: self.cood_turn=self.cood_turn|0x02 #获取缩放比例 use_x0 = self.Coordinate_trans(self.origin, self.thate, self.ax0, True, False,False,False) use_x1 = self.Coordinate_trans(self.origin, self.thate, self.ax1, True, False,False,False) use_y0 = self.Coordinate_trans(self.origin, self.thate, self.ay0, True, False,False,False) use_y1 = self.Coordinate_trans(self.origin, self.thate, self.ay1, True, False,False,False) self.zoom[0]=(use_x0[0]-use_x1[0])/(self.x0[0]-self.x1[0]) self.zoom[1] = (use_y0[1] - use_y1[1]) / (self.y0[1] - self.y1[1]) #获取最终平移坐标 use_dx=self.y0[0] USE_dy=self.x0[1] self.my_orign=(use_dx,USE_dy) #相关标志位刷新 self.align_flag = 0 self.use_falg=1 self.my_ui.pushButton_5.setStyleSheet( '''QPushButton{background:#00ff00;}QPushButton:hover{background:yellow;}''') FlagUse.punlic_flag = 2 self.my_ui.textBrowser.append("坐标轴定义成功") self.my_ui.checkBox_2.setDisabled(True) self.my_ui.checkBox.setDisabled(True) def savefile(self,my_MainWindow): # 打开对话框, "打开文件"(对话框的名字), '.'(打开当前的路径), '图像文件(*.jpg *.png)'(打开文件的格式) savefile_name_back=QFileDialog.getExistingDirectory(my_MainWindow,"选择路径") if len(savefile_name_back)==0: return else: self.savefile_name=savefile_name_back self.my_ui.label.setText(self.savefile_name) def workend(self,ins): if ins[0]==1: self.my_ui.textBrowser.append(ins[1]) self.key_flag=1 self.my_ui.pushButton.setStyleSheet('''QPushButton{background:#6DDF6D;border-radius:5px;}''') self.align_flag =0 self.my_ui.pushButton_5.setStyleSheet( '''QPushButton{background:#00ff00;}QPushButton:hover{background:yellow;}''') FlagUse.punlic_flag = 10 FlagUse.public_coord = [(0, 0), (0, 0), (0, 0), (0, 0)] FlagUse.public_data_point=[] self.use_falg=0 self.datapoint_falg = 0 self.my_ui.pushButton_6.setStyleSheet( '''QPushButton{background:#00ff00;}QPushButton:hover{background:yellow;}''') self.my_ui.pushButton.setStyleSheet('''QPushButton{background:#D23550;border-radius:5px;}''') else: self.my_ui.textBrowser.append(ins[1]) def save_data(self): try: if os.path.exists(self.savefile_name)==False: self.my_ui.textBrowser.append("路径出错") except Exception as exc: error_str = str(exc) self.my_ui.textBrowser.append(error_str) else: file_name=self.my_ui.lineEdit.text() if len(file_name)==0: self.my_ui.textBrowser.append("文件名为空") return str_limit=["\\","/",":","*","?",'"',"<",">","!"] for i in range(len(str_limit)): if file_name.find(str_limit[i])!=-1: self.my_ui.textBrowser.append("文件名格式错误") return usestr=self.savefile_name+"/"+file_name+".xlsx" self.send_lint = [] self.send_lint.append(usestr) self.send_lint.append(2) self.send_lint.append(self.data) self.png.save("GotCurve.PNG") self.mywork1 = myworkthread(self.send_lint) self.mywork1.finishsignal.connect(self.workend) self.mywork1.start() #新建线程 class myworkthread(QThread): finishsignal=QtCore.pyqtSignal(list) def __init__(self,in_list): super(myworkthread,self).__init__() self.in_list=in_list def run(self): #耗时程序 if self.in_list[1]==1: img = cv2.imread(self.in_list[0]) labeling_task = caiya.SimpleBBoxLabeling(img) backstr=labeling_task.start() back_list = [] back_list.append(1) back_list.append(backstr) else: backstr = caiya.save_excel(self.in_list[0], self.in_list[2]) back_list=[] back_list.append(2) back_list.append(backstr) self.finishsignal.emit(back_list) if __name__=="__main__": my_mainwindow()
标签:多线程,self,QtWidgets,label,sizePolicy,ui,pyQT5lable,my,图片 From: https://www.cnblogs.com/caiya/p/17738065.html