Add video file using Git LFS
Browse files- .gitattributes +1 -34
- app.py +123 -10
- examples/video001-2.jpg +0 -0
- examples/video003-0009.jpg +0 -0
- examples/video010-0004.jpg +0 -0
- examples/video012-0009.jpg +0 -0
- examples/video015-001.jpg +0 -0
- examples/video023-021.jpg +0 -0
- examples/video026-036.jpg +0 -0
- examples/video20-010.jpg +0 -0
.gitattributes
CHANGED
@@ -1,35 +1,2 @@
|
|
1 |
-
*.7z filter=lfs diff=lfs merge=lfs -text
|
2 |
-
*.arrow filter=lfs diff=lfs merge=lfs -text
|
3 |
-
*.bin filter=lfs diff=lfs merge=lfs -text
|
4 |
-
*.bz2 filter=lfs diff=lfs merge=lfs -text
|
5 |
-
*.ckpt filter=lfs diff=lfs merge=lfs -text
|
6 |
-
*.ftz filter=lfs diff=lfs merge=lfs -text
|
7 |
-
*.gz filter=lfs diff=lfs merge=lfs -text
|
8 |
-
*.h5 filter=lfs diff=lfs merge=lfs -text
|
9 |
-
*.joblib filter=lfs diff=lfs merge=lfs -text
|
10 |
-
*.lfs.* filter=lfs diff=lfs merge=lfs -text
|
11 |
-
*.mlmodel filter=lfs diff=lfs merge=lfs -text
|
12 |
-
*.model filter=lfs diff=lfs merge=lfs -text
|
13 |
-
*.msgpack filter=lfs diff=lfs merge=lfs -text
|
14 |
-
*.npy filter=lfs diff=lfs merge=lfs -text
|
15 |
-
*.npz filter=lfs diff=lfs merge=lfs -text
|
16 |
*.onnx filter=lfs diff=lfs merge=lfs -text
|
17 |
-
*.
|
18 |
-
*.parquet filter=lfs diff=lfs merge=lfs -text
|
19 |
-
*.pb filter=lfs diff=lfs merge=lfs -text
|
20 |
-
*.pickle filter=lfs diff=lfs merge=lfs -text
|
21 |
-
*.pkl filter=lfs diff=lfs merge=lfs -text
|
22 |
-
*.pt filter=lfs diff=lfs merge=lfs -text
|
23 |
-
*.pth filter=lfs diff=lfs merge=lfs -text
|
24 |
-
*.rar filter=lfs diff=lfs merge=lfs -text
|
25 |
-
*.safetensors filter=lfs diff=lfs merge=lfs -text
|
26 |
-
saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
27 |
-
*.tar.* filter=lfs diff=lfs merge=lfs -text
|
28 |
-
*.tar filter=lfs diff=lfs merge=lfs -text
|
29 |
-
*.tflite filter=lfs diff=lfs merge=lfs -text
|
30 |
-
*.tgz filter=lfs diff=lfs merge=lfs -text
|
31 |
-
*.wasm filter=lfs diff=lfs merge=lfs -text
|
32 |
-
*.xz filter=lfs diff=lfs merge=lfs -text
|
33 |
-
*.zip filter=lfs diff=lfs merge=lfs -text
|
34 |
-
*.zst filter=lfs diff=lfs merge=lfs -text
|
35 |
-
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
*.onnx filter=lfs diff=lfs merge=lfs -text
|
2 |
+
*.mp4 filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
app.py
CHANGED
@@ -1,4 +1,6 @@
|
|
1 |
import gradio as gr
|
|
|
|
|
2 |
from core.chessboard_detector import ChessboardDetector
|
3 |
|
4 |
detector = ChessboardDetector(
|
@@ -7,8 +9,6 @@ detector = ChessboardDetector(
|
|
7 |
full_classifier_model_path="onnx/layout_recognition/v1.onnx"
|
8 |
)
|
9 |
|
10 |
-
|
11 |
-
|
12 |
# 数据集路径
|
13 |
dict_cate_names = {
|
14 |
'.': '.',
|
@@ -33,7 +33,95 @@ dict_cate_names = {
|
|
33 |
dict_cate_names_reverse = {v: k for k, v in dict_cate_names.items()}
|
34 |
|
35 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
36 |
with gr.Blocks(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
37 |
css="""
|
38 |
.image img {
|
39 |
max-height: 512px;
|
@@ -43,12 +131,21 @@ with gr.Blocks(
|
|
43 |
gr.Markdown("""
|
44 |
## 棋盘检测, 棋子识别
|
45 |
|
|
|
|
|
|
|
46 |
步骤:
|
47 |
1. 流程分成两步,第一步检测边缘
|
48 |
2. 对整个棋盘画面进行棋子分类预测
|
49 |
"""
|
50 |
)
|
51 |
|
|
|
|
|
|
|
|
|
|
|
|
|
52 |
with gr.Row():
|
53 |
with gr.Column():
|
54 |
image_input = gr.Image(label="上传棋盘图片", type="numpy", elem_classes="image")
|
@@ -83,18 +180,30 @@ with gr.Blocks(
|
|
83 |
visible=True,
|
84 |
)
|
85 |
|
|
|
|
|
|
|
|
|
86 |
|
87 |
def detect_chessboard(image):
|
88 |
-
|
|
|
|
|
|
|
|
|
89 |
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
|
96 |
-
|
97 |
-
|
|
|
|
|
|
|
|
|
98 |
|
99 |
|
100 |
return original_image_with_keypoints, transformed_image, annotation_arr_10_9, time_info
|
@@ -103,5 +212,9 @@ with gr.Blocks(
|
|
103 |
inputs=[image_input],
|
104 |
outputs=[original_image_with_keypoints, transformed_image, layout_pred_info, use_time])
|
105 |
|
|
|
|
|
|
|
|
|
106 |
if __name__ == "__main__":
|
107 |
demo.launch()
|
|
|
1 |
import gradio as gr
|
2 |
+
import cv2
|
3 |
+
import os
|
4 |
from core.chessboard_detector import ChessboardDetector
|
5 |
|
6 |
detector = ChessboardDetector(
|
|
|
9 |
full_classifier_model_path="onnx/layout_recognition/v1.onnx"
|
10 |
)
|
11 |
|
|
|
|
|
12 |
# 数据集路径
|
13 |
dict_cate_names = {
|
14 |
'.': '.',
|
|
|
33 |
dict_cate_names_reverse = {v: k for k, v in dict_cate_names.items()}
|
34 |
|
35 |
|
36 |
+
### 构建 examples
|
37 |
+
|
38 |
+
def build_examples():
|
39 |
+
examples = []
|
40 |
+
# 读取 examples 目录下的所有图片
|
41 |
+
for file in os.listdir("examples"):
|
42 |
+
if file.endswith(".jpg"):
|
43 |
+
image_path = os.path.join("examples", file)
|
44 |
+
examples.append([image_path, None])
|
45 |
+
|
46 |
+
elif file.endswith(".mp4"):
|
47 |
+
video_path = os.path.join("examples", file)
|
48 |
+
examples.append([None, video_path])
|
49 |
+
|
50 |
+
return examples
|
51 |
+
|
52 |
+
|
53 |
+
full_examples = build_examples()
|
54 |
+
|
55 |
+
|
56 |
+
def get_video_frame_with_processs(video_data, process: str = '00:00') -> cv2.UMat:
|
57 |
+
"""
|
58 |
+
获取视频指定位置的帧
|
59 |
+
"""
|
60 |
+
|
61 |
+
# 读取视频
|
62 |
+
cap = cv2.VideoCapture(video_data)
|
63 |
+
if not cap.isOpened():
|
64 |
+
gr.Warning("无法打开视频")
|
65 |
+
return None
|
66 |
+
|
67 |
+
# 获取视频的帧率
|
68 |
+
fps = cap.get(cv2.CAP_PROP_FPS)
|
69 |
+
|
70 |
+
# process 是 00:00
|
71 |
+
process_time = process.split(":")
|
72 |
+
minutes = int(process_time[0])
|
73 |
+
seconds = float(process_time[1])
|
74 |
+
|
75 |
+
# 计算总秒数
|
76 |
+
target_seconds = minutes * 60 + seconds
|
77 |
+
|
78 |
+
# 计算当前帧
|
79 |
+
current_frame = int(target_seconds * fps)
|
80 |
+
|
81 |
+
# 设置到指定帧
|
82 |
+
cap.set(cv2.CAP_PROP_POS_FRAMES, current_frame)
|
83 |
+
|
84 |
+
# 读取当前帧
|
85 |
+
ret, frame = cap.read()
|
86 |
+
cap.release()
|
87 |
+
|
88 |
+
if not ret:
|
89 |
+
gr.Warning("无法读取视频帧")
|
90 |
+
return None
|
91 |
+
|
92 |
+
frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
|
93 |
+
|
94 |
+
return frame_rgb
|
95 |
+
|
96 |
+
|
97 |
+
|
98 |
+
|
99 |
with gr.Blocks(
|
100 |
+
js="""
|
101 |
+
async () => {
|
102 |
+
document.addEventListener('timeupdate', function(e) {
|
103 |
+
// 检查事件源是否是视频元素
|
104 |
+
if (e.target.matches('#video_player video')) {
|
105 |
+
const video = e.target;
|
106 |
+
const currentTime = video.currentTime;
|
107 |
+
// 转换成 00:00 格式
|
108 |
+
let minutes = Math.floor(currentTime / 60);
|
109 |
+
let seconds = Math.floor(currentTime % 60);
|
110 |
+
let formattedTime = `${minutes.toString().padStart(2,'0')}:${seconds.toString().padStart(2,'0')}`;
|
111 |
+
|
112 |
+
// 更新输入框值
|
113 |
+
let processInput = document.querySelector("#video_process textarea");
|
114 |
+
if(processInput) {
|
115 |
+
processInput.value = formattedTime;
|
116 |
+
processInput.text = formattedTime;
|
117 |
+
|
118 |
+
processInput.dispatchEvent(new Event("input"));
|
119 |
+
}
|
120 |
+
|
121 |
+
}
|
122 |
+
}, true); // 使用捕获阶段
|
123 |
+
}
|
124 |
+
""",
|
125 |
css="""
|
126 |
.image img {
|
127 |
max-height: 512px;
|
|
|
131 |
gr.Markdown("""
|
132 |
## 棋盘检测, 棋子识别
|
133 |
|
134 |
+
x 表示 有遮挡位置
|
135 |
+
. 表示 棋盘上的普通交叉点
|
136 |
+
|
137 |
步骤:
|
138 |
1. 流程分成两步,第一步检测边缘
|
139 |
2. 对整个棋盘画面进行棋子分类预测
|
140 |
"""
|
141 |
)
|
142 |
|
143 |
+
with gr.Row():
|
144 |
+
with gr.Column():
|
145 |
+
video_input = gr.Video(label="上传视频", interactive=True, elem_id="video_player", height=356)
|
146 |
+
video_process = gr.Textbox(label="当前时间", interactive=True, elem_id="video_process", value="00:00")
|
147 |
+
extract_frame_btn = gr.Button("从视频提取当前帧")
|
148 |
+
|
149 |
with gr.Row():
|
150 |
with gr.Column():
|
151 |
image_input = gr.Image(label="上传棋盘图片", type="numpy", elem_classes="image")
|
|
|
180 |
visible=True,
|
181 |
)
|
182 |
|
183 |
+
with gr.Row():
|
184 |
+
with gr.Column():
|
185 |
+
gr.Examples(full_examples, inputs=[image_input, video_input], label="示例视频、图片")
|
186 |
+
|
187 |
|
188 |
def detect_chessboard(image):
|
189 |
+
if image is None:
|
190 |
+
return None, None, None, None
|
191 |
+
|
192 |
+
try:
|
193 |
+
original_image_with_keypoints, transformed_image, cells_labels_str, scores, time_info = detector.pred_detect_board_and_classifier(image)
|
194 |
|
195 |
+
# 将 cells_labels 转换为 DataFrame
|
196 |
+
# cells_labels ��过 \n 分割
|
197 |
+
annotation_10_rows = [item for item in cells_labels_str.split("\n")]
|
198 |
+
# 将 annotation_10_rows 转换成为 10 行 9 列的二维数组
|
199 |
+
annotation_arr_10_9 = [list(item) for item in annotation_10_rows]
|
200 |
|
201 |
+
# 将 棋子类别 转换为 中文
|
202 |
+
annotation_arr_10_9 = [[dict_cate_names_reverse[item] for item in row] for row in annotation_arr_10_9]
|
203 |
+
|
204 |
+
except Exception as e:
|
205 |
+
gr.Warning(f"检测失败 图片或者视频布局错误")
|
206 |
+
return None, None, None, None
|
207 |
|
208 |
|
209 |
return original_image_with_keypoints, transformed_image, annotation_arr_10_9, time_info
|
|
|
212 |
inputs=[image_input],
|
213 |
outputs=[original_image_with_keypoints, transformed_image, layout_pred_info, use_time])
|
214 |
|
215 |
+
extract_frame_btn.click(fn=get_video_frame_with_processs,
|
216 |
+
inputs=[video_input, video_process],
|
217 |
+
outputs=[image_input])
|
218 |
+
|
219 |
if __name__ == "__main__":
|
220 |
demo.launch()
|
examples/video001-2.jpg
ADDED
![]() |
examples/video003-0009.jpg
ADDED
![]() |
examples/video010-0004.jpg
ADDED
![]() |
examples/video012-0009.jpg
ADDED
![]() |
examples/video015-001.jpg
ADDED
![]() |
examples/video023-021.jpg
ADDED
![]() |
examples/video026-036.jpg
ADDED
![]() |
examples/video20-010.jpg
ADDED
![]() |