--- hls_streaming/hls.py
+++ hls_streaming/hls.py
... | ... | @@ -9,6 +9,7 @@ |
9 | 9 |
from datetime import datetime |
10 | 10 |
from threading import Lock, Thread, Event |
11 | 11 |
|
12 |
+DEBUG = False |
|
12 | 13 |
|
13 | 14 |
|
14 | 15 |
class FrameCapturer: |
... | ... | @@ -38,7 +39,7 @@ |
38 | 39 |
self.buffer_size = buffer_size |
39 | 40 |
self.frame_buffer = [] |
40 | 41 |
self.current_frame = [] |
41 |
- self.frame_buffer_lock = Lock() # for no memory sharing between receive_stream_packet and process_frames |
|
42 |
+ self.frame_buffer_lock = Lock() # for no memory sharing between receive_stream_packet and process_frames |
|
42 | 43 |
self.captured_frame_count = 0 |
43 | 44 |
self.last_capture_time = 0 |
44 | 45 |
self.start_time = time.time() |
... | ... | @@ -59,7 +60,6 @@ |
59 | 60 |
def __call__(self, *args, **kwargs): |
60 | 61 |
return self.current_frame |
61 | 62 |
|
62 |
- |
|
63 | 63 |
# ```receive_stream_packet``` and ```process_frames``` work asynchronously (called with Thread) |
64 | 64 |
# so that it always run as intended (for every '''interval''' sec, send a photo) |
65 | 65 |
# regardless of how you buffer frames as long as there are enough buffer. |
... | ... | @@ -71,6 +71,9 @@ |
71 | 71 |
self.frame_buffer.append(frame) |
72 | 72 |
time.sleep(self.capture_interval) |
73 | 73 |
|
74 |
+ #TODO Although there is no problems with how it works and how it was intended, because there seems to be an |
|
75 |
+ # unexpected behaivor on "if current_time - self.start_time >= self.buffer_duration:" line, |
|
76 |
+ # more inspection should be done |
|
74 | 77 |
def process_frames(self): |
75 | 78 |
while not self.stop_event.is_set(): |
76 | 79 |
current_time = time.time() |
... | ... | @@ -88,10 +91,13 @@ |
88 | 91 |
img_binary = cv2.imencode('.png', self.current_frame) |
89 | 92 |
img_binary = img_binary[1].tobytes() |
90 | 93 |
self.send_image_to_server(img_binary) |
91 |
- cv2.imwrite(f'hls_streaming/captured_frame_/{self.cctvid}_{datetime.now()}_{frame_name}', self.current_frame) |
|
94 |
+ if DEBUG: |
|
95 |
+ cv2.imwrite( |
|
96 |
+ f'hls_streaming/captured_frame_/{self.cctvid}_{datetime.now()}_{frame_name}', |
|
97 |
+ self.current_frame) |
|
92 | 98 |
self.last_capture_time = current_time |
93 | 99 |
# print(f"Captured {frame_name} of {self.cctvid} at time: {current_time - self.start_time:.2f}s") |
94 |
- self.captured_frame_count +=1 |
|
100 |
+ self.captured_frame_count += 1 |
|
95 | 101 |
|
96 | 102 |
time.sleep(0.1) |
97 | 103 |
|
... | ... | @@ -100,20 +106,20 @@ |
100 | 106 |
header = { |
101 | 107 |
'Content-Type': f'image/{image_type}', |
102 | 108 |
'x-time-sent': time_sent, |
103 |
- # Why are you encoding string? because post method has a problem with sending not english chars. |
|
109 |
+ # Why are you encoding string? because post method has a problem with sending non-english chars. |
|
104 | 110 |
# (It defaults to latin-1 encoding and not straight forward to change) |
105 | 111 |
'x-cctv-name': base64.b64encode(str(self.cctvid).encode('utf-8')).decode('ascii'), |
106 |
- 'x-cctv-latitude' : str(self.lat), |
|
107 |
- 'x-cctv-longitude' : str(self.lon), |
|
112 |
+ 'x-cctv-latitude': str(self.lat), |
|
113 |
+ 'x-cctv-longitude': str(self.lon), |
|
108 | 114 |
} |
109 | 115 |
session = requests.Session() |
110 | 116 |
try: |
111 | 117 |
multipart_data = MultipartEncoder( |
112 |
- fields = { |
|
118 |
+ fields={ |
|
113 | 119 |
'file': (f'frame_{self.cctvid}.{image_type}', |
114 |
- image, |
|
115 |
- f'image/{image_type}') |
|
116 |
- } |
|
120 |
+ image, |
|
121 |
+ f'image/{image_type}') |
|
122 |
+ } |
|
117 | 123 |
) |
118 | 124 |
header["Content-Type"] = multipart_data.content_type |
119 | 125 |
response = session.post(self.endpoint, headers=header, data=multipart_data) |
... | ... | @@ -151,5 +157,5 @@ |
151 | 157 |
del capturer |
152 | 158 |
t2 = time.time() |
153 | 159 |
with open("result.txt", "w") as file: |
154 |
- file.write(f'{t2-t1} seconds before terminating') |
|
160 |
+ file.write(f'{t2 - t1} seconds before terminating') |
|
155 | 161 |
exit() |
--- run_image_anal_backend.sh
+++ run_image_anal_backend.sh
... | ... | @@ -20,8 +20,30 @@ |
20 | 20 |
cleanup() { |
21 | 21 |
echo "Terminating all processes..." |
22 | 22 |
for pid in "${pids[@]}"; do |
23 |
+ # Attempt to terminate the process |
|
23 | 24 |
kill -9 $pid |
25 |
+ |
|
26 |
+ # Wait a bit for the process to terminate |
|
27 |
+ sleep 1 |
|
28 |
+ |
|
29 |
+ # Check if the process is still running |
|
30 |
+ if kill -0 $pid 2>/dev/null; then |
|
31 |
+ echo "Process $pid did not terminate, trying again..." |
|
32 |
+ kill -9 $pid |
|
33 |
+ sleep 1 # Wait a bit before checking again |
|
34 |
+ |
|
35 |
+ # Final check - if it still didn't terminate, report failure |
|
36 |
+ if kill -0 $pid 2>/dev/null; then |
|
37 |
+ echo "Failed to terminate process $pid." |
|
38 |
+ else |
|
39 |
+ echo "Process $pid terminated successfully after retry." |
|
40 |
+ fi |
|
41 |
+ else |
|
42 |
+ echo "Process $pid terminated successfully." |
|
43 |
+ fi |
|
24 | 44 |
done |
45 |
+ echo "Exiting script." |
|
46 |
+ exit 0 # Exit the script |
|
25 | 47 |
} |
26 | 48 |
|
27 | 49 |
# Trap keyboard interrupt and call cleanup |
--- streaming_process.py
+++ streaming_process.py
... | ... | @@ -20,10 +20,22 @@ |
20 | 20 |
return api_result.loc[0]["cctvurl"] |
21 | 21 |
|
22 | 22 |
args = argparse.ArgumentParser() |
23 |
- args.add_argument("--cctv_num", type=int, help="index number of cctv, see cctv_list.csv") |
|
23 |
+ args.add_argument("--cctv_num", type=int, |
|
24 |
+ help="Index number of cctv, to view or edit the list of cctv, see cctv_list.csv") |
|
25 |
+ args.add_argument("--interval", type=float, default=5, |
|
26 |
+ help="Interval of frame extract of the process, unit is second, default is 5 seconds") |
|
27 |
+ args.add_argument("--video_buffer", type=float, default=15, |
|
28 |
+ help="How may seconds of video frame buffer will be there, " |
|
29 |
+ "default value is 15 seconds, which matches ITS video streaming packet response interval") |
|
30 |
+ |
|
24 | 31 |
args = args.parse_args() |
25 | 32 |
|
33 |
+ # This is a must, because if you refer to variables inside args directly, |
|
34 |
+ # when ERROR happens out of that variables or related, python can not |
|
35 |
+ # direct you to where it happens and instead unintelligible garbage |
|
26 | 36 |
cctv_ind = args.cctv_num |
37 |
+ frame_extract_interval = args.interval |
|
38 |
+ video_buffer = args.video_buffer |
|
27 | 39 |
|
28 | 40 |
cctv_info = pd.read_csv("config_files/cctv_list.csv") |
29 | 41 |
cctv_info = cctv_info.iloc[cctv_ind] |
... | ... | @@ -41,7 +53,7 @@ |
41 | 53 |
|
42 | 54 |
cctv_url = refresh_hls_address(lat, lon, ) |
43 | 55 |
print(name) |
44 |
- hls_streaming = FrameCapturer(cctv_url, name, lat, lon, 5, 15, 300, "Asia/Seoul", |
|
56 |
+ hls_streaming = FrameCapturer(cctv_url, name, lat, lon, frame_extract_interval, video_buffer, 300, "Asia/Seoul", |
|
45 | 57 |
endpoint= "http://localhost:12345/cctv/infer") |
46 | 58 |
hls_streaming.start() |
47 | 59 |
|
--- yoloseg/inference_.py
+++ yoloseg/inference_.py
... | ... | @@ -142,6 +142,8 @@ |
142 | 142 |
all_mask = full_masks.sum(axis=0) |
143 | 143 |
all_mask = np.clip(all_mask, 0, 1) |
144 | 144 |
# Append a dimension so that cv2 can understand ```all_mask``` argument as an image. |
145 |
+ # This is because for this particular application, there is only single class ```water_body``` |
|
146 |
+ # However, if that is not the case, you must modify this part. |
|
145 | 147 |
all_mask = all_mask.reshape((image_shape[0], image_shape[1], 1)) |
146 | 148 |
return all_mask.astype(np.uint8) |
147 | 149 |
|
... | ... | @@ -200,6 +202,9 @@ |
200 | 202 |
Returns: |
201 | 203 |
np.ndarray: The image_binary with the overlay. |
202 | 204 |
""" |
205 |
+ assert alpha <= 1 and 0 <= alpha, (f"Error! invalid alpha value, it must be float, inbetween including 0 to 1, " |
|
206 |
+ f"\n given alpha : {alpha}") |
|
207 |
+ |
|
203 | 208 |
# Ensure the mask is a binary mask |
204 | 209 |
mask = (mask > 0).astype(np.uint8) # Convert mask to binary if not already |
205 | 210 |
|
Add a comment
Delete comment
Once you delete this comment, you won't be able to recover it. Are you sure you want to delete this comment?