YACWC
This commit is contained in:
Submodule orin/01_do_obj_det deleted from 8625930f38
@@ -1,132 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
import glob
|
||||
import argparse
|
||||
import os
|
||||
import json
|
||||
from CommonCode.util import exit_if_not_ipython, get_cset_for_file_matching, is_ipython
|
||||
from CommonCode import kwq
|
||||
from CommonCode.settings import get_logger, LogColorize
|
||||
from kafka import TopicPartition
|
||||
from kafka.structs import OffsetAndMetadata
|
||||
from pprint import pprint
|
||||
|
||||
pfm = LogColorize.remove_without_nuggets
|
||||
logger = get_logger(__name__,'/var/log/ml_vision_logs/02_remove_without_nuggets', stdout=True, systemd=False)
|
||||
|
||||
input_topic = kwq.TOPICS.videos_scored_detection
|
||||
|
||||
client_id='obj_detector_remove_without_nuggets'
|
||||
group_id = client_id
|
||||
|
||||
consumer = kwq.create_consumer(input_topic, group_id = group_id, client_id = client_id)
|
||||
c_part = TopicPartition(input_topic, 0)
|
||||
consumer.assign([c_part])
|
||||
|
||||
producer = kwq.producer
|
||||
|
||||
|
||||
class RESULT_TYPE():
|
||||
NOTHING = 0
|
||||
HAS_OBJS = 1
|
||||
KEPT = 2
|
||||
REMOVED = 3
|
||||
NO_JSON = 4
|
||||
|
||||
|
||||
def get_ok_to_delete(file_path):
|
||||
max_look = 5
|
||||
c_path = file_path
|
||||
settings_default = {'class_threshold':10000, 'frames_with_dets_threshold': -10000}
|
||||
for i in range(max_look):
|
||||
c_path = os.path.abspath(os.path.join(c_path, '..'))
|
||||
test_path = os.path.join(c_path, 'settings.json')
|
||||
if os.path.exists(test_path):
|
||||
with open(test_path, 'r') as rr:
|
||||
settings = json.load(rr)
|
||||
settings_default.update(settings)
|
||||
|
||||
return settings_default
|
||||
|
||||
def exec_file_remove_logic(file_path):
|
||||
result = RESULT_TYPE.NOTHING
|
||||
cset = get_cset_for_file_matching(file_path)
|
||||
|
||||
settings = get_ok_to_delete(cset['.mp4'])
|
||||
logger.info(f"EVALUATING LOGIC WITH SETTINGS: "+str(settings))
|
||||
if settings['class_threshold'] > 1:
|
||||
logger.info(f"THRESHOLD SET TO ABOVE 1, SKIPPING: {file_path}")
|
||||
result = RESULT_TYPE.HAS_OBJS
|
||||
return
|
||||
|
||||
logger.info(f"EXECUTING_LOGIC :{file_path}")
|
||||
json_check = '.json.orin'
|
||||
if '.has_objs' in cset:
|
||||
logger.info(f"HAS_OBJS :{file_path}")
|
||||
result = RESULT_TYPE.HAS_OBJS
|
||||
return result
|
||||
|
||||
|
||||
if json_check in cset and os.path.exists(cset[ json_check]):
|
||||
logger.info(f"HAS_JSON :{file_path}")
|
||||
if os.path.getsize(cset[json_check]) == 0:
|
||||
det_data = {'scores':[]}
|
||||
else:
|
||||
with open(cset[json_check],'r') as jj:
|
||||
det_data = json.load(jj)
|
||||
|
||||
thresh = settings['class_threshold']
|
||||
frames_with_dets_thresh = settings['frames_with_dets_threshold']
|
||||
|
||||
all_scores = list()
|
||||
for x in det_data['scores']:
|
||||
sc_in = [y['score'] for y in x['detections']]
|
||||
sc_in.append(0)
|
||||
all_scores.append(max(sc_in))
|
||||
|
||||
frames_above_thresh = sum([x>thresh for x in all_scores ])
|
||||
num_frames = len(det_data['scores'])
|
||||
|
||||
ratio_with_frames = frames_above_thresh / (num_frames + 1)
|
||||
if ratio_with_frames > frames_with_dets_thresh:
|
||||
cpath = os.path.splitext(cset['.mp4'])[0] + '.has_objs.orin'
|
||||
with open(cpath,'w') as cc:
|
||||
pass
|
||||
|
||||
|
||||
logger.info(f"HAS_OBJECTS_DETECTED_WILL_NOT_REMOVE :{pfm(file_path)}")
|
||||
result = RESULT_TYPE.KEPT
|
||||
|
||||
else:
|
||||
logger.info(f"OBJECTS_NOT_DETECTED_WILL_REMOVE :{pfm(file_path)}")
|
||||
for ff, cf in cset.items():
|
||||
if cf.endswith(json_check) or cf.endswith('.jpg'):
|
||||
pass
|
||||
else:
|
||||
logger.info(f"REMOVING :{cf}")
|
||||
os.remove(cf)
|
||||
|
||||
result = RESULT_TYPE.REMOVED
|
||||
|
||||
else:
|
||||
result = RESULT_TYPE.NO_JSON
|
||||
logger.info(f"NO_JSON_DONT_REMOVE :{pfm(file_path)}")
|
||||
|
||||
|
||||
return result
|
||||
|
||||
|
||||
for msg in consumer:
|
||||
key = msg.key
|
||||
value = msg.value
|
||||
|
||||
purge_reason = exec_file_remove_logic(value['filepath'])
|
||||
d_send = {'value':msg.value, 'key':msg.key}
|
||||
if purge_reason in [RESULT_TYPE.KEPT, RESULT_TYPE.HAS_OBJS]:
|
||||
producer.send(kwq.TOPICS.videos_with_nuggets, **d_send)
|
||||
elif purge_reason == RESULT_TYPE.REMOVED:
|
||||
producer.send(kwq.TOPICS.videos_without_nuggets, **d_send)
|
||||
elif purge_reason == RESULT_TYPE.NO_JSON:
|
||||
producer.send(kwq.TOPICS.videos_no_json, **d_send)
|
||||
|
||||
# %%
|
||||
|
||||
@@ -1,115 +0,0 @@
|
||||
import glob
|
||||
from pymilvus import MilvusClient
|
||||
from pymilvus.client.types import LoadState
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import json
|
||||
from CommonCode.util import exit_if_not_ipython, get_cset_for_file_matching, is_ipython
|
||||
from CommonCode import kwq
|
||||
from CommonCode.settings import get_logger, LogColorize
|
||||
from kafka import TopicPartition
|
||||
from kafka.structs import OffsetAndMetadata
|
||||
from pprint import pprint
|
||||
import numpy as np
|
||||
pfm = LogColorize.embeds_in_db
|
||||
logger = get_logger(__name__,'/var/log/ml_vision_logs/03_put_into_vectordb', stdout=True, systemd=False)
|
||||
|
||||
input_topic = kwq.TOPICS.videos_with_nuggets
|
||||
|
||||
client_id='embedding_place_in_db_1'
|
||||
group_id = client_id
|
||||
|
||||
consumer = kwq.create_consumer(input_topic, group_id = group_id, client_id = client_id)
|
||||
c_part = TopicPartition(input_topic, 0)
|
||||
consumer.assign([c_part])
|
||||
|
||||
|
||||
producer = kwq.producer
|
||||
model_type = 'ViT-L-16-SigLIP2-512'
|
||||
|
||||
def get_db_embed_done_path(vpath):
|
||||
return os.path.splitext(vpath)[0]+'.oclip.orin.indb'
|
||||
|
||||
|
||||
#video_file_to_upload='/srv/ftp/ptz/2025/04/14/PTZBackRight_00_20250414063817.mp4'
|
||||
|
||||
|
||||
def get_vec_path(vpath):
|
||||
return os.path.splitext(vpath)[0]+'.oclip.orin'
|
||||
|
||||
def get_date(vpath):
|
||||
split_entries = os.path.splitext(vpath)[0].split('/')
|
||||
return ''.join(split_entries[-4:-1])
|
||||
|
||||
def get_camera_name(vpath):
|
||||
split_entries = os.path.splitext(vpath)[0].split('/')
|
||||
return split_entries[split_entries.index('ftp')+1]
|
||||
|
||||
def upload_vector_file(video_file_to_upload):
|
||||
client = MilvusClient(
|
||||
uri="http://localhost:19530"
|
||||
)
|
||||
|
||||
db_done_path = get_db_embed_done_path(video_file_to_upload)
|
||||
if os.path.exists(db_done_path):
|
||||
print('Already exists in DB, skipping upload')
|
||||
# return
|
||||
|
||||
video_file_to_upload = get_vec_path(video_file_to_upload)
|
||||
|
||||
with open(video_file_to_upload,'r') as jj:
|
||||
vecs = json.load(jj)
|
||||
|
||||
|
||||
embeds = [x['score'] for x in vecs['scores']]
|
||||
fr_nums = [x['frame'] for x in vecs['scores']]
|
||||
|
||||
fname_root = video_file_to_upload.rsplit('/',1)[-1].split('.')[0]
|
||||
fc = fname_root.split('_')[-1]
|
||||
|
||||
# data = list()
|
||||
filepath = video_file_to_upload.replace('/srv/ftp/','').replace('/mergedfs/ftp','').split('.')[-0]
|
||||
|
||||
data_v2 = list()
|
||||
date = get_date(filepath)
|
||||
for embed, frame_num in zip(embeds, fr_nums):
|
||||
fg = '{0:05g}'.format(frame_num)
|
||||
id_num = int(fc+fg)
|
||||
embeds_as_np = np.asarray(embed, dtype=np.float16)
|
||||
to_put_2 = dict(primary_id= id_num, filepath=filepath, frame_number = int(frame_num), so400m=embeds_as_np, date=str(date))
|
||||
data_v2.append(to_put_2)
|
||||
|
||||
cam_name = get_camera_name(video_file_to_upload)
|
||||
client.insert(collection_name = f'nuggets_{cam_name}_so400m_siglip2', data=data_v2)
|
||||
client.close()
|
||||
|
||||
|
||||
with open(db_done_path,'w') as ff:
|
||||
ff.write("")
|
||||
|
||||
print(f'Inserting into DB, {video_file_to_upload}')
|
||||
|
||||
|
||||
|
||||
for msg in consumer:
|
||||
key = msg.key
|
||||
value = msg.value
|
||||
file_path = value['filepath']
|
||||
success = False
|
||||
try:
|
||||
upload_vector_file(value['filepath'])
|
||||
success = True
|
||||
logger.info(f"SUCCESS_UPLOADING :{pfm(file_path)}")
|
||||
except Exception as e:
|
||||
logger.info(f"ERROR_UPLOADING :{pfm(file_path)} + {e}")
|
||||
|
||||
d_send = {'value':msg.value, 'key':msg.key}
|
||||
|
||||
if success:
|
||||
send_topic = kwq.TOPICS.videos_embedding_in_db
|
||||
else:
|
||||
send_topic = kwq.TOPICS.videos_embedding_in_db_fail
|
||||
|
||||
|
||||
producer.send(send_topic, **d_send)
|
||||
Submodule orin/old_01_do_obj_det deleted from 8625930f38
+116
@@ -0,0 +1,116 @@
|
||||
#!/home/thebears/envs/ml_vision_objdet/bin/python
|
||||
import os
|
||||
|
||||
import subprocess as sp
|
||||
import time
|
||||
import psutil
|
||||
import stat
|
||||
import sys
|
||||
import logging
|
||||
from watchdog.observers.polling import PollingObserver
|
||||
from watchdog.events import FileSystemEventHandler
|
||||
from threading import Thread
|
||||
from tqdm import tqdm
|
||||
from common_code import kwq
|
||||
from common_code.settings import get_logger, LogColorize
|
||||
import argparse
|
||||
if not ('__file__' in vars() or '__file__' in globals()):
|
||||
__file__ = '/home/thebears/Source/pipelines/00_watch_for_new_videos/watch_and_fix_permissions.py'
|
||||
|
||||
parent_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
|
||||
sys.path.append(parent_dir)
|
||||
logger = get_logger(__name__,'/var/log/ml_vision_logs/00_load_missed', stdout=True, systemd=False, level=logging.INFO)
|
||||
from common_code import settings
|
||||
|
||||
#default_dir_watch = settings.dir_watch_missed
|
||||
default_dir_watch = settings.dir_watch
|
||||
|
||||
publish = kwq.producer.send
|
||||
#topic = kwq.TOPICS.exit_00_videos_to_score_detection
|
||||
topic = kwq.TOPICS.enter_60_videos_embed_backfill
|
||||
|
||||
necessary_extensions = [
|
||||
'.oclip_embeds.npz',
|
||||
'.detection.npz']
|
||||
|
||||
def decide_to_put_in_queue(file_name, force = False):
|
||||
if os.path.getsize(file_name) < 1*1000*1000:
|
||||
return False
|
||||
disqualifiers = list()
|
||||
disqualifiers.append(not os.path.exists(file_name))
|
||||
disqualifiers.append("_reduced" in file_name)
|
||||
disqualifiers.append("_trimmed" in file_name)
|
||||
# disqualifiers.append('hummingbird' in file_name)
|
||||
|
||||
disqualified = any(disqualifiers)
|
||||
if file_name.endswith(".mp4") and not disqualified:
|
||||
rt_path, _ = os.path.splitext(file_name)
|
||||
if force:
|
||||
all_exist = False
|
||||
else:
|
||||
all_exist = all([os.path.exists( rt_path + ext) for ext in necessary_extensions])
|
||||
return (not all_exist)
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
parent_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
|
||||
sys.path.append(parent_dir)
|
||||
def place_file_in_queue(filef):
|
||||
dirname = os.path.dirname(filef)
|
||||
foldmode = stat.S_IMODE(os.stat(dirname).st_mode)
|
||||
if oct(foldmode) != "0o777":
|
||||
os.system(f"sudo chmod 777 {dirname}")
|
||||
|
||||
logging.info(f"SETTING_PERMISSIONS: {dirname}")
|
||||
|
||||
chand = {"root": os.path.dirname(filef), "name": os.path.basename(filef)}
|
||||
try:
|
||||
|
||||
os.chmod(filef, 0o777)
|
||||
except Exception as e:
|
||||
pass
|
||||
#$ logging.error(e)
|
||||
|
||||
logging.info(f"QUEUE_PUT: {filef}")
|
||||
publish(topic, key=filef, value={"filepath": filef})
|
||||
|
||||
|
||||
|
||||
def add_files_to_queue(paths, dry_run = False, force = False):
|
||||
queued = set()
|
||||
for rt in paths:
|
||||
for root, dirs, files in os.walk(rt):
|
||||
for f in files:
|
||||
new_path = os.path.join(root, f)
|
||||
if decide_to_put_in_queue(new_path, force = force):
|
||||
queued.add(new_path)
|
||||
|
||||
|
||||
for x in tqdm(queued):
|
||||
if dry_run:
|
||||
print('DRY RUN, CANDIDATES FOR QUEUE: ' + x)
|
||||
else:
|
||||
place_file_in_queue(x)
|
||||
|
||||
|
||||
# %%
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(
|
||||
prog="Watch and Fix Permissions And Push to Kafka Queue"
|
||||
)
|
||||
|
||||
parser.add_argument("paths", nargs="*", help="Paths to monitor", default=())
|
||||
parser.add_argument("--dry-run", action='store_true', help='Dry Run')
|
||||
parser.add_argument("--force", action='store_true', help='Force adding (do not check if already done)')
|
||||
args, _ = parser.parse_known_args()
|
||||
paths = args.paths
|
||||
force = args.force
|
||||
dry_run = args.dry_run
|
||||
|
||||
if len(paths) == 0:
|
||||
paths = default_dir_watch
|
||||
|
||||
add_files_to_queue(paths, dry_run = dry_run, force=force)
|
||||
|
||||
|
||||
+12
-14
@@ -8,36 +8,34 @@ import logging
|
||||
from watchdog.observers.polling import PollingObserver
|
||||
from watchdog.events import FileSystemEventHandler
|
||||
from threading import Thread
|
||||
from CommonCode import wq
|
||||
from CommonCode.util import is_ipython
|
||||
from common_code.util import is_ipython
|
||||
import queue
|
||||
from CommonCode.settings import get_logger, LogColorize
|
||||
from common_code.settings import get_logger, LogColorize
|
||||
import argparse
|
||||
|
||||
from common_code import kwq
|
||||
import subprocess
|
||||
from collections import deque
|
||||
|
||||
|
||||
publish = kwq.producer.send
|
||||
topic = kwq.TOPICS.exit_00_videos_to_score_detection
|
||||
|
||||
|
||||
pfm = LogColorize.watch_and_fix_permissions
|
||||
if not ('__file__' in vars() or '__file__' in globals()):
|
||||
__file__ = '/home/thebears/Source/pipelines/00_watch_for_new_videos/watch_and_fix_permissions.py'
|
||||
__file__ = '/home/thebears/Source/pipelines/vision_v3/00_watch_for_new_videos/00_watch_and_fix_permissions.py'
|
||||
|
||||
parent_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
|
||||
sys.path.append(parent_dir)
|
||||
|
||||
from common import settings
|
||||
from common_code import settings
|
||||
default_dir_watch = settings.dir_watch
|
||||
|
||||
tasks = queue.Queue()
|
||||
logger = get_logger(__name__,'/var/log/ml_vision_logs/00_watch_and_fix_permissions', stdout=True, systemd=False, level = logging.INFO)
|
||||
|
||||
logger.info(pfm(f"Starting watch_and_fix_permissions.py"))
|
||||
logger.info(pfm(f"Starting file watcher @ {__file__}"))
|
||||
|
||||
try:
|
||||
from CommonCode import kwq
|
||||
publish = kwq.producer.send
|
||||
topic = kwq.TOPICS.exit_00_videos_to_score_detection
|
||||
except Exception as e:
|
||||
logger.error("ERROR WHEN IMPORTING KAFKA:"+ str(e))
|
||||
|
||||
def decide_to_put_in_queue(file_name):
|
||||
disqualifiers = list()
|
||||
@@ -112,7 +110,7 @@ def process_file(filef):
|
||||
|
||||
if decide_to_put_in_queue(filef):
|
||||
logging.info(f"QUEUE_PUT: {pfm(filef)}")
|
||||
wq.publish(wq.TOPICS.ml_vision_to_score, filef)
|
||||
|
||||
try:
|
||||
future = publish(topic, key=filef, value={"filepath": filef})
|
||||
except Exception as e:
|
||||
Binary file not shown.
@@ -0,0 +1,20 @@
|
||||
from load_missed_lib import place_file_in_queue
|
||||
|
||||
# %%
|
||||
import os
|
||||
|
||||
rrt = ['/srv/ftp_tcc/', '/mnt/hdd_24tb_1/videos/ftp']
|
||||
dir_scan = ['leopards3','leopards4']
|
||||
|
||||
|
||||
rt_scans = list()
|
||||
|
||||
for r1 in rrt:
|
||||
for d1 in dir_scan:
|
||||
rt_scans.append(os.path.join(r1, d1))
|
||||
|
||||
# %%
|
||||
for rt_s in rt_scans:
|
||||
for root, dirs, files in os.walk(rt_s):
|
||||
for x in files:
|
||||
print(x)
|
||||
+6
-7
@@ -10,9 +10,9 @@ import logging
|
||||
from watchdog.observers.polling import PollingObserver
|
||||
from watchdog.events import FileSystemEventHandler
|
||||
from threading import Thread
|
||||
from CommonCode import wq
|
||||
from CommonCode import kwq
|
||||
from CommonCode.settings import get_logger, LogColorize
|
||||
|
||||
from common_code import kwq
|
||||
from common_code.settings import get_logger, LogColorize
|
||||
import argparse
|
||||
if not ('__file__' in vars() or '__file__' in globals()):
|
||||
__file__ = '/home/thebears/Source/pipelines/00_watch_for_new_videos/watch_and_fix_permissions.py'
|
||||
@@ -20,7 +20,7 @@ if not ('__file__' in vars() or '__file__' in globals()):
|
||||
parent_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
|
||||
sys.path.append(parent_dir)
|
||||
logger = get_logger(__name__,'/var/log/ml_vision_logs/00_load_missed', stdout=True, systemd=False, level=logging.INFO)
|
||||
from common import settings
|
||||
from common_code import settings
|
||||
|
||||
#default_dir_watch = settings.dir_watch_missed
|
||||
default_dir_watch = settings.dir_watch
|
||||
@@ -30,8 +30,7 @@ topic = kwq.TOPICS.exit_00_videos_to_score_detection
|
||||
|
||||
necessary_extensions = [
|
||||
'.oclip_embeds.npz',
|
||||
'.json',
|
||||
'.db_has_sl2_embeds_part' ]
|
||||
'.detection.npz']
|
||||
|
||||
def decide_to_put_in_queue(file_name):
|
||||
if os.path.getsize(file_name) < 1*1000*1000:
|
||||
@@ -71,7 +70,7 @@ def place_file_in_queue(filef):
|
||||
|
||||
logging.info(f"QUEUE_PUT: {filef}")
|
||||
publish(topic, key=filef, value={"filepath": filef})
|
||||
wq.publish(wq.TOPICS.ml_vision_to_score, filef)
|
||||
|
||||
|
||||
|
||||
def add_files_to_queue(paths, dry_run = False):
|
||||
@@ -1,11 +0,0 @@
|
||||
from CommonCode import kwq
|
||||
publish = kwq.producer.send
|
||||
topic = kwq.TOPICS.videos_to_score_detection
|
||||
cons = kwq.create_consumer()
|
||||
|
||||
# %%
|
||||
cons.subscribe([topic])
|
||||
|
||||
# %%
|
||||
if True:
|
||||
out = cons.poll()
|
||||
@@ -1,162 +0,0 @@
|
||||
import os
|
||||
import subprocess as sp
|
||||
import time
|
||||
import psutil
|
||||
import stat
|
||||
import sys
|
||||
import logging
|
||||
from watchdog.observers.polling import PollingObserver
|
||||
from watchdog.events import FileSystemEventHandler
|
||||
from threading import Thread
|
||||
from CommonCode import wq
|
||||
|
||||
from CommonCode.settings import get_logger, LogColorize
|
||||
import argparse
|
||||
pfm = LogColorize.watch_and_fix_permissions
|
||||
if not ('__file__' in vars() or '__file__' in globals()):
|
||||
__file__ = '/home/thebears/Source/pipelines/00_watch_for_new_videos/watch_and_fix_permissions.py'
|
||||
|
||||
parent_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
|
||||
sys.path.append(parent_dir)
|
||||
|
||||
from common import settings
|
||||
default_dir_watch = settings.dir_watch
|
||||
# %%
|
||||
logger = get_logger(__name__,'/var/log/ml_vision_logs/00_watch_and_fix_permissions', stdout=True, systemd=False, level = logging.INFO)
|
||||
|
||||
logger.info(pfm(f"Starting watch_and_fix_permissions.py"))
|
||||
|
||||
try:
|
||||
from CommonCode import kwq
|
||||
publish = kwq.producer.send
|
||||
topic = kwq.TOPICS.exit_00_videos_to_score_detection
|
||||
except Exception as e:
|
||||
logger.error("ERROR WHEN IMPORTING KAFKA:"+ str(e))
|
||||
|
||||
def decide_to_put_in_queue(file_name):
|
||||
disqualifiers = list()
|
||||
disqualifiers.append("_reduced" in file_name)
|
||||
disqualifiers.append("_trimmed" in file_name)
|
||||
|
||||
disqualified = any(disqualifiers)
|
||||
|
||||
if file_name.endswith(".mp4") and not disqualified:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
|
||||
class logic_execute(Thread):
|
||||
def __init__(self, event):
|
||||
logging.debug(f"EVENT: {event}")
|
||||
Thread.__init__(self)
|
||||
self.event = event
|
||||
|
||||
def run(self):
|
||||
event = self.event
|
||||
if isinstance(event, str):
|
||||
src_path = event
|
||||
else:
|
||||
src_path = event.src_path
|
||||
|
||||
filef = os.path.abspath(os.path.join(os.getcwd(), src_path))
|
||||
logging.debug(f"GOT_FILE: {pfm(filef)}")
|
||||
|
||||
broke_out = False
|
||||
for i in range(120):
|
||||
files = list()
|
||||
for proc in psutil.process_iter():
|
||||
try:
|
||||
if "ftp" in proc.name():
|
||||
files.append(proc.open_files())
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
f = list()
|
||||
for x in files:
|
||||
f.extend(x)
|
||||
|
||||
if any([filef == e.path for e in f]):
|
||||
pass
|
||||
else:
|
||||
if decide_to_put_in_queue(filef):
|
||||
dirname = os.path.dirname(filef)
|
||||
foldmode = stat.S_IMODE(os.stat(dirname).st_mode)
|
||||
if oct(foldmode) != "0o777":
|
||||
os.system(f"sudo chmod 777 {dirname}")
|
||||
|
||||
logging.info(f"SETTING_PERMISSIONS: {dirname}")
|
||||
broke_out = True
|
||||
break
|
||||
|
||||
time.sleep(1)
|
||||
|
||||
if not broke_out:
|
||||
logging.info(f"TIMED_OUT: {filef}")
|
||||
|
||||
|
||||
chand = {"root": os.path.dirname(filef), "name": os.path.basename(filef)}
|
||||
|
||||
try:
|
||||
os.chmod(filef, 0o777)
|
||||
except Exception as e:
|
||||
logging.error(e)
|
||||
|
||||
if decide_to_put_in_queue(filef):
|
||||
logging.info(f"QUEUE_PUT: {pfm(filef)}")
|
||||
wq.publish(wq.TOPICS.ml_vision_to_score, filef)
|
||||
try:
|
||||
future = publish(topic, key=filef, value={"filepath": filef})
|
||||
except Exception as e:
|
||||
logging.error("KAFKA ERROR " + str(e))
|
||||
else:
|
||||
logging.info(f"QUEUE_DO_NOT_PUT: {filef}")
|
||||
|
||||
|
||||
class Handler(FileSystemEventHandler):
|
||||
def on_created(self, event):
|
||||
try:
|
||||
self.handle_it(event)
|
||||
except Exception as e:
|
||||
logging.error(e)
|
||||
|
||||
def handle_it(self, event):
|
||||
if event.is_directory:
|
||||
return
|
||||
lclass = logic_execute(event)
|
||||
lclass.start()
|
||||
|
||||
|
||||
def observe_path(path):
|
||||
event_handler = Handler()
|
||||
observer = PollingObserver()
|
||||
logger.info(f"Monitoring {path}")
|
||||
observer.schedule(event_handler, path, recursive=True)
|
||||
observer.start()
|
||||
observer.is_alive()
|
||||
return observer
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(
|
||||
prog="Watch and Fix Permissions And Push to Kafka Queue"
|
||||
)
|
||||
|
||||
parser.add_argument("paths", nargs="*", help="Paths to monitor", default=())
|
||||
|
||||
args, _ = parser.parse_known_args()
|
||||
paths = args.paths
|
||||
if len(paths) == 0:
|
||||
paths = default_dir_watch
|
||||
observers = [observe_path(path) for path in paths]
|
||||
|
||||
try:
|
||||
while True:
|
||||
time.sleep(1)
|
||||
except Exception as e:
|
||||
logging.error(str(e))
|
||||
|
||||
for observer in observers:
|
||||
observer.stop()
|
||||
observer.join()
|
||||
@@ -0,0 +1,150 @@
|
||||
from common_code.settings import get_logger, LogColorize
|
||||
import logging
|
||||
pfm = LogColorize.score_obj_det_embed
|
||||
if not ('__file__' in vars() or '__file__' in globals()):
|
||||
__file__ = '/home/thebears/Source/pipelines/vision_v3/10_do_obj_det_and_clip/10_score_videos_objdet_and_clip.py'
|
||||
|
||||
|
||||
logger = get_logger(__name__,'/var/log/ml_vision_logs/10_score_videos_objdet_and_clip', stdout=True, systemd=False, level = logging.INFO)
|
||||
|
||||
import sys
|
||||
sys.path.insert(0,'/home/thebears/Source/task_runners/vision_v3')
|
||||
from cuda_objdet_clip import infer
|
||||
from common_code import kwq, util, file_names, vector_utils
|
||||
from common_code.video_meta import FTPVideo
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import json
|
||||
import traceback
|
||||
|
||||
|
||||
client_suffix = os.environ.get('CONSUMER_CLIENT_SUFFIX','')
|
||||
|
||||
# Call logger twice to reclaim
|
||||
logger = get_logger(__name__,'/var/log/ml_vision_logs/10_score_videos_objdet_and_clip'+client_suffix, stdout=True, systemd=False, level = logging.INFO)
|
||||
logger.info(pfm(f"Starting objdet_and_embedder scoring @ {__file__}"))
|
||||
|
||||
|
||||
pref = ''
|
||||
priority_queue = pref + kwq.TOPICS.enter_60_videos_embed_priority
|
||||
regular_queue = pref + kwq.TOPICS.exit_00_videos_to_score_detection
|
||||
backfill_queue = pref + kwq.TOPICS.enter_60_videos_embed_backfill
|
||||
invalid_file_topic = kwq.TOPICS.exit_60_videos_invalid
|
||||
failed_embed_topic = kwq.TOPICS.exit_60_embedding_failed
|
||||
success_embed_topic = kwq.TOPICS.exit_60_videos_embedded
|
||||
|
||||
|
||||
group_id = "vision_v3"
|
||||
client_id = "objdet_and_embedder"+client_suffix
|
||||
|
||||
|
||||
|
||||
queue_regular = kwq.create_consumer(group_id = group_id, client_id = client_id, auto_offset_reset = 'latest')
|
||||
queue_regular.subscribe([regular_queue])
|
||||
|
||||
|
||||
queue_priority = kwq.create_consumer(group_id = group_id, client_id = client_id, auto_offset_reset = 'latest')
|
||||
queue_priority.subscribe([priority_queue])
|
||||
|
||||
queue_backfill = kwq.create_consumer(group_id = group_id, client_id = client_id, auto_offset_reset = 'earliest')
|
||||
queue_backfill.subscribe([backfill_queue])
|
||||
|
||||
|
||||
|
||||
logging.debug(f'KAFKA: Created subscribers to {regular_queue} and {priority_queue}')
|
||||
|
||||
|
||||
def check_file_validity(file_to_score):
|
||||
if not os.path.exists(file_to_score):
|
||||
return False, "file n/a"
|
||||
|
||||
if os.stat(file_to_score).st_size < 100*1000: #If less than 100kb don't score it
|
||||
return False, "file too small"
|
||||
|
||||
if '_reduced' in file_to_score:
|
||||
return False, 'file reduced resolution'
|
||||
|
||||
|
||||
if '_trimmed' in file_to_score:
|
||||
return False, 'file is trimmed'
|
||||
|
||||
if not file_to_score.endswith('.mp4'):
|
||||
return False, "Not mp4"
|
||||
|
||||
if len(FTPVideo(file_to_score).get_frames_info()) == 0:
|
||||
return False, "Failed getting frame info"
|
||||
|
||||
return True, ""
|
||||
|
||||
|
||||
|
||||
def get_score_file(f):
|
||||
return f.key().decode().strip('"')
|
||||
|
||||
|
||||
def perform_loop_kafka():
|
||||
score_this = None
|
||||
high_priority = False
|
||||
result_priority = queue_priority.poll(timeout=0.05)
|
||||
msg_value = None
|
||||
if result_priority is not None:
|
||||
score_this = get_score_file(result_priority)
|
||||
msg_value = result_priority.value()
|
||||
high_priority = True
|
||||
logging.info(f"KAFKA: high priority file {pfm(score_this)}")
|
||||
queue_priority.commit()
|
||||
else:
|
||||
result_regular = queue_regular.poll(timeout=0.05)
|
||||
if result_regular is not None:
|
||||
msg_value = result_regular.value()
|
||||
score_this = get_score_file(result_regular)
|
||||
logging.info(f"KAFKA: regular priority file {pfm(score_this)}")
|
||||
queue_regular.commit()
|
||||
else:
|
||||
result_backfill = queue_backfill.poll(timeout=0.05)
|
||||
if result_backfill is not None:
|
||||
msg_value = result_backfill.value()
|
||||
score_this = get_score_file(result_backfill)
|
||||
logging.info(f"KAFKA: backfill file {pfm(score_this)}")
|
||||
queue_backfill.commit()
|
||||
|
||||
|
||||
|
||||
|
||||
if score_this is None:
|
||||
return
|
||||
|
||||
file_to_score = file_names.resolve_file_location(score_this)
|
||||
if file_to_score is None:
|
||||
return
|
||||
if file_to_score != score_this:
|
||||
logger.info(f"FILE_PATH_CHANGED: from {pfm(score_this)} to {pfm(file_to_score)}")
|
||||
|
||||
file_is_valid, message = check_file_validity(file_to_score)
|
||||
|
||||
if not file_is_valid:
|
||||
logger.info(f'INVALID_FILE: Skipping {pfm(file_to_score)}')
|
||||
kwq.publish(invalid_file_topic, file_to_score, message)
|
||||
else:
|
||||
logger.info(f'VALID_FILE: Scoring {pfm(file_to_score)}')
|
||||
try:
|
||||
det_scores, clip_scores = infer.score_video_cached(file_to_score, return_dict = True)
|
||||
vector_utils.upload_vectors_to_db( file_to_score, clip_scores['embeds'], clip_scores['frame_numbers'])
|
||||
kwq.publish(success_embed_topic, file_to_score)
|
||||
logger.info(f'SCORING_SUCCESS: {pfm(file_to_score)}')
|
||||
# vector_utils.upload_to_doris( file_to_score, clip_scores['embeds'], clip_scores['frame_numbers'])
|
||||
logging.info(f'UPLOADED TO DB: {pfm(file_to_score)}')
|
||||
except Exception as e:
|
||||
traceback.print_exc()
|
||||
logging.error(f"SCORING_ERROR: {pfm(file_to_score)}: {e}")
|
||||
kwq.publish(failed_embed_topic, file_to_score, str(e))
|
||||
|
||||
|
||||
|
||||
while True:
|
||||
perform_loop_kafka()
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,148 @@
|
||||
from common_code.settings import get_logger, LogColorize
|
||||
import logging
|
||||
pfm = LogColorize.score_obj_det_embed
|
||||
if not ('__file__' in vars() or '__file__' in globals()):
|
||||
__file__ = '/home/thebears/Source/pipelines/vision_v3/10_do_obj_det_and_clip/10_score_videos_objdet_and_clip.py'
|
||||
|
||||
|
||||
logger = get_logger(__name__,'/var/log/ml_vision_logs/10_score_videos_objdet_and_clip', stdout=True, systemd=False, level = logging.INFO)
|
||||
|
||||
import sys
|
||||
sys.path.insert(0,'/home/thebears/Source/task_runners/vision_v3')
|
||||
from cuda_objdet_clip import infer
|
||||
from common_code import kwq, util, file_names, vector_utils
|
||||
from common_code.video_meta import FTPVideo
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import json
|
||||
import traceback
|
||||
|
||||
|
||||
|
||||
# Call logger twice to reclaim
|
||||
logger = get_logger(__name__,'/var/log/ml_vision_logs/10_score_videos_objdet_and_clip', stdout=True, systemd=False, level = logging.INFO)
|
||||
logger.info(pfm(f"Starting objdet_and_embedder scoring @ {__file__}"))
|
||||
|
||||
|
||||
pref = ''
|
||||
priority_queue = pref + kwq.TOPICS.enter_60_videos_embed_priority
|
||||
regular_queue = pref + kwq.TOPICS.exit_00_videos_to_score_detection
|
||||
backfill_queue = pref + kwq.TOPICS.enter_60_videos_embed_backfill
|
||||
invalid_file_topic = kwq.TOPICS.exit_60_videos_invalid
|
||||
failed_embed_topic = kwq.TOPICS.exit_60_embedding_failed
|
||||
success_embed_topic = kwq.TOPICS.exit_60_videos_embedded
|
||||
|
||||
client_suffix = os.environ.get('CONSUMER_CLIENT_SUFFIX','')
|
||||
|
||||
group_id = "vision_v3"
|
||||
client_id = "objdet_and_embedder"+client_suffix
|
||||
|
||||
|
||||
|
||||
queue_regular = kwq.create_consumer(group_id = group_id, client_id = client_id, auto_offset_reset = 'latest')
|
||||
queue_regular.subscribe([regular_queue])
|
||||
|
||||
|
||||
queue_priority = kwq.create_consumer(group_id = group_id, client_id = client_id, auto_offset_reset = 'latest')
|
||||
queue_priority.subscribe([priority_queue])
|
||||
|
||||
queue_backfill = kwq.create_consumer(group_id = group_id, client_id = client_id, auto_offset_reset = 'earliest')
|
||||
queue_backfill.subscribe([backfill_queue])
|
||||
|
||||
|
||||
|
||||
logging.debug(f'KAFKA: Created subscribers to {regular_queue} and {priority_queue}')
|
||||
|
||||
|
||||
def check_file_validity(file_to_score):
|
||||
if not os.path.exists(file_to_score):
|
||||
return False, "file n/a"
|
||||
|
||||
if os.stat(file_to_score).st_size < 100*1000: #If less than 100kb don't score it
|
||||
return False, "file too small"
|
||||
|
||||
if '_reduced' in file_to_score:
|
||||
return False, 'file reduced resolution'
|
||||
|
||||
|
||||
if '_trimmed' in file_to_score:
|
||||
return False, 'file is trimmed'
|
||||
|
||||
if not file_to_score.endswith('.mp4'):
|
||||
return False, "Not mp4"
|
||||
|
||||
if len(FTPVideo(file_to_score).get_frames_info()) == 0:
|
||||
return False, "Failed getting frame info"
|
||||
|
||||
return True, ""
|
||||
|
||||
|
||||
|
||||
def get_score_file(f):
|
||||
return f.key().decode().strip('"')
|
||||
|
||||
|
||||
def perform_loop_kafka():
|
||||
score_this = None
|
||||
high_priority = False
|
||||
result_priority = queue_priority.poll(timeout=0.05)
|
||||
msg_value = None
|
||||
if result_priority is not None:
|
||||
score_this = get_score_file(result_priority)
|
||||
msg_value = result_priority.value()
|
||||
high_priority = True
|
||||
logging.info(f"KAFKA: high priority file {pfm(score_this)}")
|
||||
queue_priority.commit()
|
||||
else:
|
||||
result_regular = queue_regular.poll(timeout=0.05)
|
||||
if result_regular is not None:
|
||||
msg_value = result_regular.value()
|
||||
score_this = get_score_file(result_regular)
|
||||
logging.info(f"KAFKA: regular priority file {pfm(score_this)}")
|
||||
queue_regular.commit()
|
||||
else:
|
||||
result_backfill = queue_backfill.poll(timeout=0.05)
|
||||
if result_backfill is not None:
|
||||
msg_value = result_backfill.value()
|
||||
score_this = get_score_file(result_backfill)
|
||||
logging.info(f"KAFKA: backfill file {pfm(score_this)}")
|
||||
queue_backfill.commit()
|
||||
|
||||
|
||||
|
||||
|
||||
if score_this is None:
|
||||
return
|
||||
|
||||
file_to_score = file_names.resolve_file_location(score_this)
|
||||
if file_to_score is None:
|
||||
return
|
||||
if file_to_score != score_this:
|
||||
logger.info(f"FILE_PATH_CHANGED: from {pfm(score_this)} to {pfm(file_to_score)}")
|
||||
|
||||
file_is_valid, message = check_file_validity(file_to_score)
|
||||
|
||||
if not file_is_valid:
|
||||
logger.info(f'INVALID_FILE: Skipping {pfm(file_to_score)}')
|
||||
kwq.publish(invalid_file_topic, file_to_score, message)
|
||||
else:
|
||||
logger.info(f'VALID_FILE: Scoring {pfm(file_to_score)}')
|
||||
try:
|
||||
det_scores, clip_scores = infer.score_video_cached(file_to_score, return_dict = True)
|
||||
vector_utils.upload_vectors_to_db( file_to_score, clip_scores['embeds'], clip_scores['frame_numbers'])
|
||||
kwq.publish(success_embed_topic, file_to_score)
|
||||
logger.info(f'SCORING_SUCCESS: {pfm(file_to_score)}')
|
||||
except Exception as e:
|
||||
traceback.print_exc()
|
||||
logging.error(f"SCORING_ERROR: {pfm(file_to_score)}: {e}")
|
||||
kwq.publish(failed_embed_topic, file_to_score, str(e))
|
||||
|
||||
|
||||
|
||||
while True:
|
||||
perform_loop_kafka()
|
||||
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,4 @@
|
||||
from common_code.vector_utils import upload_vectors_to_db
|
||||
|
||||
|
||||
upload_vectors_to_db('/srv/ftp_local/backyard/2026/07/03/backyard_00_20260703192858.mp4')
|
||||
@@ -0,0 +1,57 @@
|
||||
from common_code.vector_utils import upload_vectors_to_db
|
||||
from common_code import kwq, util, file_names, vector_utils
|
||||
from multiprocessing import Pool
|
||||
from tqdm import tqdm
|
||||
import argparse
|
||||
import os
|
||||
import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
|
||||
topic_subscribe = 'upload_to_ch_db'
|
||||
def add_files_to_queue(paths, dry_run = False, force = False, do_upload = True, do_queue = False):
|
||||
queued = set()
|
||||
for rt in paths:
|
||||
for root, dirs, files in os.walk(rt):
|
||||
for f in files:
|
||||
new_path = os.path.join(root, f)
|
||||
if new_path.endswith('detection.npz') and 'leopards' not in new_path.lower():
|
||||
# if decide_to_put_in_queue(new_path, force = force):
|
||||
queued.add(new_path)
|
||||
|
||||
for x in tqdm(queued):
|
||||
try:
|
||||
if do_upload:
|
||||
upload_vectors_to_db(x)
|
||||
if do_queue:
|
||||
kwq.publish(topic_subscribe, x, x)
|
||||
|
||||
except Exception as e:
|
||||
print('Failed: '+str(x)+'with '+str(e))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(
|
||||
prog="Watch and Fix Permissions And Push to Kafka Queue"
|
||||
)
|
||||
|
||||
parser.add_argument("paths", nargs="*", help="Paths to monitor", default=())
|
||||
parser.add_argument("--dry-run", action='store_true', help='Dry Run')
|
||||
parser.add_argument("--force", action='store_true', help='Force adding (do not check if already done)')
|
||||
parser.add_argument("--skip_upload", action='store_true', help='Force adding (do not check if already done)')
|
||||
parser.add_argument("--do_queue", action='store_true', help='Force adding (do not check if already done)')
|
||||
args, _ = parser.parse_known_args()
|
||||
paths = args.paths
|
||||
force = args.force
|
||||
dry_run = args.dry_run
|
||||
do_queue = args.do_queue
|
||||
do_upload = not args.skip_upload
|
||||
if len(paths) == 0:
|
||||
paths = default_dir_watch
|
||||
|
||||
add_files_to_queue(paths, dry_run = dry_run, force=force, do_upload = do_upload, do_queue = do_queue)
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
from common_code.vector_utils import upload_to_doris
|
||||
from tqdm import tqdm
|
||||
import argparse
|
||||
import os
|
||||
|
||||
def add_files_to_queue(paths, dry_run = False, force = False):
|
||||
queued = set()
|
||||
for rt in paths:
|
||||
for root, dirs, files in os.walk(rt):
|
||||
for f in files:
|
||||
new_path = os.path.join(root, f)
|
||||
if new_path.endswith('.oclip_embeds.npz'):
|
||||
# if decide_to_put_in_queue(new_path, force = force):
|
||||
queued.add(new_path)
|
||||
|
||||
for x in tqdm(queued):
|
||||
try:
|
||||
upload_to_doris(x)
|
||||
except Exception as e:
|
||||
print('Failed: '+str(x)+'with '+str(e))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(
|
||||
prog="Watch and Fix Permissions And Push to Kafka Queue"
|
||||
)
|
||||
|
||||
parser.add_argument("paths", nargs="*", help="Paths to monitor", default=())
|
||||
parser.add_argument("--dry-run", action='store_true', help='Dry Run')
|
||||
parser.add_argument("--force", action='store_true', help='Force adding (do not check if already done)')
|
||||
args, _ = parser.parse_known_args()
|
||||
paths = args.paths
|
||||
force = args.force
|
||||
dry_run = args.dry_run
|
||||
|
||||
if len(paths) == 0:
|
||||
paths = default_dir_watch
|
||||
|
||||
add_files_to_queue(paths, dry_run = dry_run, force=force)
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
from common_code.vector_utils import upload_vectors_to_db
|
||||
from common_code import kwq, util, file_names, vector_utils, settings
|
||||
from multiprocessing import Pool
|
||||
from tqdm import tqdm
|
||||
import argparse
|
||||
import os
|
||||
import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
|
||||
topic_subscribe = 'upload_to_vector_db'
|
||||
def add_files_to_queue(paths, dry_run = False, force = False, do_upload = True, do_queue = False):
|
||||
queued = set()
|
||||
for rt in paths:
|
||||
for root, dirs, files in os.walk(rt):
|
||||
for f in files:
|
||||
new_path = os.path.join(root, f)
|
||||
if new_path.endswith('.oclip_embeds.npz'):
|
||||
# if decide_to_put_in_queue(new_path, force = force):
|
||||
queued.add(new_path)
|
||||
|
||||
for x in tqdm(queued):
|
||||
try:
|
||||
if do_upload:
|
||||
if os.path.exists(x+'.in_queue'):
|
||||
pass
|
||||
else:
|
||||
upload_vectors_to_db(x)
|
||||
with open(x+'.in_queue','w') as ff:
|
||||
pass
|
||||
if do_queue:
|
||||
kwq.publish(topic_subscribe, x, x)
|
||||
|
||||
except Exception as e:
|
||||
print('Failed: '+str(x)+'with '+str(e))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(
|
||||
prog="Watch and Fix Permissions And Push to Kafka Queue"
|
||||
)
|
||||
|
||||
parser.add_argument("paths", nargs="*", help="Paths to monitor", default=())
|
||||
parser.add_argument("--dry-run", action='store_true', help='Dry Run')
|
||||
parser.add_argument("--force", action='store_true', help='Force adding (do not check if already done)')
|
||||
parser.add_argument("--skip_upload", action='store_true', help='Force adding (do not check if already done)')
|
||||
parser.add_argument("--do_queue", action='store_true', help='Force adding (do not check if already done)')
|
||||
args, _ = parser.parse_known_args()
|
||||
paths = args.paths
|
||||
force = args.force
|
||||
dry_run = args.dry_run
|
||||
do_queue = args.do_queue
|
||||
do_upload = not args.skip_upload
|
||||
if len(paths) == 0:
|
||||
paths = settings.dir_watch
|
||||
|
||||
add_files_to_queue(paths, dry_run = dry_run, force=force, do_upload = do_upload, do_queue = do_queue)
|
||||
|
||||
@@ -0,0 +1,202 @@
|
||||
|
||||
import numpy as np
|
||||
import time
|
||||
from multiprocessing import Process, Queue, Manager
|
||||
import threading
|
||||
from common_code import kwq, util, file_names, vector_utils, video_meta
|
||||
|
||||
from datetime import datetime
|
||||
from clickhouse_connect import get_client
|
||||
|
||||
|
||||
topic_subscribe = 'upload_to_ch_db'
|
||||
group_id = "vision_v3_uploaders"
|
||||
|
||||
def get_score_file(f):
|
||||
return f.key().decode().strip('"')
|
||||
|
||||
|
||||
|
||||
def insert_into_ch(file_path, client):
|
||||
cset = util.get_cset_match(file_path)
|
||||
ff = np.load(cset['.detection.npz'], allow_pickle = True)
|
||||
det_results = dict(ff)
|
||||
del_idx = list()
|
||||
|
||||
filt_scores = det_results['final_scores']
|
||||
filt_frames = det_results['final_frames']
|
||||
spec_label_idx = ff['species_label_map'].tolist()
|
||||
|
||||
ftp_vid = video_meta.FTPVideo(cset)
|
||||
|
||||
frame_num_off = ftp_vid.sorted_frames_info
|
||||
frame_period = ftp_vid.frameperiod
|
||||
frame_rate = ftp_vid.framerate
|
||||
|
||||
indexes = np.searchsorted(ff['scored_frames'], filt_frames)
|
||||
dff = np.diff(ff['scored_frames'])
|
||||
|
||||
head = np.insert(dff, 0, 0)
|
||||
tail = np.append(dff, 0)
|
||||
all_frame_durations = frame_period*np.mean(np.stack([head,tail]), axis=0)
|
||||
|
||||
|
||||
frame_file = [ftp_vid.cpath.split('/')[-1].replace('_reduced','').replace('.mp4','')]*len(filt_frames)
|
||||
frame_bboxes = ff['final_boxes']
|
||||
frame_numbers = filt_frames
|
||||
frame_scores = filt_scores
|
||||
frame_species = [spec_label_idx[int(x)] for x in ff['final_labels']]
|
||||
frame_durations = all_frame_durations[indexes]
|
||||
frame_tstamps = [frame_num_off[x]['time'] for x in filt_frames]
|
||||
db_insert_times = [datetime.now()]*len(filt_frames)
|
||||
|
||||
a = frame_numbers
|
||||
starts = np.r_[0, np.flatnonzero(a[1:] != a[:-1]) + 1]
|
||||
det_count_num = np.arange(len(a)) - np.repeat(starts, np.diff(np.r_[starts, len(a)]))
|
||||
camera = [ftp_vid.camera_name] * len(filt_frames)
|
||||
|
||||
|
||||
result = client.insert('nuggets.cameras_object_detection_results',
|
||||
column_oriented = True,
|
||||
column_names = ['camera','video_filename','frame_number','detection_number','classification_score','object_name','bbox_xyxy','frame_duration','frame_timestamp','db_insert_time'],
|
||||
data = [camera, frame_file, frame_numbers, det_count_num, frame_scores, frame_species, frame_bboxes.tolist(), frame_durations, frame_tstamps, db_insert_times]
|
||||
)
|
||||
|
||||
|
||||
# %%
|
||||
|
||||
|
||||
def watch_and_upload(rank, health_queue):
|
||||
client = get_client(host='192.168.1.242', compression=True)
|
||||
start_time = time.time()
|
||||
client_suffix = '_'+str(rank)
|
||||
client_id = 'uploader_to_ch_db'+client_suffix
|
||||
current_time = time.time()
|
||||
health_queue.put({'rank': rank, 'timestamp': current_time, 'status': 'alive'})
|
||||
health_queue.put({'rank': rank, 'timestamp': current_time, 'status': 'alive'})
|
||||
|
||||
queue = kwq.create_consumer(group_id = group_id, client_id = client_id, auto_offset_reset = 'earliest')
|
||||
queue.subscribe([topic_subscribe])
|
||||
|
||||
last_heartbeat = time.time()
|
||||
|
||||
while True:
|
||||
current_time = time.time()
|
||||
|
||||
# # Exit after 5 minutes
|
||||
# if (current_time - start_time) > 60*5:
|
||||
# print('###########################')
|
||||
# print('######### EXITING #########')
|
||||
# print('###########################')
|
||||
# return
|
||||
|
||||
# Send heartbeat every 10 seconds
|
||||
if current_time - last_heartbeat > 5:
|
||||
try:
|
||||
health_queue.put({'rank': rank, 'timestamp': current_time, 'status': 'alive'})
|
||||
last_heartbeat = current_time
|
||||
except:
|
||||
# Queue might be full, continue working
|
||||
pass
|
||||
|
||||
result = queue.poll(timeout=0.05)
|
||||
if result is not None:
|
||||
try:
|
||||
score_this = get_score_file(result)
|
||||
insert_into_ch(score_this, client)
|
||||
print('#' + str(rank) + ' Uploaded to ' + score_this)
|
||||
# Send success heartbeat
|
||||
try:
|
||||
health_queue.put({'rank': rank, 'timestamp': current_time, 'status': 'working'})
|
||||
except:
|
||||
pass
|
||||
except Exception as e:
|
||||
print('Failed ' + score_this + ':' + str(e))
|
||||
|
||||
queue.commit()
|
||||
|
||||
def health_monitor(processes, health_queues, num_workers):
|
||||
"""Monitor process health and restart hung processes"""
|
||||
last_heartbeat = {}
|
||||
HEALTH_TIMEOUT = 120 # Consider process hung if no heartbeat for 60 seconds
|
||||
|
||||
while True:
|
||||
time.sleep(5) # Check every 5 seconds
|
||||
current_time = time.time()
|
||||
|
||||
for rank in range(num_workers):
|
||||
# Drain the health queue for this process
|
||||
latest_heartbeat = None
|
||||
try:
|
||||
while True:
|
||||
try:
|
||||
heartbeat = health_queues[rank].get_nowait()
|
||||
if heartbeat['rank'] == rank:
|
||||
latest_heartbeat = heartbeat['timestamp']
|
||||
except:
|
||||
break
|
||||
except:
|
||||
pass
|
||||
|
||||
# Update last known heartbeat
|
||||
if latest_heartbeat:
|
||||
last_heartbeat[rank] = latest_heartbeat
|
||||
|
||||
# Check if process is alive and responsive
|
||||
process = processes[rank]
|
||||
last_seen = last_heartbeat.get(rank, 0)
|
||||
|
||||
if not process.is_alive():
|
||||
print(f"Process {rank} has died. Restarting...")
|
||||
processes[rank] = Process(target=watch_and_upload, args=(rank, health_queues[rank]))
|
||||
processes[rank].start()
|
||||
last_heartbeat[rank] = current_time
|
||||
elif current_time - last_seen > HEALTH_TIMEOUT:
|
||||
print(f"Process {rank} appears hung (no heartbeat for {current_time - last_seen:.1f}s). Restarting...")
|
||||
process.terminate()
|
||||
process.join(timeout=5)
|
||||
if process.is_alive():
|
||||
process.kill()
|
||||
process.join()
|
||||
|
||||
# Create new process
|
||||
processes[rank] = Process(target=watch_and_upload, args=(rank, health_queues[rank]))
|
||||
processes[rank].start()
|
||||
last_heartbeat[rank] = current_time
|
||||
|
||||
# Main execution
|
||||
if __name__ == "__main__":
|
||||
num_workers = 4
|
||||
|
||||
# Create health queues for each worker
|
||||
health_queues = [Queue(maxsize=10) for _ in range(num_workers)]
|
||||
|
||||
# Create and start worker processes
|
||||
processes = []
|
||||
for rank in range(num_workers):
|
||||
p = Process(target=watch_and_upload, args=(rank, health_queues[rank]))
|
||||
p.start()
|
||||
processes.append(p)
|
||||
|
||||
# Start health monitor in a separate thread
|
||||
monitor_thread = threading.Thread(
|
||||
target=health_monitor,
|
||||
args=(processes, health_queues, num_workers),
|
||||
daemon=True
|
||||
)
|
||||
monitor_thread.start()
|
||||
|
||||
try:
|
||||
# Wait for all processes to complete (they will exit after 5 minutes)
|
||||
for p in processes:
|
||||
p.join()
|
||||
print("All worker processes completed")
|
||||
except KeyboardInterrupt:
|
||||
print("Shutting down...")
|
||||
for p in processes:
|
||||
p.terminate()
|
||||
p.join(timeout=5)
|
||||
if p.is_alive():
|
||||
p.kill()
|
||||
p.join()
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
from common_code.vector_utils import upload_vectors_to_db
|
||||
from common_code import kwq, util, file_names, vector_utils
|
||||
import time
|
||||
from multiprocessing import Process, Queue, Manager
|
||||
import threading
|
||||
|
||||
topic_subscribe = 'upload_to_vector_db'
|
||||
group_id = "vision_v3_uploaders"
|
||||
|
||||
def get_score_file(f):
|
||||
return f.key().decode().strip('"')
|
||||
|
||||
def watch_and_upload(rank, health_queue):
|
||||
start_time = time.time()
|
||||
client_suffix = '_'+str(rank)
|
||||
client_id = 'uploader_to_vector_db'+client_suffix
|
||||
|
||||
queue = kwq.create_consumer(group_id = group_id, client_id = client_id, auto_offset_reset = 'earliest')
|
||||
queue.subscribe([topic_subscribe])
|
||||
|
||||
last_heartbeat = time.time()
|
||||
|
||||
while True:
|
||||
current_time = time.time()
|
||||
|
||||
# # Exit after 5 minutes
|
||||
# if (current_time - start_time) > 60*5:
|
||||
# print('###########################')
|
||||
# print('######### EXITING #########')
|
||||
# print('###########################')
|
||||
# return
|
||||
|
||||
# Send heartbeat every 10 seconds
|
||||
if current_time - last_heartbeat > 5:
|
||||
try:
|
||||
health_queue.put({'rank': rank, 'timestamp': current_time, 'status': 'alive'})
|
||||
last_heartbeat = current_time
|
||||
except:
|
||||
# Queue might be full, continue working
|
||||
pass
|
||||
|
||||
result = queue.poll(timeout=0.05)
|
||||
if result is not None:
|
||||
score_this = get_score_file(result)
|
||||
try:
|
||||
upload_vectors_to_db(score_this)
|
||||
print('#' + str(rank) + ' Uploaded to ' + score_this)
|
||||
# Send success heartbeat
|
||||
try:
|
||||
health_queue.put({'rank': rank, 'timestamp': current_time, 'status': 'working'})
|
||||
except:
|
||||
pass
|
||||
except Exception as e:
|
||||
print('Failed ' + score_this + ':' + str(e))
|
||||
|
||||
queue.commit()
|
||||
|
||||
def health_monitor(processes, health_queues, num_workers):
|
||||
"""Monitor process health and restart hung processes"""
|
||||
last_heartbeat = {}
|
||||
HEALTH_TIMEOUT = 15 # Consider process hung if no heartbeat for 60 seconds
|
||||
|
||||
while True:
|
||||
time.sleep(5) # Check every 5 seconds
|
||||
current_time = time.time()
|
||||
|
||||
for rank in range(num_workers):
|
||||
# Drain the health queue for this process
|
||||
latest_heartbeat = None
|
||||
try:
|
||||
while True:
|
||||
try:
|
||||
heartbeat = health_queues[rank].get_nowait()
|
||||
if heartbeat['rank'] == rank:
|
||||
latest_heartbeat = heartbeat['timestamp']
|
||||
except:
|
||||
break
|
||||
except:
|
||||
pass
|
||||
|
||||
# Update last known heartbeat
|
||||
if latest_heartbeat:
|
||||
last_heartbeat[rank] = latest_heartbeat
|
||||
|
||||
# Check if process is alive and responsive
|
||||
process = processes[rank]
|
||||
last_seen = last_heartbeat.get(rank, 0)
|
||||
|
||||
if not process.is_alive():
|
||||
print(f"Process {rank} has died. Restarting...")
|
||||
processes[rank] = Process(target=watch_and_upload, args=(rank, health_queues[rank]))
|
||||
processes[rank].start()
|
||||
last_heartbeat[rank] = current_time
|
||||
elif current_time - last_seen > HEALTH_TIMEOUT:
|
||||
print(f"Process {rank} appears hung (no heartbeat for {current_time - last_seen:.1f}s). Restarting...")
|
||||
process.terminate()
|
||||
process.join(timeout=5)
|
||||
if process.is_alive():
|
||||
process.kill()
|
||||
process.join()
|
||||
|
||||
# Create new process
|
||||
processes[rank] = Process(target=watch_and_upload, args=(rank, health_queues[rank]))
|
||||
processes[rank].start()
|
||||
last_heartbeat[rank] = current_time
|
||||
|
||||
# Main execution
|
||||
if __name__ == "__main__":
|
||||
num_workers = 4
|
||||
|
||||
# Create health queues for each worker
|
||||
health_queues = [Queue(maxsize=10) for _ in range(num_workers)]
|
||||
|
||||
# Create and start worker processes
|
||||
processes = []
|
||||
for rank in range(num_workers):
|
||||
p = Process(target=watch_and_upload, args=(rank, health_queues[rank]))
|
||||
p.start()
|
||||
processes.append(p)
|
||||
|
||||
# Start health monitor in a separate thread
|
||||
monitor_thread = threading.Thread(
|
||||
target=health_monitor,
|
||||
args=(processes, health_queues, num_workers),
|
||||
daemon=True
|
||||
)
|
||||
monitor_thread.start()
|
||||
|
||||
try:
|
||||
# Wait for all processes to complete (they will exit after 5 minutes)
|
||||
for p in processes:
|
||||
p.join()
|
||||
print("All worker processes completed")
|
||||
except KeyboardInterrupt:
|
||||
print("Shutting down...")
|
||||
for p in processes:
|
||||
p.terminate()
|
||||
p.join(timeout=5)
|
||||
if p.is_alive():
|
||||
p.kill()
|
||||
p.join()
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
from common_code.settings import get_logger, LogColorize
|
||||
import logging
|
||||
pfm = LogColorize.score_obj_det_embed
|
||||
if not ('__file__' in vars() or '__file__' in globals()):
|
||||
__file__ = '/home/thebears/Source/pipelines/vision_v3/40_do_cropped_clip/40_do_cropped_clip.py'
|
||||
|
||||
|
||||
log_file = '/var/log/ml_vision_logs/40_do_cropped_clip'
|
||||
logger = get_logger(__name__,log_file, stdout=True, systemd=False, level = logging.INFO)
|
||||
|
||||
import sys
|
||||
sys.path.insert(0,'/home/thebears/Source/task_runners/vision_v3')
|
||||
from cuda_objdet_clip import infer
|
||||
from common_code import kwq, util, file_names, vector_utils
|
||||
from common_code.video_meta import FTPVideo
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import json
|
||||
import traceback
|
||||
|
||||
|
||||
client_suffix = os.environ.get('CONSUMER_CLIENT_SUFFIX','')
|
||||
|
||||
# Call logger twice to reclaim
|
||||
logger = get_logger(__name__,log_file, stdout=True, systemd=False, level = logging.INFO)
|
||||
logger.info(pfm(f"Starting objdet_and_embedder scoring @ {__file__}"))
|
||||
|
||||
|
||||
pref = ''
|
||||
regular_queue = pref + kwq.TOPICS.exit_60_videos_embedded
|
||||
|
||||
|
||||
|
||||
group_id = "vision_v3"
|
||||
client_id = "cropped_embedder"+client_suffix
|
||||
|
||||
|
||||
queue_regular = kwq.create_consumer(group_id = group_id, client_id = client_id, auto_offset_reset = 'latest')
|
||||
queue_regular.subscribe([regular_queue])
|
||||
|
||||
logging.debug(f'KAFKA: Created subscribers to {regular_queue}')
|
||||
|
||||
def check_file_validity(file_to_score):
|
||||
if 'leopard' in file_to_score.lower():
|
||||
return True, ''
|
||||
else:
|
||||
return False, ''
|
||||
|
||||
|
||||
def get_score_file(f):
|
||||
return f.key().decode().strip('"')
|
||||
|
||||
def perform_loop_kafka():
|
||||
score_this = None
|
||||
msg_value = None
|
||||
result_regular = queue_regular.poll(timeout=0.05)
|
||||
if result_regular is not None:
|
||||
msg_value = result_regular.value()
|
||||
score_this = get_score_file(result_regular)
|
||||
logging.info(f"KAFKA: regular priority file {pfm(score_this)}")
|
||||
queue_regular.commit()
|
||||
|
||||
if score_this is None:
|
||||
return
|
||||
|
||||
file_to_score = file_names.resolve_file_location(score_this)
|
||||
if file_to_score is None:
|
||||
return
|
||||
|
||||
|
||||
|
||||
|
||||
if file_to_score != score_this:
|
||||
logger.info(f"FILE_PATH_CHANGED: from {pfm(score_this)} to {pfm(file_to_score)}")
|
||||
|
||||
file_is_valid, message = check_file_validity(file_to_score)
|
||||
if not file_is_valid:
|
||||
logger.info(f'INVALID_FILE: Skipping {pfm(file_to_score)}')
|
||||
return
|
||||
|
||||
logger.info(f'VALID_FILE: Scoring {pfm(file_to_score)}')
|
||||
try:
|
||||
infer.score_video_sub_clip_cached( file_to_score)
|
||||
logger.info(f'SCORING_SUCCESS: {pfm(file_to_score)}')
|
||||
except Exception as e:
|
||||
traceback.print_exc()
|
||||
logging.error(f"SCORING_ERROR: {pfm(file_to_score)}: {e}")
|
||||
|
||||
while True:
|
||||
perform_loop_kafka()
|
||||
|
||||
Reference in New Issue
Block a user