Compare commits

..

13 Commits

Author SHA1 Message Date
459e551048 load from video 2024-11-19 10:54:51 +08:00
d8b29c9ea7 排除clip文件夹 2024-11-04 14:39:33 +08:00
702a6a60fe 增加clip功能,用于截取视频流 2024-10-29 15:46:53 +08:00
3c13486c0e 增加至3监视器,视频源默认从相机读取,可控制刷新 2024-10-29 14:51:56 +08:00
22e4778dce 更新测试代码 2024-10-21 08:37:51 +08:00
ea0f0829b1 更新测试代码 2024-10-21 08:35:50 +08:00
41524be8fc 调整测试函数 2024-10-21 08:33:25 +08:00
b3da69f7da 更新尺寸 2024-10-21 08:30:30 +08:00
a9302f4836 gui:更新前端按钮+增加视频buffer和抽帧 2024-10-18 19:44:15 +08:00
89b70a8fab change 2024-10-18 18:40:55 +08:00
f733f866f5 readme 2024-10-17 20:31:30 +08:00
2b01190021 readme 2024-10-17 19:55:34 +08:00
0c373550d1 ui 分离 2024-10-15 11:07:59 +08:00
3 changed files with 238 additions and 109 deletions

View File

@ -1,6 +1,6 @@
# ESD_bleeding_view_tool
## main分支
## gui分支
### 安装
@ -20,6 +20,11 @@ pdm run main
pdm run main
```
使用conda环境
```shell
pdm export -
```
安装gui环境如没有问题请跳过
```shell
sudo apt-get update

View File

