Created
December 29, 2019 17:28
-
-
Save simeneide/d6b50871246d76141a811a0e370505ed to your computer and use it in GitHub Desktop.
bounding box of videostream. visualized in streamlit
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#%% | |
import time | |
import numpy as np | |
import streamlit as st | |
import pandas as pd | |
import cv2 | |
video_sources = { | |
'Rindabotn' : "http://217.17.213.66:8081/mjpg/video.mjpg?overview=0&camera=1&videoframeskipmode=empty&Axis-Orig-Sw=true&resolution=1280x720", | |
'Hodlekve' : "http://217.17.213.66:8080/mjpg/video.mjpg?overview=0&camera=1&videoframeskipmode=empty&Axis-Orig-Sw=true&resolution=1280x720", | |
'Times Square ground' : 'https://videos3.earthcam.com/fecnetwork/9974.flv/chunklist_w1421640637.m3u8', | |
'Times Square' : 'https://videos3.earthcam.com/fecnetwork/hdtimes10.flv/chunklist_w1581551174.m3u8', | |
'Road' : 'https://videos3.earthcam.com/fecnetwork/15559.flv/chunklist_w1295434004.m3u8' | |
} | |
#%% Run the YOLO model to detect objects. | |
# Borrowed functions from https://github.com/streamlit/demo-self-driving/blob/master/app.py | |
def yolo_v3(image, confidence_threshold, overlap_threshold): | |
# Load the network. Because this is cached it will only happen once. | |
@st.cache(allow_output_mutation=True) | |
def load_network(config_path, weights_path): | |
net = cv2.dnn.readNetFromDarknet(config_path, weights_path) | |
output_layer_names = net.getLayerNames() | |
output_layer_names = [output_layer_names[i[0] - 1] for i in net.getUnconnectedOutLayers()] | |
return net, output_layer_names | |
net, output_layer_names = load_network("yolov3.cfg", "yolov3.weights") | |
# Run the YOLO neural net. | |
blob = cv2.dnn.blobFromImage(image, 1 / 255.0, (416, 416), swapRB=True, crop=False) | |
net.setInput(blob) | |
layer_outputs = net.forward(output_layer_names) | |
# Supress detections in case of too low confidence or too much overlap. | |
boxes, confidences, class_IDs = [], [], [] | |
H, W = image.shape[:2] | |
for output in layer_outputs: | |
for detection in output: | |
scores = detection[5:] | |
classID = np.argmax(scores) | |
confidence = scores[classID] | |
if confidence > confidence_threshold: | |
box = detection[0:4] * np.array([W, H, W, H]) | |
centerX, centerY, width, height = box.astype("int") | |
x, y = int(centerX - (width / 2)), int(centerY - (height / 2)) | |
boxes.append([x, y, int(width), int(height)]) | |
confidences.append(float(confidence)) | |
class_IDs.append(classID) | |
indices = cv2.dnn.NMSBoxes(boxes, confidences, confidence_threshold, overlap_threshold) | |
# Map from YOLO labels to Udacity labels. | |
UDACITY_LABELS = { | |
0: 'pedestrian', | |
1: 'biker', | |
2: 'car', | |
3: 'biker', | |
5: 'truck', | |
7: 'truck', | |
9: 'trafficLight' | |
} | |
xmin, xmax, ymin, ymax, labels = [], [], [], [], [] | |
if len(indices) > 0: | |
# loop over the indexes we are keeping | |
for i in indices.flatten(): | |
label = class_IDs[i]#UDACITY_LABELS.get(class_IDs[i], None) | |
if label is None: | |
continue | |
# extract the bounding box coordinates | |
x, y, w, h = boxes[i][0], boxes[i][1], boxes[i][2], boxes[i][3] | |
xmin.append(x) | |
ymin.append(y) | |
xmax.append(x+w) | |
ymax.append(y+h) | |
labels.append(label) | |
boxes = pd.DataFrame({"xmin": xmin, "ymin": ymin, "xmax": xmax, "ymax": ymax, "labels": labels}) | |
return boxes[["xmin", "ymin", "xmax", "ymax", "labels"]] | |
def create_image_with_boxes(image, boxes, header, description): | |
# Superpose the semi-transparent object detection boxes. # Colors for the boxes | |
LABEL_COLORS = { | |
"car": [255, 0, 0], | |
"pedestrian": [0, 255, 0], | |
"truck": [0, 0, 255], | |
"trafficLight": [255, 255, 0], | |
"biker": [255, 0, 255], | |
} | |
image_with_boxes = image.astype(np.float64) | |
for _, (xmin, ymin, xmax, ymax, label) in boxes.iterrows(): | |
image_with_boxes[int(ymin):int(ymax),int(xmin):int(xmax),:] += [label*10,255-10*label,label] #LABEL_COLORS[label] | |
image_with_boxes[int(ymin):int(ymax),int(xmin):int(xmax),:] /= 2 | |
return image_with_boxes.astype(np.uint8) | |
#%% | |
import cv2 | |
from threading import Thread | |
class ThreadedCamera(object): | |
def __init__(self, source = 0): | |
self.capture = cv2.VideoCapture(source) | |
self.thread = Thread(target = self.update, args = ()) | |
self.thread.daemon = True | |
self.thread.start() | |
self.status = False | |
self.frame = None | |
def update(self): | |
while True: | |
if self.capture.isOpened(): | |
(self.status, self.frame) = self.capture.read() | |
def grab_frame(self): | |
if self.status: | |
return self.frame | |
return None | |
#%% DISPLAY | |
st.sidebar.title("Parameters") | |
source = st.sidebar.radio("Velg kamera", list(video_sources.keys())) | |
st.markdown(f"# {source}") | |
url = video_sources[source] | |
streamer = ThreadedCamera(url) | |
cap = cv2.VideoCapture(url) | |
confidence_threshold = st.sidebar.slider("Confidence threshold", 0.0, 1.0, 0.5, 0.01) | |
overlap_threshold = st.sidebar.slider("Overlap threshold", 0.0, 1.0, 0.3, 0.01) | |
sleeptime = st.sidebar.slider("Sleep", 0.0, 10.0, 1.0, 0.1) | |
stream = st.empty() | |
while True: | |
#result, frame = cap.read() | |
frame = streamer.grab_frame() | |
boxes = yolo_v3(frame, confidence_threshold=confidence_threshold, overlap_threshold=overlap_threshold) | |
frame = create_image_with_boxes(frame,boxes, header="",description="") | |
stream.image(frame, use_column_width=True) | |
time.sleep(sleeptime) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment