一、安装
最好python 3.8以上
pip install open3d
可以自己加清华或者其他的下载源加快下载。
读取pcd点云文件并显示
import open3d as o3d
pcd = o3d.io.read_point_cloud("./PointClouds/0120.pcd") # 读取pcd文件
print(pcd) #只是简单的打印信息:PointCloud with 113662 points.
#显示,zoom等信息是一些可选项
o3d.visualization.draw_geometries([pcd])
# o3d.visualization.draw_geometries([pcd], zoom=0.3412,
# front=[0.4257, -0.2125, -0.8795],
# lookat=[2.6172, 2.0475, 1.532],
# up=[-0.0694, -0.9768, 0.2024])
# 在同级目录下写入 copy_of_fragment.pcd文件
o3d.io.write_point_cloud("copy_of_fragment.pcd", pcd)
Pyqt5+open3d显示点云
pip install PyQt5 -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install pyqtgraph -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install pyOpenGL -i https://pypi.douban.com/simple
import sys
import open3d as o3d
import numpy as np
import pyqtgraph.opengl as gl
from PyQt5.QtWidgets import QApplication, QVBoxLayout, QPushButton, QWidget, QFileDialog
from pyqtgraph.opengl import GLViewWidget
class PyQtGraphicDemo(QWidget):
def __init__(self, parent=None):
super(PyQtGraphicDemo, self).__init__(parent)
self.resize(800, 600)
#显示控件
self.graphicsView = GLViewWidget(self)
#按钮
self.pushButton = QPushButton(self)
self.pushButton.setText("PushButton")
self.pushButton.clicked.connect(self.showCloud)
#布局
self.verticalLayout = QVBoxLayout(self)
self.verticalLayout.addWidget(self.graphicsView)
self.verticalLayout.addWidget(self.pushButton)
self.setLayout(self.verticalLayout)
def showCloud(self):
fileName, filetype = QFileDialog.getOpenFileName(self, "请选择点云:", '.', "cloud Files(*pcd *ply)")
if fileName != '':
pcd = o3d.io.read_point_cloud(fileName) # 读取点云
np_points = np.asarray(pcd.points) # 获取Numpy数组
plot = gl.GLScatterPlotItem() # 创建显示对象
plot.setData(pos=np_points, color=(1, 1, 1, 1), size=0.001, pxMode=False) # 设置显示数据
self.graphicsView.addItem(plot) # 显示点云
if __name__ == '__main__':
app = QApplication(sys.argv)
window = PyQtGraphicDemo()
window.show()
sys.exit(app.exec_())
效果图
加入自己qt工程
# -*- coding: utf-8 -*-
'''**************************************************************************
这是通用的图像识别的qt界面,具有图片检测,摄像头检测,本地视频检测的功能。
版本:1.0
内容:创建pyqt界面,用于图像识别,有基本打开图像,显示图像、检测图像,摄像头实时显示并检测,本地视频检测
时间:2021.9.13
作者:狄云
版本:2.0
内容:目前最新版界面,开始识别,停止识别,保存图像,界面大小设置等
时间:2022.10.22
作者:狄云
版本:3.0
内容:新增显示点云界面设计
时间:2022.10.22
作者:狄云
***************************************************************************'''
import sys
import cv2
import cv2 as cv
import random
import os
import numpy as np
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5 import QtWidgets
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from timeit import time
#点云显示相关
import open3d as o3d
import pyqtgraph.opengl as gl
from pyqtgraph.opengl import GLViewWidget
envpath = '/home/xxxxxx/anaconda3/envs/pytorch_gpu/lib/python3.8/site-packages/cv2/qt/plugins/platforms'
os.environ['QT_QPA_PLATFORM_PLUGIN_PATH'] = envpath
###========全局变量 定义开始=======###
# 打开的是摄像头还是本地视频
camera_or_local_flag = 0
# 识别进行中还是暂停识别中,1为摄像头,2位本地摄像头
Start_or_pause_flag = 0
result_image = ...
DISPLAY_W=1400 # 显示的宽度
DISPLAY_H=900 # 显示的高度
DISPLAY_RIGHT_W=220 # 右边按钮显示的宽度
fps = 0.0
len_last = 0
SAVE_OUTPUT=1 #保存图像
one_enter=1
def plot_one_box(x, img, color=None, label=None, line_thickness=3):
# Plots one bounding box on image img
tl = line_thickness or round(0.002 * (img.shape[0] + img.shape[1]) / 2) + 1 # line/font thickness
color = color or [random.randint(0, 255) for _ in range(3)]
c1, c2 = (int(x[0]), int(x[1])), (int(x[2]), int(x[3]))
cv2.rectangle(img, c1, c2, color, thickness=tl, lineType=cv2.LINE_AA)
if label:
tf = max(tl - 1, 1) # font thickness
t_size = cv2.getTextSize(label, 0, fontScale=tl / 3, thickness=tf)[0]
c2 = c1[0] + t_size[0], c1[1] - t_size[1] - 3
cv2.rectangle(img, c1, c2, color, -1, cv2.LINE_AA) # filled
cv2.putText(img, label, (c1[0], c1[1] - 2), 0, tl / 3, [225, 255, 255], thickness=tf, lineType=cv2.LINE_AA)
#查找系统有几个摄像头
class Camera:
def __init__(self, cam_preset_num=10):
self.cam_preset_num = cam_preset_num
def get_cam_num(self):
cnt = 0
for device in range(0, self.cam_preset_num):
stream = cv.VideoCapture(device)
grabbed = stream.grab()
stream.release()
if not grabbed:
break
cnt = cnt + 1
return cnt
class Ui_MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(Ui_MainWindow, self).__init__(parent)
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
# 1、总界面框大小 MainWindow
MainWindow.resize(DISPLAY_W+DISPLAY_RIGHT_W+100, DISPLAY_H+50) # 总界面框
# 左边界面区域:verticalLayoutWidget QWidget类
self.verticalLayoutWidget = QtWidgets.QWidget(MainWindow)
self.verticalLayoutWidget.setGeometry(QtCore.QRect(30, 25, DISPLAY_W, DISPLAY_H)) # 左边图片框。左上角坐标及宽度高度
self.verticalLayoutWidget.setStyleSheet('background-color:rgb(55,55,55)') # 设置做左边框的颜色
self.verticalLayoutWidget.setObjectName("verticalLayoutWidget")
self.verticalLayout = QtWidgets.QVBoxLayout(self.verticalLayoutWidget) # QVBoxLayout类 垂直地摆放小部件
self.verticalLayout.setContentsMargins(0, 0, 0, 0) # 设置左侧、顶部、右侧和底部边距,以便在布局周围使用。
self.verticalLayout.setObjectName("verticalLayout")
#self.label_ShowPicture = QtWidgets.QLabel(self.verticalLayoutWidget)
#self.label_ShowPicture.setObjectName("label_ShowPicture")
#self.verticalLayout.addWidget(self.label_ShowPicture)
#显示控件
self.graphicsView = GLViewWidget(self.verticalLayoutWidget)
self.graphicsView.setObjectName("graphicsView")
self.verticalLayout.addWidget(self.graphicsView)
# 右边按钮及显示结果字符的一块区域:verticalLayoutWidget_2 QWidget类
self.verticalLayoutWidget_2 = QtWidgets.QWidget(MainWindow)
self.verticalLayoutWidget_2.setGeometry(QtCore.QRect(DISPLAY_W + 50, 50, DISPLAY_RIGHT_W, DISPLAY_H)) # 右边按钮及显示结果字符的大小
# self.verticalLayoutWidget_2.setStyleSheet('background-color:rgb(155,155,155)') # 设置做左边框的颜色
self.verticalLayoutWidget_2.setObjectName("verticalLayoutWidget_2")
self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.verticalLayoutWidget_2) # QVBoxLayout类 垂直地摆放小部件
self.verticalLayout_2.setContentsMargins(0, 0, 0, 0)
self.verticalLayout_2.setObjectName("verticalLayout_2")
# 设置控件间的间距
self.verticalLayout_2.setSpacing(30)
# 按钮0 查看系统有几个摄像头:pushButton_select_pcture
self.pushButton_find_camera = QtWidgets.QPushButton(self.verticalLayoutWidget_2)
self.pushButton_find_camera.setObjectName("pushButton_find_camera")
self.verticalLayout_2.addWidget(self.pushButton_find_camera) # 将按钮1增加到
# 按钮1 打开图片:pushButton_open_picture
self.pushButton_open_picture = QtWidgets.QPushButton(self.verticalLayoutWidget_2)
self.pushButton_open_picture.setObjectName("pushButton_open_picture")
self.verticalLayout_2.addWidget(self.pushButton_open_picture)
# 按钮2 打开摄像头:pushButton_select_pcture
self.pushButton_open_camera = QtWidgets.QPushButton(self.verticalLayoutWidget_2)
self.pushButton_open_camera.setObjectName("pushButton_open_camera")
self.verticalLayout_2.addWidget(self.pushButton_open_camera) # 将按钮1增加到
# 按钮3 选择视频按钮:pushButton_select_pcture
self.pushButton_open_Local_video = QtWidgets.QPushButton(self.verticalLayoutWidget_2)
self.pushButton_open_Local_video.setObjectName("pushButton_open_Local_video")
self.verticalLayout_2.addWidget(self.pushButton_open_Local_video) # 将按钮1增加到
# 按钮4 开始识别按钮:pushButton_shibie
self.pushButton_Start_or_pause = QtWidgets.QPushButton(self.verticalLayoutWidget_2)
self.pushButton_Start_or_pause.setObjectName("pushButton_Start_or_pause")
self.verticalLayout_2.addWidget(self.pushButton_Start_or_pause)
# 按钮5 停止识别按钮:pushButton_shibie
self.pushButton_stop = QtWidgets.QPushButton(self.verticalLayoutWidget_2)
self.pushButton_stop.setObjectName("pushButton_stop")
self.verticalLayout_2.addWidget(self.pushButton_stop)
# 按钮6 显示点云按钮:pushButton_shibie
self.pushButton_PointClouds = QtWidgets.QPushButton(self.verticalLayoutWidget_2)
self.pushButton_PointClouds.setObjectName("pushButton_PointClouds")
self.verticalLayout_2.addWidget(self.pushButton_PointClouds)
# 放“图像识别结果为”这一句话
self.label = QtWidgets.QLabel(self.verticalLayoutWidget_2)
font = QtGui.QFont()
font.setPointSize(15)
self.label.setFont(font)
self.label.setObjectName("label")
self.verticalLayout_2.addWidget(self.label)
# lable_2放显示结果1
self.label_2 = QtWidgets.QLabel(self.verticalLayoutWidget_2)
font = QtGui.QFont()
font.setPointSize(15)
self.label_2.setFont(font)
self.label_2.setText("")
self.label_2.setObjectName("label_2")
self.verticalLayout_2.addWidget(self.label_2)
# lable_3放是否密集
self.label_3 = QtWidgets.QLabel(self.verticalLayoutWidget_2)
font = QtGui.QFont()
font.setPointSize(15)
self.label_3.setFont(font)
self.label_3.setText("")
self.label_3.setObjectName("label_3")
self.verticalLayout_2.addWidget(self.label_3)
self.timer_camera = QtCore.QTimer() # 初始化定时器
self.cap = cv2.VideoCapture() # 初始化摄像头
self.cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1920)
self.cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 1080)
self.CAM_NUM = 0
self.__flag_work = 0
self.x = 0
self.count = 0
# 视频显示与计时器,以及关闭识别
# 建立通信连接
self.pushButton_find_camera.clicked.connect(self.button_find_camera_click)
self.pushButton_open_camera.clicked.connect(self.button_open_camera_click)
self.timer_camera.timeout.connect(self.kaishi_shibie)
self.pushButton_open_Local_video.clicked.connect(self.pushButton_open_Local_video_click) #
self.pushButton_Start_or_pause.clicked.connect(self.pushButton_Start_or_pause_click)
self.pushButton_open_picture.clicked.connect(self.pushButton_select_pcture_click)
self.pushButton_stop.clicked.connect(self.pushButton_stop_click)
self.pushButton_PointClouds.clicked.connect(self.pushButton_PointClouds_click)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
name_picture = 0
image = None
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "点云显示系统"))
self.pushButton_find_camera.setText(_translate("MainWindow", "检查设备"))
self.pushButton_open_picture.setText(_translate("MainWindow", "图片识别"))
self.pushButton_open_camera.setText(_translate("MainWindow", "打开相机"))
self.pushButton_open_Local_video.setText(_translate("MainWindow", "选择本地视频识别"))
self.pushButton_Start_or_pause.setText(_translate("MainWindow", "开始识别"))
self.pushButton_stop.setText(_translate("MainWindow", "停止识别"))
self.pushButton_PointClouds.setText(_translate("MainWindow", "打开点云"))
# 查看系统有几个摄像头
def button_find_camera_click(self):
cam = Camera()
cam_num = cam.get_cam_num()
print(cam_num)
new_num=str(cam_num)
#self.label_2.setText(cam_num)
self.label.setText( "当前设备摄像头个数为:")
self.label_2.setText(new_num)
# 打开摄像头
def button_open_camera_click(self):
print("进入打开视频按钮")
global camera_or_local_flag
global one_enter
one_enter = 1
if self.timer_camera.isActive() == False:
flag = self.cap.open(self.CAM_NUM)
if flag != True:
print("运行到行号:", sys._getframe().f_lineno)
# 后两项分别为按钮(以|隔开,共有7种按钮类型,见示例后)、默认按钮(省略则默认为第一个按钮)
msg = QMessageBox.warning(self, "消息框标题", "请检测相机与电脑是否连接正确!", QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes)
return
else:
print("运行到行号:", sys._getframe().f_lineno)
self.cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1920)
self.cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 1080)
self.timer_camera.start(30)
camera_or_local_flag = 1 # 打开了摄像头
self.pushButton_open_camera.setText(u'关闭相机')
else:
self.timer_camera.stop()
self.cap.release()
camera_or_local_flag = 0 # 关闭了摄像头
self.label_ShowPicture.clear()
self.pushButton_open_camera.setText(u'打开相机')
# 选择图片
def pushButton_select_pcture_click(self):
print("进入选择按钮")
name_list = []
img_name, _ = QtWidgets.QFileDialog.getOpenFileName(self, "打开图片", "", "*.jpg;;*.png;;All Files(*)")
img = cv2.imread(img_name)
print(img_name)
showimg = img
[height_src, width_src, tongdao_src] = img.shape
number1111=0
showimg =cv2.putText(showimg, "fps= %.2f" % (fps), (0, 40), cv.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
cv2.imwrite('./temp/prediction.jpg', showimg)
self.result = cv2.cvtColor(showimg, cv2.COLOR_BGR2BGRA)
self.result = cv2.resize(self.result, (DISPLAY_W, DISPLAY_H), interpolation=cv2.INTER_AREA)
self.QtImg = QtGui.QImage(self.result.data, self.result.shape[1], self.result.shape[0], QtGui.QImage.Format_RGB32)
#self.label.setPixmap(QtGui.QPixmap.fromImage(self.QtImg))
self.label_ShowPicture.setPixmap(QtGui.QPixmap.fromImage(self.QtImg))
def pushButton_PointClouds_click(self):
print("进入选择点云按钮")
fileName, filetype = QFileDialog.getOpenFileName(self, "请选择点云:", '.', "cloud Files(*pcd *ply)")
if fileName != '':
pcd = o3d.io.read_point_cloud(fileName) # 读取点云
np_points = np.asarray(pcd.points) # 获取Numpy数组
plot = gl.GLScatterPlotItem() # 创建显示对象
plot.setData(pos=np_points, color=(1, 1, 1, 1), size=0.001, pxMode=False) # 设置显示数据
#self.graphicsView.addItem(plot) # 显示点云
self.graphicsView.addItem(plot)
# 选择视频
def pushButton_open_Local_video_click(self):
print("进入打开本地视频按钮")
global camera_or_local_flag
global Start_or_pause_flag
global one_enter
# 打开本地视频,则关闭摄像头的视频
self.timer_camera.stop()
self.cap.release()
camera_or_local_flag = 0 # 关闭了摄像头
Start_or_pause_flag = 0 # 0代表不识别
self.pushButton_Start_or_pause.setText(u'开始识别')
self.label_ShowPicture.clear()
self.pushButton_open_camera.setText(u'打开相机')
one_enter = 1
if self.timer_camera.isActive() == False:
print("打开本地视频")
self.fileName, self.fileType = QFileDialog.getOpenFileName(None, 'Choose file', '', '*.mp4;;*.avi')
self.cap_Local_video = cv.VideoCapture(self.fileName)
# self.timer_camera.start(30)
camera_or_local_flag = 2 # 打开了本地视频
#self.pushButton_open_Local_video.setText(u'关闭本地视频')
# 打开录像后,不进行播放,等点击开始识别后开始播放
ret, self.frame = self.cap_Local_video.read()
img = cv2.resize(self.frame, (DISPLAY_W, DISPLAY_H), interpolation=cv2.INTER_AREA)
height, width, bytesPerComponent = img.shape # 取彩色图片的长、宽、通道
bytesPerLine = 3 * width
cv.cvtColor(img, cv.COLOR_BGR2RGB, img)
QImg = QImage(img.data, width, height, bytesPerLine, QImage.Format_RGB888)
pixmap = QPixmap.fromImage(QImg)
self.label_ShowPicture.setPixmap(QPixmap(pixmap))
else:
self.timer_camera.stop()
self.cap_Local_video.release()
camera_or_local_flag = 0 # 关闭了摄像头
self.pushButton_Start_or_pause.setText(u'开始识别')
self.label_ShowPicture.clear()
self.pushButton_open_camera.setText(u'打开相机')
# 停止按钮
def pushButton_stop_click(self):
print("进入停止按钮")
global camera_or_local_flag
global Start_or_pause_flag
global one_enter
self.out.release()
self.timer_camera.stop()
self.cap.release()
camera_or_local_flag = 0 # 关闭了摄像头
Start_or_pause_flag = 0
one_enter=1
self.label_ShowPicture.clear()
self.pushButton_open_Local_video.setText(u'打开本地视频')
self.pushButton_open_camera.setText(u'打开相机')
self.pushButton_Start_or_pause.setText(u'开始识别')
# 开启按钮
def pushButton_Start_or_pause_click(self):
global camera_or_local_flag
global Start_or_pause_flag
print(camera_or_local_flag, Start_or_pause_flag)
print(254)
if camera_or_local_flag == 1: # 摄像头视频
if Start_or_pause_flag == 0:
Start_or_pause_flag = 1 # 代表开始识别
print(258)
self.timer_camera.start(30)
self.pushButton_Start_or_pause.setText(u'识别中')
# self.deep_sort() # 调用函数
else:
Start_or_pause_flag = 0 # 3代表开始识别
self.timer_camera.stop()
self.pushButton_Start_or_pause.setText(u'开始识别')
elif camera_or_local_flag == 2: # 本地视频
if Start_or_pause_flag == 0:
Start_or_pause_flag = 1 # 代表开始识别
self.timer_camera.start(30)
print(269)
print(camera_or_local_flag, Start_or_pause_flag)
self.pushButton_Start_or_pause.setText(u'识别中')
# self.deep_sort() # 调用函数
else:
Start_or_pause_flag = 0 # 0代表不识别
self.timer_camera.stop()
self.pushButton_Start_or_pause.setText(u'开始识别')
print(" 2 camera_or_local_flag =%d Start_or_pause_flag =%d", camera_or_local_flag, Start_or_pause_flag)
def kaishi_shibie(self):
global camera_or_local_flag
global Start_or_pause_flag
global result_image
global counter_zhenhao
global counter_jueduizhenhao
global fps
global len_last
global one_enter
t1 = time.time()
ret = False
fps_src=30
if camera_or_local_flag == 1 and Start_or_pause_flag == 0:
ret, self.frame = self.cap.read()
fps_src = self.cap.get(cv2.CAP_PROP_FPS) # 帧数
elif camera_or_local_flag == 2 and Start_or_pause_flag == 0: # 打开本地文件,且只显示首帧
ret, self.frame = self.cap_Local_video.read()
fps_src = self.cap_Local_video.get(cv2.CAP_PROP_FPS) # 帧数
if camera_or_local_flag == 1 and Start_or_pause_flag == 1:
ret, self.frame = self.cap.read()
fps_src = self.cap.get(cv2.CAP_PROP_FPS) # 帧数
elif camera_or_local_flag == 2 and Start_or_pause_flag == 1: # 打开本地文件,且只显示首帧
ret, self.frame = self.cap_Local_video.read()
fps_src = self.cap_Local_video.get(cv2.CAP_PROP_FPS) # 帧数
#print("417",ret, camera_or_local_flag, Start_or_pause_flag)
frame0=None
if ret != True:
print("打开图像失败 or 识别结束")
Start_or_pause_flag = 0 # 0代表不识别
self.cap.release()
self.pushButton_Start_or_pause.setText(u'开始识别')
self.out.release()
self.label_ShowPicture.clear()
one_enter = 1
self.timer_camera.stop()
return
if Start_or_pause_flag == 1:
a=int(self.cap.get(3))
b=int(self.cap.get(4))
#print(a,b)
name_list = []
img = self.frame.copy()
number1111=0
chunjing_img = self.frame.copy()
[height_src, width_src, tongdao_src] = chunjing_img.shape
if SAVE_OUTPUT and one_enter == 1:
#print("运行到行号:", sys._getframe().f_lineno)
[height, width, tongdao] = chunjing_img.shape
print(width, height, tongdao)
fourcc = cv2.VideoWriter_fourcc('m', 'p', '4', 'v')
date = time.strftime("%Y_%m_%d_%H_%M_%S")
print(date) # 输出:'2019-06-15 18:58:07'
print("运行到行号:", sys._getframe().f_lineno)
self.out = cv2.VideoWriter('./output/output_{}.mp4'.format(date), fourcc, fps_src, (width, height)) # 写入视频
one_enter = 0
if img is not None:
showimg = img.copy()
fps = (fps + (1. / (time.time() - t1))) / 2
# print("fps= %.2f" % (fps))
showimg = cv.putText(showimg, "fps= %.2f" % (fps), (0, 40), cv.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
frame0 = showimg.copy()
new_num = str(number1111)
if SAVE_OUTPUT:
# save a frame
self.out.write(frame0)
#**************************************************************************************************************************
else:
frame0 = self.frame.copy()
# 在界面实时显示结果
#print("运行到行号:", sys._getframe().f_lineno)
img = cv2.resize(frame0, (DISPLAY_W, DISPLAY_H), interpolation=cv2.INTER_AREA)
height, width, bytesPerComponent = img.shape # 取彩色图片的长、宽、通道
bytesPerLine = 3 * width
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
QImg = QImage(img.data, width, height, bytesPerLine, QImage.Format_RGB888)
pixmap = QPixmap.fromImage(QImg)
self.label_ShowPicture.setPixmap(QPixmap(pixmap))
if __name__ == '__main__':
counter_zhenhao = 3
counter_jueduizhenhao = 0
#os.system('python login_main.py') # 执行login_main.py文件,即登录界面,账号和密码为 diyun 12345
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())