Skip to content

Commit

Permalink
Merge pull request #10 from aagustinconti/app
Browse files Browse the repository at this point in the history
App
  • Loading branch information
aagustinconti authored Apr 14, 2023
2 parents c31d6a6 + e843f85 commit e441861
Show file tree
Hide file tree
Showing 9 changed files with 118 additions and 87 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
*.pt
*.avi
*.mp4
*.jpg

# Byte-compiled / optimized / DLL files
__pycache__/
Expand Down
29 changes: 10 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ In addition to the detections, **it has been possible to track these objects and

### Information flow

![Information flow](readme-img/Untitled.png)
![Information flow](readme-img/graph_1.png)

### Count algorithm

![Count Algorithm](readme-img/Untitled%201.png)
![Count Algorithm](readme-img/graph_2.png)

## Results

Expand Down Expand Up @@ -105,7 +105,7 @@ Do this following steps *in order.*
nvtop # To run the nvtop
```

![nvidia-smi](/readme-img/Untitled%202.png)
![nvidia-smi](/readme-img/nvidia-smi.png)

**Pull nvidia-gpu image**

Expand All @@ -117,26 +117,14 @@ Follow this **[installation guide.](https://docs.nvidia.com/datacenter/cloud-na
git pull https://github.com/aagustinconti/yolov7_counting
```

**Change permissions of ./start.sh**

```bash
sudo chmod +x ./start.sh
```

**Download YOLOv7x pretrained weights**

1. Download the pretrained weights of YOLOv7x [here.](https://github.com/WongKinYiu/yolov7/blob/main/README.md#performance)
2. Save them in **./pretrained_weights** directory.

**RUN ./start.sh**

To build the docker image if is not available in your PC and run the container with the propp

```bash
./start.sh
```

### Configuring the test
**Configuring the test**

- Into the **test_oop.py** file you can modify some characteristics of the instance of the class *YoloSortCount()* before to execute the *run()* method.
- By default:
Expand All @@ -145,15 +133,18 @@ To build the docker image if is not available in your PC and run the container w
- Classes: person (ID: 0)
- Save: False

**RUN the test**

On the docker terminal run
**RUN docker_control.py**

To build the docker image if it's not available in your PC and run the container with the propp
```bash
python test_oop.py
python3 docker_control.py
```
## Thanks to
[YOLOv7](https://github.com/WongKinYiu/yolov7/)
Expand Down
69 changes: 69 additions & 0 deletions docker_control.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import docker
import os
import logging

# Debug
logging.basicConfig(
format='%(asctime)s | %(levelname)s: %(message)s', level=logging.INFO)

# Get the current working directory
logging.info("Looking for the current directory...")
cwd = os.getcwd()
logging.info(f"The current directory is --> {cwd}")

logging.info("Looking for the current display...")
display = os.getenv("DISPLAY")
logging.info(f"The current display is --> {display}")


# Docker SDK --> https://docker-py.readthedocs.io/en/stable/containers.html

logging.info("Instantiating Docker client...")
client = docker.from_env()

logging.info("Checking if the Image already exists...")

if str(os.popen("docker image inspect yolov7_detect_track_count:latest 2> /dev/null").read())[:2] == "[]":

logging.info("The image doesn't exist. Building the Docker Image...")

os.chdir("./dependencies")

cwd = os.getcwd()
logging.info(f"The current directory is --> {cwd}")

os.system("docker build -t yolov7_detect_track_count .")
os.chdir("..")

cwd = os.getcwd()
logging.info(f"The current directory is --> {cwd}")

else:
logging.info("The image has already exists.")


logging.info(
"Setting up X Server to accept connections. Turning Access control off...")
os.system("xhost +")


logging.info("Running a container...")


container = client.containers.run(
image='yolov7_detect_track_count:latest',
stdin_open=True,
tty=True,
auto_remove=True,
network_mode='host',
name="test",
device_requests=[docker.types.DeviceRequest(
device_ids=["0"], capabilities=[['gpu']])],
devices=["/dev/video0:/dev/video0"],
volumes={
'/tmp/.X11-unix': {'bind': '/tmp/.X11-unix', 'mode': 'rw'},
cwd: {'bind': '/workspace', 'mode': 'rw'}
},
environment=[f"DISPLAY={display}"],
command='python test_oop.py'
)
File renamed without changes
File renamed without changes
File renamed without changes
28 changes: 0 additions & 28 deletions start.sh

This file was deleted.

4 changes: 2 additions & 2 deletions test_oop.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@
WebCamera: 0 ---> DEFAULT
Youtube Video or stream: "https://www.youtube.com/watch?v=qP1y7Tdab7Y"
Stream URL: "http://IP/hls/stream_src.m3u8"
RSTP Stream:
RSTP Stream: "http://192.168.1.3:4747/video"
Local video: "img_bank/cows_for_sale.mp4"
Local image: "img_bank/img.jpg" | "img_bank/img.png"
"""
test.video_path = 0
test.video_path = 0#"https://www.youtube.com/watch?v=2wqpy036z24"


"""
Expand Down
74 changes: 36 additions & 38 deletions yolov7_sort_count_oop.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,6 @@
from count_oop import Count


"""
"""


class YoloSortCount():
Expand Down Expand Up @@ -67,14 +63,14 @@ def __init__(self):
self.ds_nn_budget = 100
self.ds_color = (0, 0, 255)

self.max_fps = 25
self.max_width = 720

# Pre defined
self.names = None

self.orig_w = None
self.orig_h = None
self.orig_ratio = None
self.orig_fps = None

self.stopped = False
Expand All @@ -93,7 +89,7 @@ def __init__(self):

# Debug
logging.basicConfig(
format='%(asctime)s | %(levelname)s: %(message)s', level=logging.NOTSET)
format='%(asctime)s | %(levelname)s: %(message)s', level=logging.INFO)

self.show_configs = False
self.show_detection = False
Expand Down Expand Up @@ -154,26 +150,18 @@ def load_video_capture(self, video_path):
logging.info(f'Source of the video: {video_path}')

cap = cv2.VideoCapture(video_path)

# To discard delayed frames
cap.set(cv2.CAP_PROP_BUFFERSIZE, 1)

logging.info('The video capture has been loaded.')

orig_w = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
orig_h = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))

