class MainProgram(MainUI): def __init__(self, parent=None): super(MainProgram, self).__init__() self.__initVariable() def __initVariable(self): self.projectFile = None self.database = None self.cpManager = None self.cirManager = None self.title = '' #窗口标题 #当前模式 #-1 尚未打开工程 #0 一般模式 #1 选择控制点模式 #2 选择基桩模式 self.currentMode = 0 self.tmpObject = None self.geoCorrectMode = 0 #检查当前状态 def __checkMode(self, mode): if self.database is None: return False if self.currentMode != mode: return False return True #新建工程 def newProject(self): if self.projectFile is not None: QMessageBox.information(self, '提示', '请先关闭当前工程') return self.projectFile, ext = QFileDialog.getSaveFileName( self, "新建工程文件", '', "Project File (*.pro)") if len(self.projectFile) > 0: #创建数据库 self.database = DataBase(self.projectFile) self.database.setSQLFile(self.programPath + '/config/database.sql') self.database.createDB() #连接数据库 self.database.connectDB() self.title = os.path.split(self.projectFile)[1] #获取文件名 self.title = self.windowTitle() + '——' + self.title self.setWindowTitle(self.title) else: self.projectFile = None #导入图像 def importImages(self): if not self.__checkMode(0): return files, ext = QFileDialog.getOpenFileNames(self, "导入图像", '', "Image Files (*.jpg *tif)") if len(files) > 0: self.database.insertImage(files) ids, files, states = self.database.getImages() self.centerUi.fileViewer.insertFiles(ids, files, states) #打开工程 def openProject(self): if self.projectFile is not None: QMessageBox.information(self, '提示', '请先关闭当前工程') return self.projectFile, ext = QFileDialog.getOpenFileName( self, "文件选择", './', "pro Files (*.pro)") if len(self.projectFile) > 0: #连接数据库 self.database = DataBase(self.projectFile) self.database.connectDB() #查询图像 ids, files, states = self.database.getImages() self.centerUi.fileViewer.insertFiles(ids, files, states) #显示文件名列表 self.geoCorrectMode = self.database.getCorrectMode() self.title = os.path.split(self.projectFile)[1] #获取文件名 self.title = self.windowTitle() + '——' + self.title self.setWindowTitle(self.title) else: self.projectFile = None # 设置校正模式 def setParmsMode(self): if not self.__checkMode(0): return dialog = GeoCorrectDialog(self.geoCorrectMode, self) lastMode = self.geoCorrectMode self.geoCorrectMode = dialog.getMode() if lastMode != self.geoCorrectMode: self.database.setCorrectMode(self.geoCorrectMode) # 更新数据库所有数据 self.database.resetImageState(self.geoCorrectMode) self.centerUi.fileViewer.resetState() #导入控制点 def importControlPoint(self): if not self.__checkMode(0): return file, ext = QFileDialog.getOpenFileName( self, "文件选择", './', "Data Files (*.xlsx *.xls *.txt)") if len(file) > 0: #导入 pointsFile = ImportPoints(file) names, points = pointsFile.getPoints() #保持 self.database.insertCPoints(names, points) num = len(names) if num > 0: QMessageBox.information(self, '成功', '共导入' + str(num) + '个点') #查看控制点 def lookControlPoint(self): if not self.__checkMode(0): return _, names, points = self.database.getCPoints() table = CPointsTable(self) table.setContents(names, points) table.exec_() #导入CAD def importCAD(self): if not self.__checkMode(0): return ImportCADDiaolg(self.database, self).exec_() #查看导入的CAD数据 def lookCircle(self): if not self.__checkMode(0): return look = LookCircleDialog(self) look.exec_() if look.flag == 1: ids, names, locations, radius = self.database.getCircles() table = CircleTable(self) table.setDataBase(self.database) table.setContents(ids, names, locations, radius) table.exec_() elif look.flag == 2: _, names, locations, radius = self.database.getCircles() self.centerUi.showImportCircle(names, locations, radius) #选点模式 def selectCPoints(self): if not self.__checkMode(0): return self.currentMode = 1 ### self.centerUi.setMode(1) self.centerUi.fileViewer.selectImage.connect( self.__selectCPointsManager) title = self.title + '(选点模式)' self.setWindowTitle(title) def __selectCPointsManager(self, image_idx, file): if not os.path.exists(file): QMessageBox.information(self, '失败', '图像不存在,请检查路径') return name = os.path.basename(file) title = self.title + '——' + name + '(选点模式)' self.setWindowTitle(title) self.centerUi.addPointListView() self.cpManager = PointsManager(mode=self.geoCorrectMode) self.cpManager.setWidget(self.centerUi.imageViewer, self.centerUi.pLister, self.centerUi.fileViewer) self.cpManager.setDataBase(self.database) self.cpManager.setCurrentImageID(image_idx) #退出选点模式 def exitCPoints(self): if not self.__checkMode(1): return self.currentMode = 0 # if self.cpManager is None: # return self.centerUi.setMode(0) self.centerUi.deletePointListView() self.cpManager = None self.setWindowTitle(self.title) self.centerUi.fileViewer.selectImage.disconnect( self.__selectCPointsManager) #计算每张图像上的圆 def estimateCircles(self): if not self.__checkMode(0): return estDialog = EstCirclesDialog(self.geoCorrectMode, self) estDialog.setDBFile(self.projectFile) estDialog.exec_() #选圆模式 def selectCircles(self): if not self.__checkMode(0): return self.currentMode = 2 self.centerUi.setMode(2) self.centerUi.fileViewer.selectImage.connect( self.__selectCirclesManager) title = self.title + '(标注基桩模式)' self.setWindowTitle(title) def __selectCirclesManager(self, image_idx, file): if not os.path.exists(file): QMessageBox.information(self, '失败', '图像不存在,请检查路径') return name = os.path.basename(file) title = self.title + '——' + name + '(标注基桩模式)' programFile = self.programPath + '/modules/segment.exe' self.setWindowTitle(title) self.centerUi.addCircleListView() self.cirManager = CirclesManager(self.geoCorrectMode) self.cirManager.setsegmentProgram(programFile) self.cirManager.setWidget(self.centerUi.imageViewer, self.centerUi.cLister, self.centerUi.fileViewer) self.cirManager.setDataBase(self.database) self.cirManager.setCurrentImageID(image_idx, self) #退出选圆模式 def exitCircles(self): if not self.__checkMode(2): return self.currentMode = 0 # if self.cirManager is None: # return self.centerUi.setMode(0) self.centerUi.deleteCircleListView() self.cirManager = None self.setWindowTitle(self.title) self.centerUi.fileViewer.selectImage.disconnect( self.__selectCirclesManager) #统计结果 def collect(self): if not self.__checkMode(0): return collDialog = CollCirclesDialog(self) collDialog.setDBFile(self.projectFile) collDialog.exec_() #查看报告 def lookReport(self): if not self.__checkMode(0): return names, errors = self.database.getReportWithoutCoords() table = ReportTable(self) table.setContents(names, errors) table.exec_() #导出报告 def exportReport(self): if not self.__checkMode(0): return names, points, point_r, gPoints, gPoints_r, errors = self.database.getReport( ) file, ext = QFileDialog.getSaveFileName(self, "文件保存", './', "Excel Files (*.xls)") if len(file) > 0: report = Report(file) report.setContents(names, points, point_r, gPoints, gPoints_r, errors) QMessageBox.information(self, '成功', '导出成功!') #导出图像 def exportComposite(self): if not self.__checkMode(0): return programFile = self.programPath + '/modules/composite.exe' compDialog = CompositeDialog(self) compDialog.setParms(programFile, self.projectFile) compDialog.exec_() #查看拼接后的图像(与圆叠加显示) def lookComposite(self): if not self.__checkMode(0): return file, ext = QFileDialog.getOpenFileName(self, "文件选择", '', "Image (*.tif)") if len(file) > 0: self.centerUi.showImportComposite() self.tmpObject = LookComposite(self) self.tmpObject.setImageViewer(self.centerUi.imageViewer) self.tmpObject.setFile(file, self.projectFile) #相机表达参数 def caliParmsOpen(self): command = self.programPath + '/modules/calib.exe' # os.system(command) subprocess.Popen(command, shell=False, close_fds=True) #图片畸变矫正 def undistortOpen(self): command = self.programPath + '/modules/undist.exe' # os.system(command) subprocess.Popen(command, shell=False, close_fds=True) # def closeEvent(self,event): # if self.database is not None: # self.database.closeDB() # def __del__(self): if self.database is not None: self.database.closeDB()
class CirclesAssign(QObject): processImage=pyqtSignal(int) def __init__(self,dbFile, geoCorrectMode): super(CirclesAssign,self).__init__() self.geoCorrectMode=geoCorrectMode self.database=DataBase(dbFile) self.database.connectDB() self.__initVariable() def __del__(self): self.database.closeDB() def __initVariable(self): self.width=None self.height=None # self.radius=None #下面的,长度相同 self.ids=[]#图像id号 self.parms=[]#图像转换参数 self.limits=[]#图像范围 def run(self): if not self.updateLimit(): return False self.__getCircles() return True #更新图像的四个点坐标范围 def updateLimit(self): if not self.__getImage(): return False self.__convertLimits() return True def __getImage(self): self.ids,images,self.parms=self.database.getImageTransformParmsByState() num=len(self.ids) #发送图像个数 self.processImage.emit(num) if num==0: return False #获取图像尺寸 img=Image.open(images[0]) self.width,self.height=img.size del img return True #计算每张图的地理坐标范围,并保存至数据库 def __convertLimits(self): cf=CoordsTransform() pixels=[[0,0],[0,self.height-1],[self.width-1,self.height-1],[self.width-1,0]] #计算 for idx,parm in zip(self.ids,self.parms): cf.setParms(parm) limit=cf.pixelsToGrounds(pixels) self.limits.append(limit) #保存 self.database.updateImageLimit(self.ids,self.limits) #读取圆信息并开始处理 def __getCircles(self): idCs,_,locations,radius=self.database.getCircles() if len(idCs)==0: self.processImage.emit(len(self.limits)-1) return # self.radius=radius[0] idCs=np.matrix(idCs) locations=np.matrix(locations) #### self.__filter(idCs,locations,radius) #根据地理坐标范围过滤,并求转换坐标 def __filter(self,idCs,points,radius): cf=CoordsTransform() #对每张图 for i,limit in enumerate(self.limits): #过滤的结果 index=self.__pointsInRect(limit,points) #没有圆落在该图像内 if index[0].size==0: self.processImage.emit(i) continue #位于某图像上的圆的id idCs_Image=idCs.T[index].tolist()[0] #位于某图像上的圆的地理坐标 grounds_Image=points[index[0]].tolist() #计算对应的像素坐标 cf.setParms(self.parms[i]) #计算像素半径 radiusPixel=cf.lengthGroundsToPixels(radius[i]) if self.geoCorrectMode==0: pixels = cf.groundsToPixels(grounds_Image) else: if self.geoCorrectMode == 1: coordsTool = GeoCorrect1Poly() polyParms = self.database.getGeo1PloyParms(self.ids[i]) elif self.geoCorrectMode == 2: coordsTool = GeoCorrect2Poly() polyParms=self.database.getGeo2PloyParms(self.ids[i]) coordsTool.setParms(polyParms) pixels=coordsTool.groundsToPixels(grounds_Image) self.__saveCirclesInImageToDB(self.ids[i],idCs_Image,pixels,radiusPixel) #发送当前正在处理的图像序号 self.processImage.emit(i) #保存至数据库 def __saveCirclesInImageToDB(self,image_id,circle_ids,pixels,radius): self.database.insertSelectCircle(image_id,circle_ids,pixels,radius) #圆是否在矩形中,返回在矩形中的序号(行号) def __pointsInRect(self,limit,points): num=points.shape[0] limit=np.matrix(limit) #矩形框逆时针四个点 p1=limit[0] p2=limit[1] p3=limit[2] p4=limit[3] #向量 p2p0=points-p2 p1p2=p2-p1 p3p0=points-p3 p3p4=p4-p3 p1p0=points-p1 p1p4=p4-p1 p2p0=points-p2 p2p3=p3-p2 #(x1,y1)x(x2,y2)=x1*y2-x2*y1 #p2p0 x p1p2 s1=p2p0[:,0]*p1p2[0,1]-p1p2[0,0]*p2p0[:,1] #p3p0 X p3p4 s2=p3p0[:,0]*p3p4[0,1]-p3p4[0,0]*p3p0[:,1] #p1p0 x p1p4 s3=p1p0[:,0]*p1p4[0,1]-p1p4[0,0]*p1p0[:,1] #p2p0 x p2p3 s4=p2p0[:,0]*p2p3[0,1]-p2p3[0,0]*p2p0[:,1] d1=np.multiply(s1,s2)>0 d2=np.multiply(s3,s4)<0 flag=d1 & d2 return np.where(flag==True)