Compare commits

..

5 Commits

Author SHA1 Message Date
7396d43a6d 兼容gui分支 2024-11-04 14:38:40 +08:00
49ac75b280 Merge branch 'main' of https://gitea.airo.cc/Fiber/ESD_bleeding_view_tool 2024-10-17 20:00:05 +08:00
aeb3582a6c readme 2024-10-17 19:56:39 +08:00
376fb7c6c0 更新 'README.md' 2024-10-16 17:59:27 +08:00
bf953e7afb 更新 'README.md' 2024-10-16 17:58:22 +08:00
3 changed files with 109 additions and 238 deletions

View File

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

View File

@ -1,14 +1,10 @@
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, QTimer,
QMetaObject, QObject, QPoint, QRect,
QSize, QTime, QUrl, Qt)
from PySide6.QtGui import (QAction, QBrush, QColor, QConicalGradient,
QCursor, QFont, QFontDatabase, QGradient,
@ -19,207 +15,140 @@ 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_test = QPushButton(self.centralwidget)
self.pushButton_test.setObjectName(u"pushButton_test")
self.pushButton.setGeometry(QRect(880, 400, 141, 81))
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_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.graphicsView.setGeometry(QRect(0, 0, 871, 700))
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_4 = QPushButton(self.centralwidget)
# self.pushButton_4.setObjectName(u"pushButton_4")
# self.comboBox = QComboBox(self.centralwidget)
# self.comboBox.setObjectName(u"comboBox")
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))
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.set_size()
self.menubar.addAction(self.menu.menuAction())
self.menubar.addAction(self.menu_2.menuAction())
self.retranslateUi(MainWindow)
QMetaObject.connectSlotsByName(MainWindow)
# 自适应界面大小
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))
# setupUi
def retranslateUi(self, MainWindow):
MainWindow.setWindowTitle(QCoreApplication.translate("MainWindow", u"MainWindow", 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))
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))
# 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.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.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.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.clip = Clip()
self.txt = ""
self.now = int(18630/30)
self.is_video_set = 0
self.is_label_set = 0
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)
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
y, x = img.shape[:-1]
frame = QImage(cvimg, x, y, QImage.Format_RGB888)
self.scene.clear() #先清空上次的残留
self.pix = QPixmap.fromImage(frame)
self.scene.addPixmap(self.pix)
def show_text(self, text="text to show", clear=0):
if clear > 0 :
self.txt = ""
self.txt += text
self.textBrowser.setText(self.txt)
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)
self.textBrowser.show()
def start(self):
## 调用start函数
self.timer.start(self.timer_interval)
self.show_text("started\n")
def left_frame(self):
if self.now > 0:
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 right_frame(self):
if self.now < self.max_mark - 1:
self.now += 1
self.show_frame()
def load_video(self):
fname ,_ = QFileDialog.getOpenFileName(self, 'Open Video', '../', 'Video files (*.mp4 *.avi *.mp4 *.m4v *.mkv *.mkv)')
self.video = Video(fname)
self.show_video()
self.is_video_set = 1
self.show_frame()
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")
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 timer_act(self):
self.show_video()
self.is_label_set = 1
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()
def name_reset(self):
name = self.comboBox.currentText()
self.mark.change_name(name)
self.show_frame()

View File

@ -3,11 +3,31 @@ import cv2
import pandas as pd
import re
import numpy as np
import time
import math
import threading
interval = 30
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
def convert_video(videoname):
capture = cv2.VideoCapture(videoname)
@ -27,100 +47,27 @@ 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=0, buffer_num_max = 3):
def __init__(self, video_dir):
self.video_dir = video_dir
capture = cv2.VideoCapture(video_dir)
if capture.isOpened():
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.total_frames = int(capture.get(cv2.CAP_PROP_FRAME_COUNT))
self.video = capture
else:
self.video = None
self.frame_num = 0
#buffer init
self.buffer = []
self.buffer_num = 0
self.buffer_num_max = buffer_num_max
def read(self): ##测试用,从视频文件读取
def read(self, frame_num):
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 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()
def cut_border(self, img):
# img = remove_the_blackborder(img)
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):