Anonymous
RTSP всегда переподключается и работает нестабильно при использовании Yolov8 с Python3
Сообщение
Anonymous » 28 дек 2024, 01:32
Я провожу эксперимент с использованием YOLOv8, Python3 и RTSP в качестве источника видео.
При разработке программы я ожидал, что RTSP останется стабильным без частых переподключений. Однако на самом деле протокол RTSP продолжает переподключаться и работает нестабильно. Чем выше модель, которую я использую, тем хуже становится проблема с переподключением RTSP.
Я провел углубленный анализ оборудования:
Мое соединение UTP очень стабильно с чрезвычайно низкой задержкой, что подтверждено различными инструментами.
Мой компьютер хорошо обрабатывает и использует CUDA, поэтому я считаю, что проблема не в компьютере.
Я уже пробовали использовать методы TCP и UDP в RTSP, но результаты остались прежними.
Я подозреваю, что протокол RTSP в OpenCV работает на Python3 довольно медленный и содержит ошибки, из-за которых он не может справиться со значительными задержками видео. Действительно, результаты, полученные во время обработки обнаружения объектов, демонстрируют значительную задержку.
Ниже представлена программа, которую я использую:
Код: Выделить всё
import numpy as np
from ultralytics import YOLO
import cv2
import cvzone
import time, math, datetime, os
from sort import *
# os.environ["OPENCV_FFMPEG_CAPTURE_OPTIONS"] = "rtsp_transport;udp"
os.environ["OPENCV_FFMPEG_CAPTURE_OPTIONS"] = "rtsp_transport;udp,max_delay=10000000"
output_folder = "Captured"
if not os.path.exists(output_folder):
os.makedirs(output_folder)
error_detection = 0
int_counting = 0
# RTSP Source
rtsp_source = "rtsp://admin:gcc12345@192.168.6.7:554/Streaming/Channels/101/" # HIKVISION
# rtsp_source = "rtsp://admin:admin12345@192.168.6.2:554/cam/realmonitor?channel=3&subtype=0" # DAHUA
# rtsp_source = "rtsp://admin:admin12345@192.168.6.2:554/cam/realmonitor?channel=2&subtype=0" # DAHUA
# rtsp_source = "rtsp://admin:admin12345@192.168.6.2:554/cam/realmonitor?channel=4&subtype=0" # DAHUA
# rtsp_source = "../Videos/cars.mp4" # VIDEO
mask = cv2.imread("mask.png")
# Tracking
tracker = Sort(max_age=20, min_hits=3, iou_threshold=0.5)
# limits = [300, 350, 673, 350]
limits = [550, 220, 550, 670]
# Inisialisasi model YOLO
model = YOLO("../Yolo-Weights/yolov8x.pt")
className = ['person', 'bicycle', 'car', 'motorcycle', 'airplane', 'bus', 'train',
'truck', 'boat', 'traffic light', 'fire hydrant', 'stop sign', 'parking meter',
'bench', 'bird', 'cat', 'dog', 'horse', 'sheep', 'cow', 'elephant', 'bear',
'zebra', 'giraffe', 'backpack', 'umbrella', 'handbag', 'tie', 'suitcase',
'frisbee', 'skis', 'snowboard', 'sports ball', 'kite', 'baseball bat',
'baseball glove', 'skateboard', 'surfboard', 'tennis racket', 'bottle',
'wine glass', 'cup', 'fork', 'knife', 'spoon', 'bowl', 'banana', 'apple',
'sandwich', 'orange', 'broccoli', 'carrot', 'hot dog', 'pizza', 'donut',
'cake', 'chair', 'couch', 'potted plant', 'bed', 'dining table', 'toilet',
'tv', 'laptop', 'mouse', 'remote', 'keyboard', 'cell phone', 'microwave',
'oven', 'toaster', 'sink', 'refrigerator', 'book', 'clock', 'vase',
'scissors', 'teddy bear', 'hair drier', 'toothbrush']
# Fungsi untuk mereset jumlah upaya koneksi ulang
def reset_attempts():
return 50
# Fungsi untuk memproses video dan mengatur reconnect
def process_video(attempts):
global error_detection, tracker, int_counting
totalCount = []
# Inisialisasi waktu untuk perhitungan FPS
prev_time = time.time()
while True:
success, img = camera.read()
start_time = time.time()
if not success:
error_detection += 1
print("[ERROR] Gagal mendapatkan frame, mencoba reconnect..." + datetime.datetime.now().strftime("%m-%d-%Y %I:%M:%S%p"))
camera.release()
if attempts > 0:
time.sleep(min(5, (50 - attempts) / 10))
return True
else:
return False
# RESET Tracker
if time.time() - start_time > 300: # Reset setiap 5 menit (300 detik)
tracker = Sort(max_age=20, min_hits=3, iou_threshold=0.3)
totalCount.clear()
start_time = time.time() # Reset waktu mulai
print("[INFO] Tracker di-reset secara berkala.")
# Menghitung waktu sekarang
current_time = time.time()
# Hitung FPS
fps = 1 / (current_time - prev_time)
prev_time = current_time
print(img)
img_resized = cv2.resize(img, (1300, 700)) # Resize frame
# img_resized = img
# Tampilkan FPS di frame
cv2.putText(img_resized, f"FPS: {int(fps)}", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
img_region = cv2.bitwise_and(img_resized, mask)
# Deteksi dengan YOLO
results = model(img_region, stream=True)
# Tracker
detections = np.empty((0,5))
for r in results:
boxes = r.boxes
for box in boxes:
# Bounding Box
x1, y1, x2, y2 = box.xyxy[0]
x1, y1, x2, y2 = int(x1), int(y1), int(x2), int(y2)
w, h = x2 - x1, y2 - y1
# Menampilkan Tulisan Persentase
conf = math.ceil((box.conf[0] * 100)) / 100
# Class Name
cls = int(box.cls[0])
currentClass = className[cls]
if currentClass == "car" or currentClass == "truck" or currentClass == "bus" or currentClass == "motorcycle" and conf > 0.5:
# cvzone.putTextRect(img_resized, f'{className[cls]} {conf}', (max(0, x1), max(35, y1)), scale=0.7, thickness=1, offset=3)
# cvzone.cornerRect(img_resized, (x1, y1, w, h), l=5, rt=5)
currentArray = np.array([x1,y1,x2,y2,conf])
detections = np.vstack((detections,currentArray))
# Tracker
resultsTracker = tracker.update(detections)
cv2.line(img_resized,(limits[0], limits[1]), (limits[2], limits[3]),(0, 0, 255), 5)
# cv2.line(img_region, (limits[0], limits[1]), (limits[2], limits[3]), (0, 0, 255), 5)
for result in resultsTracker:
x1, y1, x2, y2, Id = result
x1, y1, x2, y2 = int(x1), int(y1), int(x2), int(y2)
# print(result)
w, h = x2 - x1, y2 - y1
cvzone.cornerRect(img_resized, (x1, y1, w, h), l=9, rt=2, colorR=(255,0,255))
cvzone.putTextRect(img_resized, f'{int(Id)}', (max(0, x1), max(35, y1)), scale=2, thickness=3, offset=10)
cx, cy = x1+w//2, y1+h//2
cv2.circle(img_resized,(cx,cy),5,(255,0,255),cv2.FILLED)
if limits[0] - 20 < cx < limits[0] + 20 and limits[1] < cy < limits[3]:
if totalCount.count(Id) == 0:
totalCount.append(Id)
int_counting += 1
# Capture gambar ketika objek melewati batas
timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
file_name = f"capture_{Id}_{timestamp}.png"
file_path = os.path.join(output_folder, file_name)
# Simpan gambar yang ditangkap ke dalam folder
cv2.imwrite(file_path, img_resized)
print(f"Gambar disimpan: {file_path}")
cvzone.putTextRect(img_resized,f'Count: {int_counting} Error Detection: {int(error_detection)}',(50, 650))
# Tampilkan hasil frame
cv2.imshow("Image", img_resized)
# cv2.imshow("ImageRegion", img_region)
# Tekan 'q' untuk keluar
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# cv2.waitKey(0)
return False
# Inisialisasi variabel recall untuk reconnect dan attempts untuk jumlah upaya
recall = True
attempts = reset_attempts()
while recall:
# Membuka stream RTSP
camera = cv2.VideoCapture(rtsp_source, cv2.CAP_FFMPEG)
camera.set(cv2.CAP_PROP_BUFFERSIZE, 1)
camera.set(cv2.CAP_PROP_FPS, 10)
if camera.isOpened():
print("[INFO] Camera connected at " +
datetime.datetime.now().strftime("%m-%d-%Y %I:%M:%S%p"))
attempts = reset_attempts() # Reset attempts saat berhasil terkoneksi
recall = process_video(attempts) # Proses video
else:
print("[ERROR] Camera not opened " +
datetime.datetime.now().strftime("%m-%d-%Y %I:%M:%S%p"))
camera.release()
attempts -= 1
print(f"Remaining attempts: {attempts}")
# Beri jeda untuk mencoba kembali
time.sleep(5)
continue
# Tutup jendela dan stream
cv2.destroyAllWindows()
Окружающая среда:
Код: Выделить всё
absl-py==2.1.0
antlr4-python3-runtime==4.9.3
asttokens==2.4.1
certifi==2024.8.30
charset-normalizer==3.3.2
colorama==0.4.6
contourpy==1.3.0
cvzone==1.5.6
cycler==0.12.1
decorator==5.1.1
exceptiongroup==1.2.2
executing==2.1.0
filelock==3.16.1
filterpy==1.4.5
fonttools==4.54.1
fsspec==2024.9.0
grpcio==1.66.1
hydra-core==1.3.2
idna==3.10
imageio==2.35.1
ipython==8.27.0
jedi==0.19.1
Jinja2==3.1.4
kiwisolver==1.4.7
lap==0.4.0
Markdown==3.7
MarkupSafe==2.1.5
matplotlib==3.9.2
matplotlib-inline==0.1.7
mpmath==1.3.0
networkx==3.3
numpy==1.26.4
omegaconf==2.3.0
opencv-python==4.10.0.84
packaging==24.1
pandas==2.2.3
parso==0.8.4
pillow==10.4.0
prompt_toolkit==3.0.47
protobuf==5.28.2
psutil==6.0.0
pure_eval==0.2.3
py-cpuinfo==9.0.0
Pygments==2.18.0
pyparsing==3.1.4
python-dateutil==2.9.0.post0
pytz==2024.2
PyWavelets==1.7.0
PyYAML==6.0.2
requests==2.32.3
scikit-image==0.19.3
scipy==1.14.1
seaborn==0.13.2
sentry-sdk==2.14.0
six==1.16.0
stack-data==0.6.3
sympy==1.13.3
tensorboard==2.17.1
tensorboard-data-server==0.7.2
thop==0.1.1.post2209072238
tifffile==2024.9.20
torch==1.13.1+cu116
torchaudio==0.13.1+cu116
torchvision==0.14.1+cu116
tqdm==4.66.5
traitlets==5.14.3
typing_extensions==4.12.2
tzdata==2024.2
ultralytics==8.2.101
ultralytics-thop==2.0.8
urllib3==2.2.3
wcwidth==0.2.13
Werkzeug==3.0.4
Кто-нибудь может помочь мне решить проблему с RTSP?
Подробнее здесь:
https://stackoverflow.com/questions/793 ... th-python3
1735338777
Anonymous
Я провожу эксперимент с использованием YOLOv8, Python3 и RTSP в качестве источника видео. При разработке программы я ожидал, что RTSP останется стабильным без частых переподключений. Однако на самом деле протокол RTSP продолжает переподключаться и работает нестабильно. Чем выше модель, которую я использую, тем хуже становится проблема с переподключением RTSP. [b]Я провел углубленный анализ оборудования:[/b] [list] [*]Мое соединение UTP очень стабильно с чрезвычайно низкой задержкой, что подтверждено различными инструментами. [*]Мой компьютер хорошо обрабатывает и использует CUDA, поэтому я считаю, что проблема не в компьютере. [*]Я уже пробовали использовать методы TCP и UDP в RTSP, но результаты остались прежними. [/list] Я подозреваю, что протокол RTSP в OpenCV работает на Python3 довольно медленный и содержит ошибки, из-за которых он не может справиться со значительными задержками видео. Действительно, результаты, полученные во время обработки обнаружения объектов, демонстрируют значительную задержку. [b]Ниже представлена программа, которую я использую:[/b] [code]import numpy as np from ultralytics import YOLO import cv2 import cvzone import time, math, datetime, os from sort import * # os.environ["OPENCV_FFMPEG_CAPTURE_OPTIONS"] = "rtsp_transport;udp" os.environ["OPENCV_FFMPEG_CAPTURE_OPTIONS"] = "rtsp_transport;udp,max_delay=10000000" output_folder = "Captured" if not os.path.exists(output_folder): os.makedirs(output_folder) error_detection = 0 int_counting = 0 # RTSP Source rtsp_source = "rtsp://admin:gcc12345@192.168.6.7:554/Streaming/Channels/101/" # HIKVISION # rtsp_source = "rtsp://admin:admin12345@192.168.6.2:554/cam/realmonitor?channel=3&subtype=0" # DAHUA # rtsp_source = "rtsp://admin:admin12345@192.168.6.2:554/cam/realmonitor?channel=2&subtype=0" # DAHUA # rtsp_source = "rtsp://admin:admin12345@192.168.6.2:554/cam/realmonitor?channel=4&subtype=0" # DAHUA # rtsp_source = "../Videos/cars.mp4" # VIDEO mask = cv2.imread("mask.png") # Tracking tracker = Sort(max_age=20, min_hits=3, iou_threshold=0.5) # limits = [300, 350, 673, 350] limits = [550, 220, 550, 670] # Inisialisasi model YOLO model = YOLO("../Yolo-Weights/yolov8x.pt") className = ['person', 'bicycle', 'car', 'motorcycle', 'airplane', 'bus', 'train', 'truck', 'boat', 'traffic light', 'fire hydrant', 'stop sign', 'parking meter', 'bench', 'bird', 'cat', 'dog', 'horse', 'sheep', 'cow', 'elephant', 'bear', 'zebra', 'giraffe', 'backpack', 'umbrella', 'handbag', 'tie', 'suitcase', 'frisbee', 'skis', 'snowboard', 'sports ball', 'kite', 'baseball bat', 'baseball glove', 'skateboard', 'surfboard', 'tennis racket', 'bottle', 'wine glass', 'cup', 'fork', 'knife', 'spoon', 'bowl', 'banana', 'apple', 'sandwich', 'orange', 'broccoli', 'carrot', 'hot dog', 'pizza', 'donut', 'cake', 'chair', 'couch', 'potted plant', 'bed', 'dining table', 'toilet', 'tv', 'laptop', 'mouse', 'remote', 'keyboard', 'cell phone', 'microwave', 'oven', 'toaster', 'sink', 'refrigerator', 'book', 'clock', 'vase', 'scissors', 'teddy bear', 'hair drier', 'toothbrush'] # Fungsi untuk mereset jumlah upaya koneksi ulang def reset_attempts(): return 50 # Fungsi untuk memproses video dan mengatur reconnect def process_video(attempts): global error_detection, tracker, int_counting totalCount = [] # Inisialisasi waktu untuk perhitungan FPS prev_time = time.time() while True: success, img = camera.read() start_time = time.time() if not success: error_detection += 1 print("[ERROR] Gagal mendapatkan frame, mencoba reconnect..." + datetime.datetime.now().strftime("%m-%d-%Y %I:%M:%S%p")) camera.release() if attempts > 0: time.sleep(min(5, (50 - attempts) / 10)) return True else: return False # RESET Tracker if time.time() - start_time > 300: # Reset setiap 5 menit (300 detik) tracker = Sort(max_age=20, min_hits=3, iou_threshold=0.3) totalCount.clear() start_time = time.time() # Reset waktu mulai print("[INFO] Tracker di-reset secara berkala.") # Menghitung waktu sekarang current_time = time.time() # Hitung FPS fps = 1 / (current_time - prev_time) prev_time = current_time print(img) img_resized = cv2.resize(img, (1300, 700)) # Resize frame # img_resized = img # Tampilkan FPS di frame cv2.putText(img_resized, f"FPS: {int(fps)}", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2) img_region = cv2.bitwise_and(img_resized, mask) # Deteksi dengan YOLO results = model(img_region, stream=True) # Tracker detections = np.empty((0,5)) for r in results: boxes = r.boxes for box in boxes: # Bounding Box x1, y1, x2, y2 = box.xyxy[0] x1, y1, x2, y2 = int(x1), int(y1), int(x2), int(y2) w, h = x2 - x1, y2 - y1 # Menampilkan Tulisan Persentase conf = math.ceil((box.conf[0] * 100)) / 100 # Class Name cls = int(box.cls[0]) currentClass = className[cls] if currentClass == "car" or currentClass == "truck" or currentClass == "bus" or currentClass == "motorcycle" and conf > 0.5: # cvzone.putTextRect(img_resized, f'{className[cls]} {conf}', (max(0, x1), max(35, y1)), scale=0.7, thickness=1, offset=3) # cvzone.cornerRect(img_resized, (x1, y1, w, h), l=5, rt=5) currentArray = np.array([x1,y1,x2,y2,conf]) detections = np.vstack((detections,currentArray)) # Tracker resultsTracker = tracker.update(detections) cv2.line(img_resized,(limits[0], limits[1]), (limits[2], limits[3]),(0, 0, 255), 5) # cv2.line(img_region, (limits[0], limits[1]), (limits[2], limits[3]), (0, 0, 255), 5) for result in resultsTracker: x1, y1, x2, y2, Id = result x1, y1, x2, y2 = int(x1), int(y1), int(x2), int(y2) # print(result) w, h = x2 - x1, y2 - y1 cvzone.cornerRect(img_resized, (x1, y1, w, h), l=9, rt=2, colorR=(255,0,255)) cvzone.putTextRect(img_resized, f'{int(Id)}', (max(0, x1), max(35, y1)), scale=2, thickness=3, offset=10) cx, cy = x1+w//2, y1+h//2 cv2.circle(img_resized,(cx,cy),5,(255,0,255),cv2.FILLED) if limits[0] - 20 < cx < limits[0] + 20 and limits[1] < cy < limits[3]: if totalCount.count(Id) == 0: totalCount.append(Id) int_counting += 1 # Capture gambar ketika objek melewati batas timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S") file_name = f"capture_{Id}_{timestamp}.png" file_path = os.path.join(output_folder, file_name) # Simpan gambar yang ditangkap ke dalam folder cv2.imwrite(file_path, img_resized) print(f"Gambar disimpan: {file_path}") cvzone.putTextRect(img_resized,f'Count: {int_counting} Error Detection: {int(error_detection)}',(50, 650)) # Tampilkan hasil frame cv2.imshow("Image", img_resized) # cv2.imshow("ImageRegion", img_region) # Tekan 'q' untuk keluar if cv2.waitKey(1) & 0xFF == ord('q'): break # cv2.waitKey(0) return False # Inisialisasi variabel recall untuk reconnect dan attempts untuk jumlah upaya recall = True attempts = reset_attempts() while recall: # Membuka stream RTSP camera = cv2.VideoCapture(rtsp_source, cv2.CAP_FFMPEG) camera.set(cv2.CAP_PROP_BUFFERSIZE, 1) camera.set(cv2.CAP_PROP_FPS, 10) if camera.isOpened(): print("[INFO] Camera connected at " + datetime.datetime.now().strftime("%m-%d-%Y %I:%M:%S%p")) attempts = reset_attempts() # Reset attempts saat berhasil terkoneksi recall = process_video(attempts) # Proses video else: print("[ERROR] Camera not opened " + datetime.datetime.now().strftime("%m-%d-%Y %I:%M:%S%p")) camera.release() attempts -= 1 print(f"Remaining attempts: {attempts}") # Beri jeda untuk mencoba kembali time.sleep(5) continue # Tutup jendela dan stream cv2.destroyAllWindows() [/code] Окружающая среда: [code]absl-py==2.1.0 antlr4-python3-runtime==4.9.3 asttokens==2.4.1 certifi==2024.8.30 charset-normalizer==3.3.2 colorama==0.4.6 contourpy==1.3.0 cvzone==1.5.6 cycler==0.12.1 decorator==5.1.1 exceptiongroup==1.2.2 executing==2.1.0 filelock==3.16.1 filterpy==1.4.5 fonttools==4.54.1 fsspec==2024.9.0 grpcio==1.66.1 hydra-core==1.3.2 idna==3.10 imageio==2.35.1 ipython==8.27.0 jedi==0.19.1 Jinja2==3.1.4 kiwisolver==1.4.7 lap==0.4.0 Markdown==3.7 MarkupSafe==2.1.5 matplotlib==3.9.2 matplotlib-inline==0.1.7 mpmath==1.3.0 networkx==3.3 numpy==1.26.4 omegaconf==2.3.0 opencv-python==4.10.0.84 packaging==24.1 pandas==2.2.3 parso==0.8.4 pillow==10.4.0 prompt_toolkit==3.0.47 protobuf==5.28.2 psutil==6.0.0 pure_eval==0.2.3 py-cpuinfo==9.0.0 Pygments==2.18.0 pyparsing==3.1.4 python-dateutil==2.9.0.post0 pytz==2024.2 PyWavelets==1.7.0 PyYAML==6.0.2 requests==2.32.3 scikit-image==0.19.3 scipy==1.14.1 seaborn==0.13.2 sentry-sdk==2.14.0 six==1.16.0 stack-data==0.6.3 sympy==1.13.3 tensorboard==2.17.1 tensorboard-data-server==0.7.2 thop==0.1.1.post2209072238 tifffile==2024.9.20 torch==1.13.1+cu116 torchaudio==0.13.1+cu116 torchvision==0.14.1+cu116 tqdm==4.66.5 traitlets==5.14.3 typing_extensions==4.12.2 tzdata==2024.2 ultralytics==8.2.101 ultralytics-thop==2.0.8 urllib3==2.2.3 wcwidth==0.2.13 Werkzeug==3.0.4 [/code] Кто-нибудь может помочь мне решить проблему с RTSP? Подробнее здесь: [url]https://stackoverflow.com/questions/79312441/rtsp-always-reconnect-and-unstable-when-using-yolov8-with-python3[/url]