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

View File

@ -1,14 +1,10 @@
import sys import sys
import cv2 import cv2
import threading
import os
import shutil
import time
from core import Video, Mark from core import Video, Mark
from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale, from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale,
QMetaObject, QObject, QPoint, QRect, QTimer, QMetaObject, QObject, QPoint, QRect,
QSize, QTime, QUrl, Qt) QSize, QTime, QUrl, Qt)
from PySide6.QtGui import (QAction, QBrush, QColor, QConicalGradient, from PySide6.QtGui import (QAction, QBrush, QColor, QConicalGradient,
QCursor, QFont, QFontDatabase, QGradient, QCursor, QFont, QFontDatabase, QGradient,
@ -19,207 +15,140 @@ from PySide6.QtWidgets import (QApplication, QFileDialog,QGraphicsView, QMainWin
QMenuBar, QPushButton, QSizePolicy, QStatusBar, QGraphicsScene, QComboBox, QMenuBar, QPushButton, QSizePolicy, QStatusBar, QGraphicsScene, QComboBox,
QTextBrowser, QWidget) QTextBrowser, QWidget)
# ui设计部分
class Ui_MainWindow(object): class Ui_MainWindow(object):
def setupUi(self, MainWindow): def setupUi(self, MainWindow):
if not MainWindow.objectName(): if not MainWindow.objectName():
MainWindow.setObjectName(u"MainWindow") MainWindow.setObjectName(u"MainWindow")
self.resize(1173, 750)
self.centralwidget = QWidget(MainWindow) self.centralwidget = QWidget(MainWindow)
self.centralwidget.setObjectName(u"centralwidget") self.centralwidget.setObjectName(u"centralwidget")
self.pushButton = QPushButton(self.centralwidget) self.pushButton = QPushButton(self.centralwidget)
self.pushButton.setObjectName(u"pushButton") self.pushButton.setObjectName(u"pushButton")
self.pushButton_test = QPushButton(self.centralwidget) self.pushButton.setGeometry(QRect(880, 400, 141, 81))
self.pushButton_test.setObjectName(u"pushButton_test")
self.pushButton_2 = QPushButton(self.centralwidget) self.pushButton_2 = QPushButton(self.centralwidget)
self.pushButton_2.setObjectName(u"pushButton_2") self.pushButton_2.setObjectName(u"pushButton_2")
self.pushButton_2.setGeometry(QRect(1020, 400, 141, 81))
self.graphicsView = QGraphicsView(self.centralwidget) self.graphicsView = QGraphicsView(self.centralwidget)
self.graphicsView.setObjectName(u"graphicsView") self.graphicsView.setObjectName(u"graphicsView")
self.graphicsView_2 = QGraphicsView(self.centralwidget) self.graphicsView.setGeometry(QRect(0, 0, 871, 700))
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 = QTextBrowser(self.centralwidget)
self.textBrowser.setObjectName(u"textBrowser") self.textBrowser.setObjectName(u"textBrowser")
self.textBrowser.setGeometry(QRect(880, 80, 281, 291))
self.pushButton_3 = QPushButton(self.centralwidget) self.pushButton_3 = QPushButton(self.centralwidget)
self.pushButton_3.setObjectName(u"pushButton_3") self.pushButton_3.setObjectName(u"pushButton_3")
# self.pushButton_4 = QPushButton(self.centralwidget) self.pushButton_3.setGeometry(QRect(880, 560, 141, 81))
# self.pushButton_4.setObjectName(u"pushButton_4") self.pushButton_4 = QPushButton(self.centralwidget)
# self.comboBox = QComboBox(self.centralwidget) self.pushButton_4.setObjectName(u"pushButton_4")
# self.comboBox.setObjectName(u"comboBox") 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) 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 = QStatusBar(MainWindow)
self.statusbar.setObjectName(u"statusbar") self.statusbar.setObjectName(u"statusbar")
MainWindow.setStatusBar(self.statusbar) MainWindow.setStatusBar(self.statusbar)
self.set_size()
self.menubar.addAction(self.menu.menuAction())
self.menubar.addAction(self.menu_2.menuAction())
self.retranslateUi(MainWindow) self.retranslateUi(MainWindow)
QMetaObject.connectSlotsByName(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): def retranslateUi(self, MainWindow):
MainWindow.setWindowTitle(QCoreApplication.translate("MainWindow", u"MainWindow", None)) MainWindow.setWindowTitle(QCoreApplication.translate("MainWindow", u"MainWindow", None))
self.pushButton.setText(QCoreApplication.translate("MainWindow", u"model", None)) self.pushButton.setText(QCoreApplication.translate("MainWindow", u"Left", None))
self.pushButton_2.setText(QCoreApplication.translate("MainWindow", u"start", None)) self.pushButton_2.setText(QCoreApplication.translate("MainWindow", u"Right", None))
self.pushButton_3.setText(QCoreApplication.translate("MainWindow", u"pause", None)) self.pushButton_3.setText(QCoreApplication.translate("MainWindow", u"\u5bfc\u5165\u89c6\u9891", None))
self.pushButton_test.setText(QCoreApplication.translate("MainWindow", u"load Video", None)) self.pushButton_4.setText(QCoreApplication.translate("MainWindow", u"\u5bfc\u5165\u6807\u7b7e", None))
# self.pushButton_4.setText(QCoreApplication.translate("MainWindow", u"no function", 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 # retranslateUi
# ui逻辑控制
class MainWindow(QMainWindow, Ui_MainWindow): class MainWindow(QMainWindow, Ui_MainWindow):
def __init__(self): def __init__(self):
self.timer_interval = 1000
self.max_width = 460
super(MainWindow, self).__init__() super(MainWindow, self).__init__()
self.setupUi(self) self.setupUi(self)
self.pushButton.clicked.connect(self.load_model) self.pushButton.clicked.connect(self.left_frame)
self.pushButton_2.clicked.connect(self.start) self.pushButton_2.clicked.connect(self.right_frame)
self.pushButton_3.clicked.connect(self.pause) self.pushButton_3.clicked.connect(self.load_video)
self.pushButton_test.clicked.connect(self.load_video) self.pushButton_4.clicked.connect(self.load_mark)
# 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.scene = QGraphicsScene()
self.graphicsView.setScene(self.scene) self.graphicsView.setScene(self.scene)
self.graphicsView.show() self.graphicsView.show()
self.clip = Clip() self.now = int(18630/30)
self.is_video_set = 0
self.txt = "" self.is_label_set = 0
def show_video(self, img = None): def show_frame(self):
if img is None: if not self.is_video_set or not self.is_label_set:
img = self.video.read() # 读入opencv视频流 return
self.clip.clip_save_img(img) frame_num, method_raw = self.mark.read(self.now)
y, x = img.shape[:-1] img = self.video.read(frame_num)
#视频帧如果过大需要在此进行缩放,如
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 cvimg = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # 把opencv 默认BGR转为通用的RGB
y, x = img.shape[:-1]
frame = QImage(cvimg, x, y, QImage.Format_RGB888) frame = QImage(cvimg, x, y, QImage.Format_RGB888)
self.scene.clear() #先清空上次的残留 self.scene.clear() #先清空上次的残留
self.pix = QPixmap.fromImage(frame) self.pix = QPixmap.fromImage(frame)
self.scene.addPixmap(self.pix) self.scene.addPixmap(self.pix)
def show_text(self, text="text to show", clear=0): text = "帧数:"+"{:06d}".format(frame_num)+"\n"+"{:02d}".format(int(frame_num/30/60%60)) \
if clear > 0 : +":"+"{:02d}".format(int(frame_num/30))+"\n操作:"
self.txt = "" method = self.mark.get_method(method_raw)
self.txt += text for i in method:
self.textBrowser.setText(self.txt) text += "\n" + i
self.textBrowser.setText(text)
self.textBrowser.show() self.textBrowser.show()
def start(self): def left_frame(self):
## 调用start函数 if self.now > 0:
self.timer.start(self.timer_interval) self.now -= 1
self.show_text("started\n") self.show_frame()
def right_frame(self):
def test(self): if self.now < self.max_mark - 1:
print("test func run") self.now += 1
self.show_frame()
def pause(self):
## 调用pause函数
self.timer.stop()
self.clip.clip_save_video()
self.show_text("paused\n")
def load_video(self): def load_video(self):
fname ,_ = QFileDialog.getOpenFileName(self, 'Open Video', '../', 'Video files (*.mp4 *.avi *.mp4 *.m4v *.mkv *.mkv)') fname ,_ = QFileDialog.getOpenFileName(self, 'Open Video', '../', 'Video files (*.mp4 *.avi *.mp4 *.m4v *.mkv *.mkv)')
self.video = Video(fname) self.video = Video(fname)
self.show_video() self.is_video_set = 1
self.show_frame()
def load_model(self): def load_mark(self):
fname ,_ = QFileDialog.getOpenFileName(self, 'Open Checkpoint Document', '../', 'Checkpoint files (*.ckpt *.pt *.pth)') fname ,_ = QFileDialog.getOpenFileName(self, 'Open Excel Document', '../', 'Video files (*.xls *.xlsx)')
##连接模型load文件的函数 self.mark = Mark(fname)
if fname == "": self.max_mark = self.mark.max_frame()
return
self.show_text("loaded model "+fname+"\n")
def timer_act(self): self.comboBox.clear()
self.show_video() self.comboBox.addItems(self.mark.sheet_list())
class Clip(): self.is_label_set = 1
def __init__(self): self.show_frame()
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): def name_reset(self):
if os.path.exists(dir): name = self.comboBox.currentText()
if autu_remove > 0: self.mark.change_name(name)
shutil.rmtree(dir) self.show_frame()
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,12 +3,32 @@ import cv2
import pandas as pd import pandas as pd
import re import re
import numpy as np 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): def convert_video(videoname):
capture = cv2.VideoCapture(videoname) capture = cv2.VideoCapture(videoname)
total_frames = int(capture.get(cv2.CAP_PROP_FRAME_COUNT)) total_frames = int(capture.get(cv2.CAP_PROP_FRAME_COUNT))
@ -27,101 +47,28 @@ def convert_video(videoname):
else: else:
print('视频打开失败!') 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: 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) capture = cv2.VideoCapture(video_dir)
if capture.isOpened(): if capture.isOpened():
if video_dir != 0:
self.total_frames = int(capture.get(cv2.CAP_PROP_FRAME_COUNT)) 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 self.video = capture
else: else:
self.video = None self.video = None
self.frame_num = 0 def read(self, frame_num):
#buffer init
self.buffer = []
self.buffer_num = 0
self.buffer_num_max = buffer_num_max
def read(self): ##测试用,从视频文件读取
cap = self.video cap = self.video
cap.set(cv2.CAP_PROP_POS_FRAMES, frame_num)
ret, img=cap.read() ret, img=cap.read()
img = self.cut_border(img)
if ret: if ret:
self.update_buffer(img)
return img return img
else: else:
return None return None
def cut_border(self, img):
def set_video_loop(self, show_video): #### # img = remove_the_blackborder(img)
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 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: class Mark:
def __init__(self, mark_dir): def __init__(self, mark_dir):
self.df_source = pd.read_excel(mark_dir, sheet_name=None) self.df_source = pd.read_excel(mark_dir, sheet_name=None)