python提取论文图片波形数据:pyautogui键盘移动鼠标,跨模块全局变量使用,cv2局部放大窗口,matplotlib图片在pyQT5lable显示,坐标变换,多线程同时使用
最近写了一个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()
主程序部分:
1 import os 2 import sys 3 from sys import argv 4 import qtawesome 5 from PyQt5.QtGui import QPixmap, QImage 6 from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas 7 import caiya 8 from PyQt5 import QtCore 9 from PyQt5.QtCore import QThread 10 from PyQt5.QtWidgets import QApplication, QMainWindow, QFileDialog 11 import caiyagui 12 import cv2 13 import FlagUse 14 import math 15 import matplotlib.pyplot as plt 16 plt.switch_backend('agg') 17 18 class my_mainwindow(): 19 def __init__(self): 20 # PyQt5中,每个应用程序都必须实例化一个QApplication(): 21 app = QApplication(argv) 22 app.setWindowIcon(qtawesome.icon("fa.github-alt",color="green")) 23 self.my_MainWindow = QMainWindow() 24 self.my_ui = caiyagui.Ui_MainWindow() 25 self.my_ui.setupUi(self.my_MainWindow) 26 #################################################################### 27 self.my_ui.textBrowser.document().setMaximumBlockCount(10000) 28 self.my_ui.pushButton.setStyleSheet('''QPushButton{background:#6DDF6D;border-radius:5px;}''') 29 self.my_ui.pushButton.setDisabled(True) 30 self.my_ui.lineEdit.setPlaceholderText("xlsx") 31 self.my_ui.pushButton_5.setStyleSheet('''QPushButton{background:#00ff00;}QPushButton:hover{background:yellow;}''') 32 self.my_ui.pushButton_6.setStyleSheet( 33 '''QPushButton{background:#00ff00;}QPushButton:hover{background:yellow;}''') 34 self.my_ui.checkBox_2.setDisabled(True) 35 self.my_ui.checkBox.setDisabled(True) 36 self.my_ui.pushButton_2.setStyleSheet( 37 '''QPushButton{background:#DDA0DD;}QPushButton:hover{background:#90EE90;}''') 38 #################################################################### 39 #子进程运行 40 self.key_flag = 1 41 #坐标轴校准 42 self.align_flag = 0 43 # 坐标系建立ok 44 self.use_falg = 0 45 # 数据选择ok 46 self.datapoint_falg = 0 47 # 坐标系旋转角度 48 self.thate = 0 49 # 坐标翻转 50 self.cood_turn = 0 51 # 最终坐标平移原点 52 self.my_orign = (0, 0) 53 # 缩放比例 54 self.zoom = [0, 0] 55 #保存数据 56 self.data = {"x": [], "y": []} 57 self.name_data = list(self.data.keys()) 58 #图片 59 fig = plt.figure() 60 plt.plot([1, 2, 3], [4, 5, 6], color='r', linestyle='-') 61 canvas = FigureCanvas(fig) 62 # 渲染画面 63 canvas.draw() 64 width, height = canvas.get_width_height() 65 # 转化为QImage 66 im = QImage(canvas.buffer_rgba(), width, height, QImage.Format_ARGB32) 67 # 转化为QPixmap 68 self.png = QPixmap(im) 69 self.my_ui.label_11.setPixmap(self.png) # 设置文本标签的图形 70 #坐标轴信息 71 self.ax0=(0,0) 72 self.ax1 = (0, 0) 73 self.ay0 = (0, 0) 74 self.ay1 = (0, 0) 75 self.a0 = (0, 0) 76 self.a1 = (0, 0) 77 self.y0 = (0, 0) 78 self.y1 = (0, 0) 79 self.origin=(0,0) 80 #要提取的点 81 self.datapoint=[] 82 #线程传递信息 83 self.send_lint=[] 84 self.openfile_name=None 85 self.savefile_name=None 86 self.my_ui.textBrowser.append("放大窗口微调:A-LEFT|D-RIGHT|W-UP|S-DOWN") 87 self.my_ui.textBrowser.append("鼠标右键-删除最近标记点|鼠标左键长按拖动-批量删除数据提取标记点") 88 self.mywork=myworkthread(self.send_lint) 89 self.mywork.finishsignal.connect(self.workend) 90 self.click_pushbutton(self.my_MainWindow) 91 ##################################################################### 92 self.my_MainWindow.show() 93 sys.exit(app.exec_()) 94 95 def click_pushbutton(self,my_MainWindow): 96 self.my_ui.pushButton_2.clicked.connect(self.save_data) 97 self.my_ui.pushButton_3.clicked.connect(lambda:self.savefile(my_MainWindow)) 98 self.my_ui.pushButton_4.clicked.connect(lambda: self.openfile(my_MainWindow)) 99 self.my_ui.pushButton_5.clicked.connect(self.align) 100 self.my_ui.pushButton_6.clicked.connect(self.data_point) 101 102 def data_point(self): 103 if self.use_falg==0: 104 self.my_ui.textBrowser.append("坐标系未建立") 105 return 106 if self.datapoint_falg==0: 107 FlagUse.punlic_flag=1 108 self.datapoint_falg=1 109 self.my_ui.pushButton_6.setStyleSheet( 110 '''QPushButton{background:red;}QPushButton:hover{background:yellow;}''') 111 self.my_ui.textBrowser.append("标记提取点") 112 elif self.datapoint_falg==1: 113 self.datapoint=[] 114 #提取数据点 115 for i in FlagUse.public_data_point: 116 self.datapoint.append(i) 117 self.data = {"x": [], "y": []} 118 self.name_data = list(self.data.keys()) 119 #数据点坐标转换 120 for i in range(len(self.datapoint)): 121 self.datapoint[i]=self.Coordinate_trans(self.origin, self.thate, self.datapoint[i], True, True, True, True) 122 #x从小到大排序 123 self.datapoint.sort(reverse=False) 124 #存入保存字典 125 for i in range(len(self.datapoint)): 126 datamy = [self.datapoint[i][0],self.datapoint[i][1]] 127 for j in range(len(datamy)): 128 self.data[self.name_data[j]].append(datamy[j]) 129 self.my_ui.textBrowser.append("数据提取OK") 130 self.datapoint_falg=0 131 self.my_ui.pushButton_6.setStyleSheet( 132 '''QPushButton{background:#00ff00;}QPushButton:hover{background:yellow;}''') 133 FlagUse.punlic_flag = 10 134 #matplotlib图片在lable显示 135 fig = plt.figure() 136 if self.my_ui.checkBox_2.isChecked(): 137 plt.xscale("log") 138 if self.my_ui.checkBox.isChecked(): 139 plt.yscale("log") 140 plt.plot(self.data[self.name_data[0]], self.data[self.name_data[1]], color='r', linestyle='-') 141 canvas = FigureCanvas(fig) 142 # 渲染画面 143 canvas.draw() 144 width, height = canvas.get_width_height() 145 # 转化为QImage 146 im = QImage(canvas.buffer_rgba(), width, height, QImage.Format_ARGB32) 147 # 转化为QPixmap 148 self.png = QPixmap(im) 149 self.my_ui.label_11.setPixmap(self.png) # 设置文本标签的图形 150 151 def Coordinate_trans(self,origin,thate,s_point,TURN,MOVE,ZOOM,LOG_FLAG): 152 datapoint=[0,0] 153 # 平移变换 154 datapoint[0] = s_point[0] - origin[0] 155 datapoint[1] = s_point[1] - origin[1] 156 # 旋转变换 157 datapoint[0] = datapoint[0] * math.cos(thate) + datapoint[1] * math.sin(thate) 158 datapoint[1] = datapoint[1] * math.cos(thate) - datapoint[0] * math.sin(thate) 159 #坐标翻转 160 if TURN: 161 if self.cood_turn|0x02==0x03: 162 datapoint[0]=-datapoint[0] 163 if self.cood_turn|0x01==0x03: 164 datapoint[1] = -datapoint[1] 165 #坐标缩放 166 if ZOOM: 167 datapoint[0]=datapoint[0]/self.zoom[0] 168 datapoint[1] = datapoint[1] / self.zoom[1] 169 #坐标最终平移 170 if MOVE: 171 datapoint[0] = datapoint[0] + self.my_orign[0] 172 datapoint[1] = datapoint[1] + self.my_orign[1] 173 #对数分度转化 174 if LOG_FLAG: 175 if self.my_ui.checkBox_2.isChecked(): # 变换x 176 datapoint[0] = 10**datapoint[0] 177 if self.my_ui.checkBox.isChecked(): # 变换y 178 datapoint[1]=10**datapoint[1] 179 return datapoint 180 181 def openfile(self,my_MainWindow): 182 if self.key_flag==1: 183 # 打开对话框, "打开文件"(对话框的名字), '.'(打开当前的路径), '图像文件(*.jpg *.png)'(打开文件的格式) 184 openfile_name_back=QFileDialog.getOpenFileName(my_MainWindow,"选择路径",'.', '图像文件(*.jpg *.png)') 185 if len(openfile_name_back[0])==0: 186 return 187 else: 188 self.openfile_name=openfile_name_back[0] 189 self.my_ui.label_4.setText(self.openfile_name) 190 # 新建线程开始计算 191 self.send_lint=[] 192 self.send_lint.append(self.openfile_name) 193 self.send_lint.append(1) 194 self.mywork = myworkthread(self.send_lint) 195 self.mywork.finishsignal.connect(self.workend) 196 self.mywork.start() 197 self.key_flag=0 198 self.my_ui.textBrowser.append("请校准坐标系") 199 self.my_ui.pushButton.setStyleSheet('''QPushButton{background:#D23550;border-radius:5px;}''') 200 else: 201 self.my_ui.textBrowser.append("还有未完成任务") 202 203 def align(self): 204 if self.align_flag==0 and self.key_flag==0: 205 FlagUse.punlic_flag=0 206 self.my_ui.pushButton_5.setStyleSheet( 207 '''QPushButton{background:red;}QPushButton:hover{background:yellow;}''') 208 self.align_flag=1 209 self.my_ui.textBrowser.append("开始校准") 210 self.use_falg = 0 211 self.my_ui.checkBox_2.setDisabled(False) 212 self.my_ui.checkBox.setDisabled(False) 213 elif self.key_flag==1: 214 self.my_ui.textBrowser.append("暂无任务") 215 elif self.align_flag==1: 216 try: 217 # 输入参数 218 self.x0 = (float(self.my_ui.lineEdit_3.text()), float(self.my_ui.lineEdit_6.text())) 219 self.x1 = (float(self.my_ui.lineEdit_2.text()), float(self.my_ui.lineEdit_7.text())) 220 self.y0 = (float(self.my_ui.lineEdit_5.text()), float(self.my_ui.lineEdit_8.text())) 221 self.y1 = (float(self.my_ui.lineEdit_4.text()), float(self.my_ui.lineEdit_9.text())) 222 #对数转换 223 if self.my_ui.checkBox_2.isChecked():#变换x 224 self.x0 = (math.log10(self.x0[0]), self.x0[1]) 225 self.x1 = (math.log10(self.x1[0]), self.x1[1]) 226 self.y0 = (math.log10(self.y0[0]), self.y0[1]) 227 self.y1 = (math.log10(self.y1[0]), self.y1[1]) 228 if self.my_ui.checkBox.isChecked():#变换y 229 self.x0 = (self.x0[0], math.log10(self.x0[1])) 230 self.x1 = (self.x1[0], math.log10(self.x1[1])) 231 self.y0 = (self.y0[0], math.log10(self.y0[1])) 232 self.y1 = (self.y1[0], math.log10(self.y1[1])) 233 except Exception as exc: 234 error_str = str(exc) 235 self.my_ui.textBrowser.append(error_str) 236 else: 237 #判断坐标校准点是否设置完 238 for i in FlagUse.public_coord: 239 if i==(0,0): 240 self.my_ui.textBrowser.append("坐标轴定义不全") 241 return 242 self.ax0 = FlagUse.public_coord[0] 243 self.ax1 = FlagUse.public_coord[1] 244 self.ay0 = FlagUse.public_coord[2] 245 self.ay1 = FlagUse.public_coord[3] 246 #这一段是获取坐标轴在图像上绘制的两个端点 247 if(self.ax0[0]-self.ax1[0])!=0: 248 k1=(self.ax0[1]-self.ax1[1])/(self.ax0[0]-self.ax1[0]) 249 if abs(k1) == 0: 250 k1 = 1 * 10 ** -6 251 else: 252 k1=1*10**6 253 b1 = self.ax1[1] - k1 * self.ax1[0] 254 kx1=b1 255 kx2=k1*FlagUse.public_size[1]+b1 256 kx3=-b1/k1 257 kx4=(FlagUse.public_size[0]-b1)/k1 258 mx=[] 259 mx.append((0,int(kx1))) 260 mx.append((FlagUse.public_size[1],int(kx2))) 261 mx.append((int(kx3),0)) 262 mx.append((int(kx4),FlagUse.public_size[0])) 263 flag_x=0 264 m1=(0,0) 265 m2=(0,0) 266 if kx1>0 and kx1<FlagUse.public_size[0]: 267 m1=mx[0] 268 flag_x=flag_x+1 269 if kx2>0 and kx2<FlagUse.public_size[0]: 270 if flag_x!=0: 271 m2=mx[1] 272 else: 273 m1=mx[1] 274 flag_x = flag_x + 1 275 if kx3>0 and kx3<FlagUse.public_size[1]: 276 if flag_x != 0: 277 m2 = mx[2] 278 else: 279 m1 = mx[2] 280 flag_x = flag_x + 1 281 if kx4>0 and kx4<FlagUse.public_size[1]: 282 if flag_x != 0: 283 m2 = mx[3] 284 else: 285 m1 = mx[3] 286 flag_x = flag_x + 1 287 if flag_x!=2: 288 self.my_ui.textBrowser.append("坐标轴定义错误") 289 return 290 else: 291 FlagUse.public_cood_data[0]=m1 292 FlagUse.public_cood_data[1] = m2 293 if (self.ay0[0] - self.ay1[0]) != 0: 294 k2 = (self.ay0[1] - self.ay1[1]) / (self.ay0[0] - self.ay1[0]) 295 if abs(k1) == 0: 296 k2 = 1 * 10 ** -6 297 else: 298 k2 = 1 * 10 ** 6 299 b2 = self.ay1[1] - k2 * self.ay1[0] 300 ky1 = b2 301 ky2 = k2 * FlagUse.public_size[1] + b2 302 ky3 = -b2 / k2 303 ky4 = (FlagUse.public_size[0] - b2) / k2 304 my = [] 305 my.append((0, int(ky1))) 306 my.append((FlagUse.public_size[1], int(ky2))) 307 my.append((int(ky3), 0)) 308 my.append((int(ky4), FlagUse.public_size[0])) 309 flag_y = 0 310 m3 = (0, 0) 311 m4 = (0, 0) 312 if ky1 > 0 and ky1 < FlagUse.public_size[0]: 313 m3 = my[0] 314 flag_y = flag_y + 1 315 if ky2 > 0 and ky2 < FlagUse.public_size[0]: 316 if flag_y != 0: 317 m4 = my[1] 318 else: 319 m3 = my[1] 320 flag_y = flag_y + 1 321 if ky3 > 0 and ky3 < FlagUse.public_size[1]: 322 if flag_y != 0: 323 m4 = my[2] 324 else: 325 m3 = my[2] 326 flag_y = flag_y + 1 327 if ky4 > 0 and ky4 < FlagUse.public_size[1]: 328 if flag_y != 0: 329 m4 = my[3] 330 else: 331 m3 = my[3] 332 flag_y = flag_y + 1 333 if flag_y != 2: 334 self.my_ui.textBrowser.append("坐标轴定义错误") 335 return 336 else: 337 FlagUse.public_cood_data[2] = m3 338 FlagUse.public_cood_data[3] = m4 339 if k1*k2+1>0.1: 340 if abs(k1-k2)<1*10**3: 341 self.my_ui.textBrowser.append("暂不支持非直角坐标系") 342 return 343 #获取坐标原点坐标 344 orign_x=(b2-b1)/(k1-k2) 345 orign_y=k1*orign_x+b1 346 self.origin=(int(orign_x),int(orign_y)) 347 #获取坐标轴旋转角度 348 self.thate=math.atan(k1) 349 FlagUse.public_cood_origin=self.origin 350 # 判断是否翻转 351 use_x0=self.Coordinate_trans(self.origin,self.thate,self.ax0,False,False,False,False) 352 use_x1 = self.Coordinate_trans(self.origin, self.thate, self.ax1,False,False,False,False) 353 use_y0 = self.Coordinate_trans(self.origin, self.thate, self.ay0,False,False,False,False) 354 use_y1 = self.Coordinate_trans(self.origin, self.thate, self.ay1,False,False,False,False) 355 if (use_x0[0] - use_x1[0]) * (self.x0[0] -self.x1[0])<0: 356 self.cood_turn=self.cood_turn|0x01 357 if (use_y0[1] - use_y1[1]) * (self.y0[1] -self.y1[1])<0: 358 self.cood_turn=self.cood_turn|0x02 359 #获取缩放比例 360 use_x0 = self.Coordinate_trans(self.origin, self.thate, self.ax0, True, False,False,False) 361 use_x1 = self.Coordinate_trans(self.origin, self.thate, self.ax1, True, False,False,False) 362 use_y0 = self.Coordinate_trans(self.origin, self.thate, self.ay0, True, False,False,False) 363 use_y1 = self.Coordinate_trans(self.origin, self.thate, self.ay1, True, False,False,False) 364 self.zoom[0]=(use_x0[0]-use_x1[0])/(self.x0[0]-self.x1[0]) 365 self.zoom[1] = (use_y0[1] - use_y1[1]) / (self.y0[1] - self.y1[1]) 366 #获取最终平移坐标 367 use_dx=self.y0[0] 368 USE_dy=self.x0[1] 369 self.my_orign=(use_dx,USE_dy) 370 #相关标志位刷新 371 self.align_flag = 0 372 self.use_falg=1 373 self.my_ui.pushButton_5.setStyleSheet( 374 '''QPushButton{background:#00ff00;}QPushButton:hover{background:yellow;}''') 375 FlagUse.punlic_flag = 2 376 self.my_ui.textBrowser.append("坐标轴定义成功") 377 self.my_ui.checkBox_2.setDisabled(True) 378 self.my_ui.checkBox.setDisabled(True) 379 380 def savefile(self,my_MainWindow): 381 # 打开对话框, "打开文件"(对话框的名字), '.'(打开当前的路径), '图像文件(*.jpg *.png)'(打开文件的格式) 382 savefile_name_back=QFileDialog.getExistingDirectory(my_MainWindow,"选择路径") 383 if len(savefile_name_back)==0: 384 return 385 else: 386 self.savefile_name=savefile_name_back 387 self.my_ui.label.setText(self.savefile_name) 388 389 def workend(self,ins): 390 if ins[0]==1: 391 self.my_ui.textBrowser.append(ins[1]) 392 self.key_flag=1 393 self.my_ui.pushButton.setStyleSheet('''QPushButton{background:#6DDF6D;border-radius:5px;}''') 394 self.align_flag =0 395 self.my_ui.pushButton_5.setStyleSheet( 396 '''QPushButton{background:#00ff00;}QPushButton:hover{background:yellow;}''') 397 FlagUse.punlic_flag = 10 398 FlagUse.public_coord = [(0, 0), (0, 0), (0, 0), (0, 0)] 399 FlagUse.public_data_point=[] 400 self.use_falg=0 401 self.datapoint_falg = 0 402 self.my_ui.pushButton_6.setStyleSheet( 403 '''QPushButton{background:#00ff00;}QPushButton:hover{background:yellow;}''') 404 self.my_ui.checkBox_2.setDisabled(True) 405 self.my_ui.checkBox.setDisabled(True) 406 else: 407 self.my_ui.textBrowser.append(ins[1]) 408 409 def save_data(self): 410 try: 411 if os.path.exists(self.savefile_name)==False: 412 self.my_ui.textBrowser.append("路径出错") 413 except Exception as exc: 414 error_str = str(exc) 415 self.my_ui.textBrowser.append(error_str) 416 else: 417 file_name=self.my_ui.lineEdit.text() 418 if len(file_name)==0: 419 self.my_ui.textBrowser.append("文件名为空") 420 return 421 str_limit=["\\","/",":","*","?",'"',"<",">","!"] 422 for i in range(len(str_limit)): 423 if file_name.find(str_limit[i])!=-1: 424 self.my_ui.textBrowser.append("文件名格式错误") 425 return 426 usestr=self.savefile_name+"/"+file_name+".xlsx" 427 self.send_lint = [] 428 self.send_lint.append(usestr) 429 self.send_lint.append(2) 430 self.send_lint.append(self.data) 431 self.png.save("GotCurve.PNG") 432 self.mywork1 = myworkthread(self.send_lint) 433 self.mywork1.finishsignal.connect(self.workend) 434 self.mywork1.start() 435 436 #新建线程 437 class myworkthread(QThread): 438 finishsignal=QtCore.pyqtSignal(list) 439 def __init__(self,in_list): 440 super(myworkthread,self).__init__() 441 self.in_list=in_list 442 443 def run(self): 444 #耗时程序 445 if self.in_list[1]==1: 446 img = cv2.imread(self.in_list[0]) 447 labeling_task = caiya.SimpleBBoxLabeling(img) 448 backstr=labeling_task.start() 449 back_list = [] 450 back_list.append(1) 451 back_list.append(backstr) 452 else: 453 backstr = caiya.save_excel(self.in_list[0], self.in_list[2]) 454 back_list=[] 455 back_list.append(2) 456 back_list.append(backstr) 457 self.finishsignal.emit(back_list) 458 459 if __name__=="__main__": 460 my_mainwindow()