@ -1,10 +1,14 @@
import sys
import cv2
import threading
import os
import shutil
import time
from core import Video, Mark
from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale,
QMetaObject, QObject, QPoint, QRect,
QMetaObject, QObject, QPoint, QRect, QTimer,
QSize, QTime, QUrl, Qt)
from PySide6.QtGui import (QAction, QBrush, QColor, QConicalGradient,
QCursor, QFont, QFontDatabase, QGradient,
@ -15,140 +19,207 @@ from PySide6.QtWidgets import (QApplication, QFileDialog,QGraphicsView, QMainWin
QMenuBar, QPushButton, QSizePolicy, QStatusBar, QGraphicsScene, QComboBox,
QTextBrowser, QWidget)
# ui设计部分
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
if not MainWindow.objectName():
MainWindow.setObjectName(u"MainWindow")
self.resize(1173, 750)
self.centralwidget = QWidget(MainWindow)
self.centralwidget.setObjectName(u"centralwidget")
self.pushButton = QPushButton(self.centralwidget)
self.pushButton.setObjectName(u"pushButton")
self.pushButton.setGeometry(QRect(880, 400, 141, 81))
self.pushButton_test = QPushButton(self.centralwidget)
self.pushButton_test.setObjectName(u"pushButton_test")
self.pushButton_2 = QPushButton(self.centralwidget)
self.pushButton_2.setObjectName(u"pushButton_2")
self.pushButton_2.setGeometry(QRect(1020, 400, 141, 81))
self.graphicsView = QGraphicsView(self.centralwidget)
self.graphicsView.setObjectName(u"graphicsView")
self.graphicsView.setGeometry(QRect(0, 0, 871, 700))
self.graphicsView_2 = QGraphicsView(self.centralwidget)
self.graphicsView_2.setObjectName(u"graphicsView_2")
self.graphicsView_3 = QGraphicsView(self.centralwidget)
self.graphicsView_3.setObjectName(u"graphicsView_3")
self.textBrowser = QTextBrowser(self.centralwidget)
self.textBrowser.setObjectName(u"textBrowser")
self.textBrowser.setGeometry(QRect(880, 80, 281, 291))
self.pushButton_3 = QPushButton(self.centralwidget)
self.pushButton_3.setObjectName(u"pushButton_3")
self.pushButton_3.setGeometry(QRect(880, 560, 141, 81))
self.pushButton_4 = QPushButton(self.centralwidget)
self.pushButton_4.setObjectName(u"pushButton_4")
self.pushButton_4.setGeometry(QRect(1020, 560, 141, 81))
self.comboBox = QComboBox(self.centralwidget)
self.comboBox.setObjectName(u"comboBox")
self.comboBox.setGeometry(QRect(1020, 530, 141, 31))
# self.pushButton_4 = QPushButton(self.centralwidget)
# self.pushButton_4.setObjectName(u"pushButton_4")
# self.comboBox = QComboBox(self.centralwidget)
# self.comboBox.setObjectName(u"comboBox")
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QMenuBar(MainWindow)
self.menubar.setObjectName(u"menubar")
self.menubar.setGeometry(QRect(0, 0, 1173, 33))
self.menu = QMenu(self.menubar)
self.menu.setObjectName(u"menu")
self.menu_2 = QMenu(self.menubar)
self.menu_2.setObjectName(u"menu_2")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QStatusBar(MainWindow)
self.statusbar.setObjectName(u"statusbar")
MainWindow.setStatusBar(self.statusbar)
self.menubar.addAction(self.menu.menuAction())
self.menubar.addAction(self.menu_2.menuAction())
self.set_size()
self.retranslateUi(MainWindow)
QMetaObject.connectSlotsByName(MainWindow)
# setupUi
# 自适应界面大小
def set_size(self, w=460, h=345):
w = w+10
h = h+10
w_button = 80
self.resize(2*w+10, h*2+100)
self.graphicsView.setGeometry(QRect(0, 0, w, h))
self.graphicsView_2.setGeometry(QRect(w+10, 0, w, h))
self.graphicsView_3.setGeometry(QRect(0, h+10, w, h))
self.textBrowser.setGeometry(QRect(w+10, h+10+30, w_button*2+10, 200))
self.pushButton.setGeometry(QRect(w+10, h+10+240, w_button, 50))
self.pushButton_2.setGeometry(QRect(w+10, h+10+300, w_button, 50))
self.pushButton_3.setGeometry(QRect(w+10+w_button+10, h+10+300, w_button, 50))
self.pushButton_test.setGeometry(QRect(w+10+w_button+10, h+10+240, w_button, 50))
# self.pushButton_4.setGeometry(QRect(w+10+w_button+10, 560, w_button, 40))
# self.comboBox.setGeometry(QRect(w+10+w_button+10, 530, w_button, 30))
def retranslateUi(self, MainWindow):
MainWindow.setWindowTitle(QCoreApplication.translate("MainWindow", u"MainWindow", None))
self.pushButton.setText(QCoreApplication.translate("MainWindow", u"Left", None))
self.pushButton_2.setText(QCoreApplication.translate("MainWindow", u"Right", None))
self.pushButton_3.setText(QCoreApplication.translate("MainWindow", u"\u5bfc\u5165\u89c6\u9891", None))
self.pushButton_4.setText(QCoreApplication.translate("MainWindow", u"\u5bfc\u5165\u6807\u7b7e", None))
self.menu.setTitle(QCoreApplication.translate("MainWindow", u"\u8f7d\u5165\u6570\u636e", None))
self.menu_2.setTitle(QCoreApplication.translate("MainWindow", u"\u6807\u7b7e\u68c0\u67e5", None))
self.pushButton.setText(QCoreApplication.translate("MainWindow", u"model", None))
self.pushButton_2.setText(QCoreApplication.translate("MainWindow", u"start", None))
self.pushButton_3.setText(QCoreApplication.translate("MainWindow", u"pause", None))
self.pushButton_test.setText(QCoreApplication.translate("MainWindow", u"load Video", None))
# self.pushButton_4.setText(QCoreApplication.translate("MainWindow", u"no function", None))
# retranslateUi
# ui逻辑控制
class MainWindow(QMainWindow, Ui_MainWindow):
def __init__(self):
self.timer_interval = 1000
self.max_width = 460
super(MainWindow, self).__init__()
self.setupUi(self)
self.pushButton.clicked.connect(self.left_frame)
self.pushButton_2.clicked.connect(self.right_frame)
self.pushButton_3.clicked.connect(self.load_video)
self.pushButton_4.clicked.connect(self.load_mark)
self.pushButton.clicked.connect(self.load_model)
self.pushButton_2.clicked.connect(self.start)
self.pushButton_3.clicked.connect(self.pause)
self.pushButton_test.clicked.connect(self.load_video)
# self.pushButton_4.clicked.connect(self.load_mark)
self.comboBox.currentIndexChanged.connect(self.name_reset)
# self.comboBox.currentIndexChanged.connect(self.name_reset)
# self.video = Video()
self.timer = QTimer()
self.timer.timeout.connect(self.timer_act)
self.scene = QGraphicsScene()
self.graphicsView.setScene(self.scene)
self.graphicsView.show()
self.now = int(18630/30)
self.is_video_set = 0
self.is_label_set = 0
self.clip = Clip()
self.txt = ""
def show_frame(self):
if not self.is_video_set or not self.is_label_set:
return
frame_num, method_raw = self.mark.read(self.now)
img = self.video.read(frame_num)
cvimg = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # 把opencv 默认BGR转为通用的RGB
def show_video(self, img = None):
if img is None:
img = self.video.read() # 读入opencv视频流
self.clip.clip_save_img(img)
y, x = img.shape[:-1]
#视频帧如果过大需要在此进行缩放,如
if x > self.max_width:
mult = self.max_width/x
img = cv2.resize(img, (0, 0), fx=mult, fy=mult, interpolation=cv2.INTER_NEAREST)
y, x = img.shape[:-1]
self.set_size(x, y)
cvimg = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # 把opencv 默认BGR转为通用的RGB
frame = QImage(cvimg, x, y, QImage.Format_RGB888)
self.scene.clear() #先清空上次的残留
self.pix = QPixmap.fromImage(frame)
self.scene.addPixmap(self.pix)
text = "帧数:"+"{:06d}".format(frame_num)+"\n"+"{:02d}".format(int(frame_num/30/60%60)) \
+":"+"{:02d}".format(int(frame_num/30))+"\n操作:"
method = self.mark.get_method(method_raw)
for i in method:
text += "\n" + i
self.textBrowser.setText(text)
def show_text(self, text="text to show", clear=0):
if clear > 0 :
self.txt = ""
self.txt += text
self.textBrowser.setText(self.txt)
self.textBrowser.show()
def left_frame(self):
if self.now > 0:
self.now -= 1
self.show_frame()
def start(self):
## 调用start函数
self.timer.start(self.timer_interval)
self.show_text("started\n")
def right_frame(self):
if self.now < self.max_mark - 1:
self.now += 1
self.show_frame()
def test(self):
print("test func run")
def pause(self):
## 调用pause函数
self.timer.stop()
self.clip.clip_save_video()
self.show_text("paused\n")
def load_video(self):
fname ,_ = QFileDialog.getOpenFileName(self, 'Open Video', '../', 'Video files (*.mp4 *.avi *.mp4 *.m4v *.mkv *.mkv)')
self.video = Video(fname)
self.is_video_set = 1
self.show_frame()
self.show_video()
def load_mark(self):
fname ,_ = QFileDialog.getOpenFileName(self, 'Open Excel Document', '../', 'Video files (*.xls *.xlsx)')
self.mark = Mark(fname)
self.max_mark = self.mark.max_frame()
self.comboBox.clear()
self.comboBox.addItems(self.mark.sheet_list())
def load_model(self):
fname ,_ = QFileDialog.getOpenFileName(self, 'Open Checkpoint Document', '../', 'Checkpoint files (*.ckpt *.pt *.pth)')
##连接模型load文件的函数
if fname == "":
return
self.show_text("loaded model "+fname+"\n")
self.is_label_set = 1
self.show_frame()
def timer_act(self):
self.show_video()
def name_reset(self):
name = self.comboBox.currentText()
self.mark.change_name(name)
self.show_frame()
class Clip():
def __init__(self):
self.img_dir = "./temp"
formatted_time = time.strftime("%Y-%m-%d %H.%M.%S")
self.clip_dir = "./clip/"+formatted_time
self.clip_num = 0
self.img_num = 0
self.init_dir("./clip")
self.init_dir(self.img_dir,1)
self.init_dir(self.clip_dir)
def init_dir(self, dir, autu_remove=0):
if os.path.exists(dir):
if autu_remove > 0:
shutil.rmtree(dir)
os.mkdir(dir)
else:
os.mkdir(dir)
def clip_save_img(self, img):
img_save_dir = self.img_dir+"/"+str(self.clip_num)
self.init_dir(img_save_dir)
cv2.imwrite(img_save_dir+"/{:05d}".format(self.img_num)+".jpg", img)
self.img_num += 1
def clip_save_video(self):
img_save_dir = self.img_dir+"/"+str(self.clip_num)
video_save_name = self.clip_dir+"/"+str(self.clip_num)+".mp4"
img_list = os.listdir(img_save_dir) # 生成图片目录下以图片名字为内容的列表
fps = 1
if len(img_list) > 0:
cvimg = cv2.imread(img_save_dir + "/" + img_list[0])
w = cvimg.shape[1]
h = cvimg.shape[0]
# fourcc = cv.VideoWriter_fourcc('M', 'J', 'P', 'G') 用于avi格式的生成
fourcc = cv2.VideoWriter.fourcc(*'mp4v') # 用于mp4格式的生成
videowriter = cv2.VideoWriter(video_save_name, fourcc, fps, (w, h)) # 创建一个写入视频对象
for img in img_list:
path = img_save_dir + "/" + img
# print(path)
frame = cv2.imread(path)
videowriter.write(frame)
videowriter.release()
self.img_num = 0
self.clip_num += 1
# def name_reset(self):
# name = self.comboBox.currentText()
# self.mark.change_name(name)
# self.show_text()

View File

@ -3,31 +3,11 @@ import cv2
import pandas as pd
import re
import numpy as np
import time
import math
import threading
interval = 30
def remove_the_blackborder(image):
img = cv2.medianBlur(image, 7) #中值滤波,去除黑色边际中可能含有的噪声干扰
b = cv2.threshold(img, 3, 255, cv2.THRESH_BINARY) #调整裁剪效果
binary_image = b[1] #二值图--具有三通道
binary_image = cv2.cvtColor(binary_image,cv2.COLOR_BGR2GRAY)
# print(binary_image.shape) #改为单通道
edges_y, edges_x = np.where(binary_image==255) ##h, w
bottom = min(edges_y)
top = max(edges_y)
height = top - bottom
left = min(edges_x)
right = max(edges_x)
height = top - bottom
width = right - left
res_image = image[bottom:bottom+height, left:left+width]
return res_image
interval = 30
def convert_video(videoname):
capture = cv2.VideoCapture(videoname)
@ -47,27 +27,100 @@ def convert_video(videoname):
else:
print('视频打开失败!')
class Mark:
def __init__(self, mark_dir):
self.df_source = pd.read_excel(mark_dir, sheet_name=None)
self.sheet = list(self.df_source.keys())
self.df = self.df_source[self.sheet[0]]
col_name = self.df.columns.tolist()
self.method = col_name[1:]
self.frame = self.df.loc[:,col_name[0]]
self.total_frame = len(self.frame)
def read(self, number):
line = self.df.loc[number,:]
rt = re.findall(r'\d+', line.iloc[0])
if len(rt) > 0:
return (int(rt[0]), line[self.method[0]:])
else:
return None
def max_frame(self):
return self.total_frame
def sheet_list(self):
return self.sheet
def get_method(self, raw):
method = []
NaN = pd.isnull(raw)
for i in range(len(raw)):
if not NaN.iloc[i]:
method.append(self.method[i])
return method
def change_name(self, name):
if name in self.sheet:
self.df = self.df_source[name]
col_name = self.df.columns.tolist()
self.frame = self.df.loc[:,col_name[0]]
self.total_frame = len(self.frame)
class Video:
def __init__(self, video_dir):
self.video_dir = video_dir
def __init__(self, video_dir=0, buffer_num_max = 3):
capture = cv2.VideoCapture(video_dir)
if capture.isOpened():
self.total_frames = int(capture.get(cv2.CAP_PROP_FRAME_COUNT))
if video_dir != 0:
self.total_frames = int(capture.get(cv2.CAP_PROP_FRAME_COUNT))
self.fps = 0
else:
self.total_frames = 0
self.fps = capture.get(cv2.CAP_PROP_FPS)
self.video = capture
else:
self.video = None
def read(self, frame_num):
self.frame_num = 0
#buffer init
self.buffer = []
self.buffer_num = 0
self.buffer_num_max = buffer_num_max
def read(self): ##测试用,从视频文件读取
cap = self.video
cap.set(cv2.CAP_PROP_POS_FRAMES, frame_num)
ret, img=cap.read()
img = self.cut_border(img)
if ret:
self.update_buffer(img)
return img
else:
return None
def cut_border(self, img):
# img = remove_the_blackborder(img)
def set_video_loop(self, show_video): ####
self.show_video_func = show_video
def video_loop(self):
ret, img=self.video.read()
if ret:
self.update_buffer(img)
self.show_video_func(img)
print("read")
def get_and_skip_frame(self, skip_num=29): #抽帧
img = self.read()
for _ in range(skip_num):
self.read()
return img
def update_buffer(self, img): #更新buffer
self.buffer.append(img)
if self.buffer_num < self.buffer_num_max:
self.buffer_num += 1
else:
self.buffer.pop(0)
def get_buffer(self): #获取buffer内容
return self.buffer
class Mark:
def __init__(self, mark_dir):