orig_ratio = orig_h / orig_w

if orig_w > self.max_width:
logging.info(
'Capture has more width than max. width allowed. Rezising...')
cap = self.change_res(cap, self.max_width, orig_ratio)

orig_w = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
orig_h = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))

logging.info(f'Capture has been resized to {(orig_w,orig_h)}')

orig_ratio = orig_w / orig_h
orig_fps = cap.get(cv2.CAP_PROP_FPS) % 100

return cap, orig_w, orig_h, orig_fps
return cap, orig_w, orig_h, orig_ratio, orig_fps

except Exception as err:
raise ImportError(
Expand Down Expand Up @@ -231,6 +219,7 @@ def load_tracking_model(self, deep_sort_model, max_dist, max_iou_distance, max_a
"""

try:
logging.info('This step may take a while...')
deepsort = DeepSort(deep_sort_model,
max_dist=max_dist,
max_iou_distance=max_iou_distance,
Expand All @@ -248,17 +237,28 @@ def load_roi(self):
- To select the ROI, interactive way.
"""

cap_roi, _, _, _ = self.load_video_capture(self.video_path)
cap_roi, _, _,_,_= self.load_video_capture(self.video_path)

orig_w_roi = int(cap_roi.get(cv2.CAP_PROP_FRAME_WIDTH))
orig_h_roi = int(cap_roi.get(cv2.CAP_PROP_FRAME_HEIGHT))
orig_ratio_roi = orig_w_roi / orig_h_roi

ret, select_roi_frame = cap_roi.read()


# To avoid the camera delay
if not self.hold_img:
frame_count_roi = 0
while frame_count_roi <= 3 and ret:

ret, select_roi_frame = cap_roi.read()
frame_count_roi += 1


# To adjust to the max width
if (self.max_width !=None) and (orig_w_roi != 0) and (orig_w_roi > self.max_width):
select_roi_frame = cv2.resize(select_roi_frame,(int(self.max_width), int(self.max_width/orig_ratio_roi)))


# To show image correctly (IE: web camera)
if self.inv_h_frame:
select_roi_frame = cv2.flip(select_roi_frame, 1)
Expand Down Expand Up @@ -325,17 +325,6 @@ def plot_text(self, frame, frame_w, fps, plot_xmin, plot_ymin, padding, counter_

return frame

def change_res(self, cap, max_width, orig_ratio):
"""
WHAT IT DOES:
- Change te resolution of the frame.
"""

cap.set(3, max_width)
cap.set(4, int(max_width * orig_ratio))

return cap

def run(self):
"""
Expand Down Expand Up @@ -368,7 +357,7 @@ def run(self):
self.roi = self.load_roi()
logging.info('ROI has been loaded.')

cap, self.orig_w, self.orig_h, self.orig_fps = self.load_video_capture(
cap, self.orig_w, self.orig_h, self.orig_ratio, self.orig_fps = self.load_video_capture(
self.video_path)

if not self.roi:
Expand All @@ -387,16 +376,25 @@ def run(self):

start_ends_in_sec = time.time()


# Run detection
while (cap.isOpened()):

# Get frame

# Get frame (The slow streaming video capture
# can be resolved by:
# https://stackoverflow.com/questions/58293187/opencv-real-time-streaming-video-capture-is-slow-how-to-drop-frames-or-get-sync )

ret, self.frame = cap.read()

# To resize frames
if (self.max_width !=None) and (self.orig_w != 0) and (self.orig_w > self.max_width):
self.frame = cv2.resize(self.frame,(int(self.max_width), int(self.max_width/self.orig_ratio)))

# To show image correctly (IE: web camera)
if self.inv_h_frame:
self.frame = cv2.flip(self.frame, 1)


# If the video has not finished yet
if ret:

Expand Down Expand Up @@ -461,7 +459,7 @@ def run(self):
self.stopped = True
break
else:
if cv2.waitKey(int(1000/self.max_fps)) & 0xFF == ord('q'):
if cv2.waitKey(1) & 0xFF == ord('q'):
logging.info('Exiting by keyboard...')
self.stopped = True
break
Expand Down

0 comments on commit e441861

Please sign in to comment.