|
@@ -0,0 +1,302 @@
|
|
|
+
|
|
|
+from PyQt5.QtWidgets import QTabWidget,QSplitter, QLineEdit,QCheckBox,QLabel,QFrame,QPushButton,QMenu,QAction
|
|
|
+from PyQt5.QtGui import QPixmap,QImage,QPainter,QResizeEvent,QCloseEvent,QPaintEvent,QFont
|
|
|
+from PyQt5.QtCore import QSize,QTimer,QRect,Qt
|
|
|
+import numpy as np
|
|
|
+import def_pb2 as pb
|
|
|
+from concurrent.futures import ThreadPoolExecutor, as_completed, wait
|
|
|
+import GrpcClient as rpc
|
|
|
+from PCViewer import PCLViewer
|
|
|
+
|
|
|
+class ControlFrame(QFrame):
|
|
|
+ def __init__(self):
|
|
|
+ QFrame.__init__(self)
|
|
|
+ self.threadPool_ = ThreadPoolExecutor(5)
|
|
|
+ self.setGeometry(0, 0, 500, 500)
|
|
|
+ self.InitUI()
|
|
|
+ self.setFrameShape(self.StyledPanel)
|
|
|
+ #self.timer_ = QTimer()
|
|
|
+ #self.timer_.timeout.connect(self.Update)
|
|
|
+ #self.timer_.start(100)
|
|
|
+ def DisplayMeasureInfo(self,info : pb.MeasureInfo):
|
|
|
+ self.ErrorInfo.setText(info.error)
|
|
|
+ def OnAction(self,dtype,id):
|
|
|
+ client=rpc.GrpcStream()
|
|
|
+ ip=self.IPEdit.text()
|
|
|
+ port=int(self.PortEdit.text())
|
|
|
+ if dtype==1:
|
|
|
+ self.threadPool_.submit(client.GrabImage,ip,port,id)
|
|
|
+ if dtype==2:
|
|
|
+ self.threadPool_.submit(client.GrabCloud,ip,port,id)
|
|
|
+ def InitUI(self):
|
|
|
+
|
|
|
+ self.begstatic = QLabel(self)
|
|
|
+ self.begstatic.setText(" IP:")
|
|
|
+ self.begstatic.setGeometry(20, 5, 80, 30)
|
|
|
+ self.IPEdit = QLineEdit(self)
|
|
|
+ self.IPEdit.setText("192.168.2.45")
|
|
|
+ self.IPEdit.setGeometry(90, 5, 150, 30)
|
|
|
+
|
|
|
+ self.endstatic = QLabel(self)
|
|
|
+ self.endstatic.setText("Port:")
|
|
|
+ self.endstatic.setGeometry(20, 50, 80, 30)
|
|
|
+ self.PortEdit = QLineEdit(self)
|
|
|
+ self.PortEdit.setText("9876")
|
|
|
+ self.PortEdit.setGeometry(90, 50, 150, 30)
|
|
|
+
|
|
|
+ self.btnGrab = QPushButton(self)
|
|
|
+ self.btnGrab.setGeometry(20, 140, 100, 40)
|
|
|
+ self.btnGrab.setText("抓取图像")
|
|
|
+ self.btnGrab.clicked.connect(self.btnGrabImageClick)
|
|
|
+
|
|
|
+ self.btnCancel = QPushButton(self)
|
|
|
+ self.btnCancel.setGeometry(150, 140, 100, 40)
|
|
|
+ self.btnCancel.setText("抓取点云")
|
|
|
+ self.btnCancel.clicked.connect(self.btnGrabCloudClick)
|
|
|
+
|
|
|
+
|
|
|
+ self.btnImageStreamCheck = QCheckBox("实时图像", self)
|
|
|
+ self.btnImageStreamCheck.setGeometry(20, 90, 120, 40)
|
|
|
+ self.btnImageStreamCheck.clicked.connect(self.RealTimeImagecb)
|
|
|
+
|
|
|
+ self.btnDataStreamCheck = QCheckBox("实时结果打印", self)
|
|
|
+ self.btnDataStreamCheck.setGeometry(150, 90, 120, 40)
|
|
|
+ self.btnDataStreamCheck.clicked.connect(self.RealTimeDatacb)
|
|
|
+
|
|
|
+ self.ErrorInfo = QLabel(self)
|
|
|
+ self.ErrorInfo.setGeometry(20, 200, 250, 400)
|
|
|
+ self.ErrorInfo.setWordWrap(True)
|
|
|
+ self.ErrorInfo.setAlignment(Qt.AlignTop)
|
|
|
+ def RealTimeDatacb(self):
|
|
|
+ if self.btnDataStreamCheck.checkState()==Qt.Checked:
|
|
|
+ client=rpc.GrpcStream()
|
|
|
+ ip=self.IPEdit.text()
|
|
|
+ port=int(self.PortEdit.text())
|
|
|
+ self.threadPool_.submit(client.OpenDataStream,ip,port)
|
|
|
+ else:
|
|
|
+ client=rpc.GrpcStream()
|
|
|
+ ip=self.IPEdit.text()
|
|
|
+ port=int(self.PortEdit.text())
|
|
|
+ self.threadPool_.submit(client.CloseDataStream,ip,port)
|
|
|
+ def RealTimeImagecb(self):
|
|
|
+ if self.btnImageStreamCheck.checkState()==Qt.Checked:
|
|
|
+ self.btnGrab.setEnabled(False)
|
|
|
+ client=rpc.GrpcStream()
|
|
|
+ ip=self.IPEdit.text()
|
|
|
+ port=int(self.PortEdit.text())
|
|
|
+ self.threadPool_.submit(client.OpenImageStream,ip,port)
|
|
|
+ else:
|
|
|
+ self.btnGrab.setEnabled(True)
|
|
|
+ client=rpc.GrpcStream()
|
|
|
+ ip=self.IPEdit.text()
|
|
|
+ port=int(self.PortEdit.text())
|
|
|
+ self.threadPool_.submit(client.CloseImageStream,ip,port)
|
|
|
+ def closeEvent(self, a0: QCloseEvent) -> None:
|
|
|
+ if self.btnImageStreamCheck.checkState()==Qt.Checked:
|
|
|
+ client=rpc.GrpcStream()
|
|
|
+ ip=self.IPEdit.text()
|
|
|
+ port=int(self.PortEdit.text())
|
|
|
+ self.threadPool_.submit(client.CloseImageStream,ip,port)
|
|
|
+ if self.btnDataStreamCheck.checkState()==Qt.Checked:
|
|
|
+ client=rpc.GrpcStream()
|
|
|
+ ip=self.IPEdit.text()
|
|
|
+ port=int(self.PortEdit.text())
|
|
|
+ self.threadPool_.submit(client.CloseDataStream,ip,port)
|
|
|
+ self.threadPool_.shutdown(wait=False)
|
|
|
+ rpc.GrpcStream().close()
|
|
|
+ def btnGrabImageClick(self):
|
|
|
+ if self.btnImageStreamCheck.checkState()==Qt.Checked:
|
|
|
+ print(" 先关闭实时显示")
|
|
|
+ else :
|
|
|
+ client=rpc.GrpcStream()
|
|
|
+ ip=self.IPEdit.text()
|
|
|
+ port=int(self.PortEdit.text())
|
|
|
+ self.threadPool_.submit(client.GrabImage,ip,port,0)
|
|
|
+ def btnGrabCloudClick(self):
|
|
|
+ client=rpc.GrpcStream()
|
|
|
+ ip=self.IPEdit.text()
|
|
|
+ port=int(self.PortEdit.text())
|
|
|
+ for id in range(4):
|
|
|
+ self.threadPool_.submit(client.GrabCloud,ip,port,id+1)
|
|
|
+ def btnCancelClick(self):
|
|
|
+ pass
|
|
|
+class ImageViewer(QLabel):
|
|
|
+ def __init__(self,parent,OnAction,id):
|
|
|
+ super(ImageViewer,self).__init__(parent=parent)
|
|
|
+ self.OnAction=OnAction
|
|
|
+ self.dtype=1
|
|
|
+ self.id=id
|
|
|
+ self.image=None
|
|
|
+ self.show = False
|
|
|
+ self.setStyleSheet("border-width:1px;border-style:solid;border-color:rgb(150,150,150)")
|
|
|
+ self.timer=QTimer()
|
|
|
+ self.timer.timeout.connect(self.OnTimer)
|
|
|
+ def FlashImg(self,pixmap):
|
|
|
+ self.image=pixmap
|
|
|
+ if self.timer.isActive()==False:
|
|
|
+ self.timer.start(500)
|
|
|
+ def ShowImg(self,pixmap):
|
|
|
+ self.timer.stop()
|
|
|
+ self.show=True
|
|
|
+ self.image=pixmap
|
|
|
+ self.repaint()
|
|
|
+ def updataData(self):
|
|
|
+ self.OnAction(self.dtype,self.id)
|
|
|
+ print("%d,%d"%(self.dtype,self.id))
|
|
|
+
|
|
|
+ def contextMenuEvent(self, a0):
|
|
|
+ menu=QMenu(self)
|
|
|
+ updata_act=QAction("更新")
|
|
|
+ updata_act.triggered.connect(self.updataData)
|
|
|
+ menu.addAction(updata_act)
|
|
|
+ ret=menu.exec_(a0.globalPos())
|
|
|
+
|
|
|
+ def OnTimer(self):
|
|
|
+ self.show=not self.show
|
|
|
+ self.repaint()
|
|
|
+
|
|
|
+ def paintEvent(self, a0: QPaintEvent) -> None:
|
|
|
+ if self.show==True:
|
|
|
+ if not self.image == None:
|
|
|
+ w, h = self.size().width(),self.size().height()
|
|
|
+ iw, ih = self.image.width(), self.image.height()
|
|
|
+ painter=QPainter(self)
|
|
|
+ painter.drawPixmap(QRect(0,0,w,h),self.image,QRect(0,0,iw,ih))
|
|
|
+
|
|
|
+class PointCLViwer(QSplitter):
|
|
|
+ def __init__(self,OnAction,id):
|
|
|
+ super(PointCLViwer, self).__init__()
|
|
|
+ self.OnAction=OnAction
|
|
|
+ self.dtype=2
|
|
|
+ self.id=id
|
|
|
+ self.InitUI()
|
|
|
+ def InitUI(self):
|
|
|
+ self.pclViewer=PCLViewer()
|
|
|
+ self.addWidget(self.pclViewer)
|
|
|
+ self.setStretchFactor(0,4)
|
|
|
+ def save(self):
|
|
|
+ print("save")
|
|
|
+ def displayCloud(self,points:np.array):
|
|
|
+ self.pclViewer.displayPCL(points)
|
|
|
+ def resetViewer(self):
|
|
|
+ self.pclViewer.resetViewer()
|
|
|
+ def updataData(self):
|
|
|
+ self.OnAction(self.dtype,self.id)
|
|
|
+ def contextMenuEvent(self, a0):
|
|
|
+ menu=QMenu(self)
|
|
|
+ updata_act=QAction("更新点云")
|
|
|
+ updata_act.triggered.connect(self.updataData)
|
|
|
+ menu.addAction(updata_act)
|
|
|
+
|
|
|
+ act=QAction("还原视野")
|
|
|
+ act.triggered.connect(self.resetViewer)
|
|
|
+ menu.addAction(act)
|
|
|
+
|
|
|
+ actSave=QAction("保存")
|
|
|
+ actSave.triggered.connect(self.save)
|
|
|
+ menu.addAction(actSave)
|
|
|
+ ret=menu.exec_(a0.globalPos())
|
|
|
+
|
|
|
+class ViewerFrame(QFrame):
|
|
|
+ def __init__(self,OnAction):
|
|
|
+ super(ViewerFrame, self).__init__()
|
|
|
+ self.OnAction=OnAction
|
|
|
+ self.InitUI()
|
|
|
+ def InitUI(self):
|
|
|
+
|
|
|
+ self.table1=QTabWidget(self)
|
|
|
+ self.table2=QTabWidget(self)
|
|
|
+ self.table3=QTabWidget(self)
|
|
|
+ self.table4=QTabWidget(self)
|
|
|
+ self.table1.setTabPosition(QTabWidget.TabPosition.North)
|
|
|
+ self.table2.setTabPosition(QTabWidget.TabPosition.North)
|
|
|
+ self.table3.setTabPosition(QTabWidget.TabPosition.North)
|
|
|
+ self.table4.setTabPosition(QTabWidget.TabPosition.North)
|
|
|
+
|
|
|
+ self.panel1=ImageViewer(self,self.OnAction,1)
|
|
|
+ self.panel2=ImageViewer(self,self.OnAction,2)
|
|
|
+ self.panel3=ImageViewer(self,self.OnAction,3)
|
|
|
+ self.panel4=ImageViewer(self,self.OnAction,4)
|
|
|
+
|
|
|
+ self.pcViewer1=PointCLViwer(self.OnAction,1)
|
|
|
+ self.pcViewer2=PointCLViwer(self.OnAction,2)
|
|
|
+ self.pcViewer3=PointCLViwer(self.OnAction,3)
|
|
|
+ self.pcViewer4=PointCLViwer(self.OnAction,4)
|
|
|
+
|
|
|
+ self.table1.addTab(self.panel1,"图像")
|
|
|
+ self.table1.addTab(self.pcViewer1,"点云")
|
|
|
+ self.table2.addTab(self.panel2,"图像")
|
|
|
+ self.table2.addTab(self.pcViewer2,"点云")
|
|
|
+ self.table3.addTab(self.panel3,"图像")
|
|
|
+ self.table3.addTab(self.pcViewer3,"点云")
|
|
|
+ self.table4.addTab(self.panel4,"图像")
|
|
|
+ self.table4.addTab(self.pcViewer4,"点云")
|
|
|
+
|
|
|
+ def closeEvent(self, a0: QCloseEvent) -> None:
|
|
|
+ pass
|
|
|
+ def resizeEvent(self, a0: QResizeEvent) -> None:
|
|
|
+ w, h = self.size().width(), self.size().height()
|
|
|
+ w=w-15
|
|
|
+ h=h-15
|
|
|
+ self.table1.setGeometry(5, 5, w/2, h/2)
|
|
|
+ self.table2.setGeometry(10+w/2, 5, w/2, h/2)
|
|
|
+ self.table3.setGeometry(5, 10+h/2, w/2, h/2)
|
|
|
+ self.table4.setGeometry(10+w/2, 10+h/2, w/2, h/2)
|
|
|
+
|
|
|
+ def PbImg2QPix(self,image:pb.Image):
|
|
|
+ img1=image
|
|
|
+ w=img1.width
|
|
|
+ h=img1.height
|
|
|
+ c=img1.channel
|
|
|
+ btarry=bytearray(img1.data)
|
|
|
+ npdata = np.frombuffer(btarry, dtype=np.uint8)
|
|
|
+ if c==3:
|
|
|
+ npdata = npdata.reshape([h,w,c])
|
|
|
+ qimg=QImage(npdata.data,w,h,QImage.Format_RGB888)
|
|
|
+ if c==1:
|
|
|
+ npdata = npdata.reshape([h,w])
|
|
|
+ qimg=QImage(npdata.data,w,h,QImage.Format_Grayscale8)
|
|
|
+ pix=QPixmap(qimg)
|
|
|
+ return pix
|
|
|
+ def PbCloud2Pts(self,cloud:pb.PointCloud):
|
|
|
+
|
|
|
+ size=cloud.size
|
|
|
+ btarry=bytearray(cloud.data)
|
|
|
+ npdata = np.frombuffer(btarry, dtype=np.short)
|
|
|
+ points= npdata.reshape([size,4])/32750.0 *5.0
|
|
|
+ return points
|
|
|
+ def DisplayFrame(self,frame : pb.ResFrame):
|
|
|
+ if frame.HasField("images"):
|
|
|
+ self.DisplayImage(frame.images)
|
|
|
+ if frame.HasField("clouds"):
|
|
|
+ self.DisplayCloud(frame.clouds)
|
|
|
+ def DisplayImage(self,images:pb.ResImage):
|
|
|
+ if images.HasField("img1"):
|
|
|
+ self.panel1.ShowImg(self.PbImg2QPix(images.img1))
|
|
|
+ if images.HasField("img2"):
|
|
|
+ self.panel2.ShowImg(self.PbImg2QPix(images.img2))
|
|
|
+ if images.HasField("img3"):
|
|
|
+ self.panel3.ShowImg(self.PbImg2QPix(images.img3))
|
|
|
+ if images.HasField("img4"):
|
|
|
+ self.panel4.ShowImg(self.PbImg2QPix(images.img4))
|
|
|
+ def DisplayCloud(self,clouds:pb.ResCloud):
|
|
|
+ if clouds.HasField("cloud1"):
|
|
|
+ self.pcViewer1.displayCloud(self.PbCloud2Pts(clouds.cloud1))
|
|
|
+ if clouds.HasField("cloud2"):
|
|
|
+ self.pcViewer2.displayCloud(self.PbCloud2Pts(clouds.cloud2))
|
|
|
+ if clouds.HasField("cloud3"):
|
|
|
+ self.pcViewer3.displayCloud(self.PbCloud2Pts(clouds.cloud3))
|
|
|
+ if clouds.HasField("cloud4"):
|
|
|
+ self.pcViewer4.displayCloud(self.PbCloud2Pts(clouds.cloud4))
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|