detection-yolov4 / detection_yolov4.py
Sazuppy's picture
Add large file using
63a28f6
raw
history blame
14.6 kB
import cv2 as cv
import streamlit as st
import tempfile
import time
from moviepy.editor import VideoClip
from moviepy.editor import AudioFileClip
import datetime
@st.cache_resource
def yolov4(names, weights, config, Conf_threshold, NMS_threshold):
Conf_threshold = Conf_threshold
NMS_threshold = NMS_threshold
COLORS = [(0, 255, 0), (0, 0, 255), (255, 0, 0),
(255, 255, 0), (255, 0, 255), (0, 255, 255)]
class_name = []
with open(names, 'r') as f:
class_name = [cname.strip() for cname in f.readlines()]
# Инициализация нейросети YOLOv4
net = cv.dnn.readNet(weights, config)
net.setPreferableBackend(cv.dnn.DNN_BACKEND_CUDA)
net.setPreferableTarget(cv.dnn.DNN_TARGET_CUDA_FP16)
model = cv.dnn_DetectionModel(net)
model.setInputParams(size=(416, 416), scale=1/255, swapRB=True)
return model, COLORS, class_name
def temp_file(data):
# Сохранение видеофайла во временный файл
temp_file = tempfile.NamedTemporaryFile(delete=False)
temp_file.write(data.read())
temp_file_path = temp_file.name
# Захват видео
cap = cv.VideoCapture(temp_file_path)
temp_file.close()
return cap, temp_file_path
def image_process(model, cap, Conf_threshold, NMS_threshold, COLORS, class_name):
ret, frame = cap.read()
# Обнаружение объектов с использованием YOLOv4
classes, scores, boxes = model.detect(frame, Conf_threshold, NMS_threshold)
for (classid, score, box) in zip(classes, scores, boxes):
color = COLORS[int(classid) % len(COLORS)]
label = "%s : %f" % (class_name[classid], score)
cv.rectangle(frame, box, color, 1)
cv.putText(frame, label, (box[0], box[1]-10),
cv.FONT_HERSHEY_COMPLEX, 0.3, color, 1)
frame = cv.resize(frame,(0,0), fx=0.8, fy=0.8)
return frame
def video_process(model, cap, Conf_threshold, NMS_threshold, COLORS, class_name):
starting_time = time.time()
frame_counter = 0
total_frames = int(cap.get(cv.CAP_PROP_FRAME_COUNT))
remaining_time = datetime.timedelta(seconds=0)
remaining_time_container = st.empty()
video_frames = []
while True:
ret, frame = cap.read()
frame_counter += 1
if ret == False:
break
# Обнаружение объектов с использованием YOLOv4
classes, scores, boxes = model.detect(frame, Conf_threshold, NMS_threshold)
for (classid, score, box) in zip(classes, scores, boxes):
color = COLORS[int(classid) % len(COLORS)]
label = "%s : %f" % (class_name[classid], score)
cv.rectangle(frame, box, color, 1)
cv.putText(frame, label, (box[0], box[1]-10),
cv.FONT_HERSHEY_COMPLEX, 0.3, color, 1)
if app_mode == 'Видео':
endingTime = time.time() - starting_time
fps = frame_counter/endingTime
remaining_frames = total_frames - frame_counter
remaining_time = datetime.timedelta(seconds=int(remaining_frames / fps))
# Преобразование кадра в формат RGB для отображения в Streamlit
frame = cv.cvtColor(frame, cv.COLOR_BGR2RGB)
video_frames.append(frame.copy())
remaining_time_container.markdown('Оставшееся время выполнения: ' + str(remaining_time))
if stop:
break
return video_frames
def concotinate_video(video_frames, data):
cap = cv.VideoCapture(data)
# Считывание видео для получения FPS
fps_original = cap.get(cv.CAP_PROP_FPS)
total_frames_original = int(cap.get(cv.CAP_PROP_FRAME_COUNT))
# Создание функции для извлечения кадров из списка video_frames
def get_frame(t):
index = int(t * fps_original)
if index < total_frames_original:
return video_frames[index]
else:
return video_frames[-1]
# Считывание аудио для получения длительности
audio_clip = AudioFileClip(data)
st.markdown('Сборка видео')
video_clip = VideoClip(get_frame, duration=total_frames_original / fps_original)
video_clip = video_clip.set_audio(audio_clip)
output_file_path = 'processed_video.mp4'
video_clip.write_videofile(output_file_path, codec="libx264", audio_codec="aac", fps=fps_original)
return output_file_path
st.set_page_config(layout="wide", page_title="Детекция с YOLO v4")
st.title("Детекция с YOLO v4")
st.sidebar.title('Информация и выбор режима')
app_mode = st.sidebar.selectbox(
'Параметры',
['О сервисе', 'Изображение', 'Видео']
)
# About Page
if app_mode == 'О сервисе':
st.markdown('''Проект создан с использованием фреймворка Streamlit и библиотеки OpenCV, при этом в его основе лежит сверточная нейросеть YOLOv4.
Проект предоставляет демонстрацию возможностей данной нейросети.
#### YOLOv4 с обученными весами:
- Проект включает в себя готовую модель YOLOv4 с предварительно обученными весами. Эта модель способна обнаруживать объекты из 80 различных классов, что обеспечивает широкий спектр применения для определения различных объектов на изображениях.
#### Переобученная модель YOLOv4-tiny:
- Кроме того, представлена переобученная модель YOLOv4-tiny, которая была адаптирована для специфической задачи - определения наличия надетой каски на человеке. В ходе этого процесса были взяты веса базовой модели YOLOv4-tiny, проведена разметка данных и выполнено обучение на домашнем компьютере с использованием технологии CUDA от NVIDIA. Обучение велось по двум классам: "helmet" (каска) и "head" (голова).
Этот проект не только демонстрирует работу нейросети, но и подчеркивает его возможности в адаптации к конкретным задачам и обучению на собственных данных.
''')
with st.expander("Пример видео на выходе после обработки"):
st.video('processed_test1.mp4')
st.video('processed_test2.mp4')
# Image Page
elif app_mode == 'Изображение':
genre = st.sidebar.radio(
"Выбор модели",
["yolov4", "helmet"],
index=0,
)
if genre == 'yolov4':
names = 'coco.names'
weights = 'yolov4-tiny.weights'
config = 'yolov4-tiny-custom.cfg'
elif genre == 'helmet':
names = 'helmet.names'
weights = 'helmet_final.weights'
config = 'helmet.cfg'
st.sidebar.markdown('---')
st.markdown("#### Определение объектов на изображении")
st.sidebar.markdown('---')
detection_confidence = st.sidebar.slider('Порог уверенности', min_value=0.0, max_value=1.0, value=0.5)
with st.sidebar.expander("Назначение:"):
st.markdown('''Определяет, насколько уверенной должна быть модель в том, что объект обнаружен, прежде чем результат будет рассматриваться как положительный.
Если уверенность модели ниже этого порога, объект не будет считаться детектированным.
Обычно устанавливается в диапазоне 0.1-0.9 в зависимости от ваших требований к уверенности.
Более низкие значения приведут к более широкому набору детекций, но с большим числом ложных срабатываний.''')
tracking_confidence = st.sidebar.slider('Порог подавления', min_value=0.0, max_value=1.0, value=0.5)
with st.sidebar.expander("Назначение:"):
st.markdown('''Используется для подавления (фильтрации) дублирующих детекций.
Когда модель обнаруживает несколько прямоугольных областей, перекрывающихся с высокой уверенностью, порог подавления помогает выбрать только одну из них.
Это предотвращает появление множественных детекций для одного и того же объекта.
Обычно устанавливается в диапазоне 0.1-0.5.
Более высокие значения делают алгоритм более консервативным, выбирая более уверенные детекции, но при этом может пропустить менее уверенные детекции.''')
st.sidebar.markdown('---')
img_file_buffer = st.sidebar.file_uploader("Загрузите изображение", type=["jpg", "jpeg", "png"])
st.sidebar.text('Исходное изображение')
if img_file_buffer:
st.sidebar.image(img_file_buffer)
if img_file_buffer:
start = st.button("Запуск обработки", type="primary")
stframe = st.empty()
if start:
model, COLORS, class_name = yolov4(names, weights, config, detection_confidence, tracking_confidence)
cap, temp_file_path = temp_file(img_file_buffer)
frame = image_process(model, cap, detection_confidence, tracking_confidence, COLORS, class_name)
stframe.image(frame,channels='BGR', use_column_width="auto")
# Video Page
elif app_mode == 'Видео':
st.set_option('deprecation.showfileUploaderEncoding', False)
genre = st.sidebar.radio(
"Выбор модели",
["yolov4", "helmet"],
index=0,
)
if genre == 'yolov4':
names = 'coco.names'
weights = 'yolov4-tiny.weights'
config = 'yolov4-tiny-custom.cfg'
elif genre == 'helmet':
names = 'helmet.names'
weights = 'helmet_final.weights'
config = 'helmet.cfg'
st.sidebar.markdown('---')
detection_confidence = st.sidebar.slider('Порог уверенности', min_value=0.0, max_value=1.0, value=0.5)
with st.sidebar.expander("Назначение:"):
st.markdown('''Определяет, насколько уверенной должна быть модель в том, что объект обнаружен, прежде чем результат будет рассматриваться как положительный.
Если уверенность модели ниже этого порога, объект не будет считаться детектированным.
Обычно устанавливается в диапазоне 0.1-0.9 в зависимости от ваших требований к уверенности.
Более низкие значения приведут к более широкому набору детекций, но с большим числом ложных срабатываний.''')
tracking_confidence = st.sidebar.slider('Порог подавления', min_value=0.0, max_value=1.0, value=0.5)
with st.sidebar.expander("Назначение:"):
st.markdown('''Используется для подавления (фильтрации) дублирующих детекций.
Когда модель обнаруживает несколько прямоугольных областей, перекрывающихся с высокой уверенностью, порог подавления помогает выбрать только одну из них.
Это предотвращает появление множественных детекций для одного и того же объекта.
Обычно устанавливается в диапазоне 0.1-0.5.
Более высокие значения делают алгоритм более консервативным, выбирая более уверенные детекции, но при этом может пропустить менее уверенные детекции.''')
st.sidebar.markdown('---')
## Get Video
video_file_buffer = st.sidebar.file_uploader("Загрузите видео", type=['mp4', 'mov', 'avi', 'asf', 'm4v'])
st.sidebar.text('Исходное видео')
if video_file_buffer:
st.sidebar.video(video_file_buffer)
st.markdown("#### Определение объектов на видео")
if video_file_buffer:
start = st.button("Запуск обработки", type="primary")
stop = st.button("Остановка обработки")
stframe = st.empty()
if start:
model, COLORS, class_name = yolov4(names, weights, config, detection_confidence, tracking_confidence)
cap, temp_file_path = temp_file(video_file_buffer)
video_frames = video_process(model, cap, detection_confidence, tracking_confidence, COLORS, class_name)
output_file_path = concotinate_video(video_frames, temp_file_path)
st.markdown('### Обработанное видео')
st.video(output_file_path)