Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d286b9b311 | |||
| 19ace202ba |
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.observers.polling import PollingObserver
|
||||||
from watchdog.events import FileSystemEventHandler
|
from watchdog.events import FileSystemEventHandler
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
from CommonCode import wq
|
from common_code.util import is_ipython
|
||||||
from CommonCode.util import is_ipython
|
|
||||||
import queue
|
import queue
|
||||||
from CommonCode.settings import get_logger, LogColorize
|
from common_code.settings import get_logger, LogColorize
|
||||||
import argparse
|
import argparse
|
||||||
|
from common_code import kwq
|
||||||
import subprocess
|
import subprocess
|
||||||
from collections import deque
|
from collections import deque
|
||||||
|
|
||||||
|
|
||||||
|
publish = kwq.producer.send
|
||||||
|
topic = kwq.TOPICS.exit_00_videos_to_score_detection
|
||||||
|
|
||||||
|
|
||||||
pfm = LogColorize.watch_and_fix_permissions
|
pfm = LogColorize.watch_and_fix_permissions
|
||||||
if not ('__file__' in vars() or '__file__' in globals()):
|
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__), '..'))
|
parent_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
|
||||||
sys.path.append(parent_dir)
|
sys.path.append(parent_dir)
|
||||||
|
|
||||||
from common import settings
|
from common_code import settings
|
||||||
default_dir_watch = settings.dir_watch
|
default_dir_watch = settings.dir_watch
|
||||||
|
|
||||||
tasks = queue.Queue()
|
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 = 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):
|
def decide_to_put_in_queue(file_name):
|
||||||
disqualifiers = list()
|
disqualifiers = list()
|
||||||
@@ -112,7 +110,7 @@ def process_file(filef):
|
|||||||
|
|
||||||
if decide_to_put_in_queue(filef):
|
if decide_to_put_in_queue(filef):
|
||||||
logging.info(f"QUEUE_PUT: {pfm(filef)}")
|
logging.info(f"QUEUE_PUT: {pfm(filef)}")
|
||||||
wq.publish(wq.TOPICS.ml_vision_to_score, filef)
|
|
||||||
try:
|
try:
|
||||||
future = publish(topic, key=filef, value={"filepath": filef})
|
future = publish(topic, key=filef, value={"filepath": filef})
|
||||||
except Exception as e:
|
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.observers.polling import PollingObserver
|
||||||
from watchdog.events import FileSystemEventHandler
|
from watchdog.events import FileSystemEventHandler
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
from CommonCode import wq
|
|
||||||
from CommonCode import kwq
|
from common_code import kwq
|
||||||
from CommonCode.settings import get_logger, LogColorize
|
from common_code.settings import get_logger, LogColorize
|
||||||
import argparse
|
import argparse
|
||||||
if not ('__file__' in vars() or '__file__' in globals()):
|
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/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__), '..'))
|
parent_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
|
||||||
sys.path.append(parent_dir)
|
sys.path.append(parent_dir)
|
||||||
logger = get_logger(__name__,'/var/log/ml_vision_logs/00_load_missed', stdout=True, systemd=False, level=logging.INFO)
|
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_missed
|
||||||
default_dir_watch = settings.dir_watch
|
default_dir_watch = settings.dir_watch
|
||||||
@@ -30,8 +30,7 @@ topic = kwq.TOPICS.exit_00_videos_to_score_detection
|
|||||||
|
|
||||||
necessary_extensions = [
|
necessary_extensions = [
|
||||||
'.oclip_embeds.npz',
|
'.oclip_embeds.npz',
|
||||||
'.json',
|
'.detection.npz']
|
||||||
'.db_has_sl2_embeds_part' ]
|
|
||||||
|
|
||||||
def decide_to_put_in_queue(file_name):
|
def decide_to_put_in_queue(file_name):
|
||||||
if os.path.getsize(file_name) < 1*1000*1000:
|
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}")
|
logging.info(f"QUEUE_PUT: {filef}")
|
||||||
publish(topic, key=filef, value={"filepath": 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):
|
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,42 @@
|
|||||||
|
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
from common_code import kwq
|
||||||
|
from common_code.util import get_cset_match
|
||||||
|
from common_code.file_names import resolve_file_location
|
||||||
|
import json
|
||||||
|
import sys
|
||||||
|
import logging
|
||||||
|
from common_code.settings import get_logger, LogColorize
|
||||||
|
sys.path.insert(0, "/home/thebears/Source/ml/sources_mltraining/model_runner/")
|
||||||
|
from video_reduce_resolution import convert_file_with_check
|
||||||
|
from common_code import settings
|
||||||
|
default_dir_watch = settings.dir_watch
|
||||||
|
|
||||||
|
|
||||||
|
pfm = LogColorize.file_modifications
|
||||||
|
logger = get_logger(__name__,'/var/log/ml_vision_logs/20_add_into_queue', stdout=True, systemd=False, level = logging.INFO)
|
||||||
|
|
||||||
|
success_det_and_embed_topic = kwq.TOPICS.exit_60_videos_embedded
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
f_nav = list()
|
||||||
|
for c_dir in settings.dir_watch_archived():
|
||||||
|
for root, _, files in os.walk(c_dir):
|
||||||
|
for f in files:
|
||||||
|
if f.endswith('.mp4') and "reduced" not in f:
|
||||||
|
cfile = os.path.join( root, f)
|
||||||
|
f_nav.append(cfile)
|
||||||
|
|
||||||
|
|
||||||
|
# %%
|
||||||
|
#for f, _ in zip(f_nav, range(10)):
|
||||||
|
from tqdm import tqdm
|
||||||
|
|
||||||
|
kwq.publish(success_det_and_embed_topic, f)
|
||||||
|
|
||||||
|
# %%
|
||||||
|
|
||||||
+154
@@ -0,0 +1,154 @@
|
|||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
from common_code import kwq
|
||||||
|
from common_code.util import get_cset_match
|
||||||
|
from common_code.file_names import resolve_file_location
|
||||||
|
import json
|
||||||
|
import sys
|
||||||
|
import logging
|
||||||
|
from common_code.settings import get_logger, LogColorize
|
||||||
|
sys.path.insert(0, "/home/thebears/Source/ml/sources_mltraining/model_runner/")
|
||||||
|
from video_reduce_resolution import convert_file_with_check
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
pfm = LogColorize.file_modifications
|
||||||
|
logger = get_logger(__name__,'/var/log/ml_vision_logs/20_delete_files_and_create_other_videos', stdout=True, systemd=False, level = logging.INFO)
|
||||||
|
|
||||||
|
success_det_and_embed_topic = kwq.TOPICS.exit_60_videos_embedded
|
||||||
|
|
||||||
|
group_id = "vision_v3"
|
||||||
|
client_id = "file_converter"
|
||||||
|
|
||||||
|
if not ('__file__' in vars() or '__file__' in globals()):
|
||||||
|
__file__ = '/home/thebears/Source/pipelines/vision_v3/20_delete_files_and_create_other_videos/20_delete_files_and_create_other_videos.py'
|
||||||
|
|
||||||
|
|
||||||
|
logger.info(pfm(f"Starting file modifier @ {__file__}"))
|
||||||
|
|
||||||
|
|
||||||
|
queue = kwq.create_consumer(group_id = group_id, client_id = client_id, auto_offset_reset = 'earliest')
|
||||||
|
queue.subscribe([success_det_and_embed_topic])
|
||||||
|
|
||||||
|
# %%
|
||||||
|
def get_ok_to_delete(file_path):
|
||||||
|
max_look = 5
|
||||||
|
c_path = file_path
|
||||||
|
settings_default = {'class_threshold':10000, 'frames_with_dets_threshold': -10000, 'species_ignore': [], 'keep_reduced_mp4': False}
|
||||||
|
|
||||||
|
depth_set = dict()
|
||||||
|
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:
|
||||||
|
depth_set[i] = json.load(rr)
|
||||||
|
|
||||||
|
depth_set = dict(sorted(depth_set.items(), reverse=True))
|
||||||
|
|
||||||
|
for depth, val in depth_set.items():
|
||||||
|
settings_default.update(val)
|
||||||
|
|
||||||
|
|
||||||
|
settings_default['species_ignore'] = set(settings_default['species_ignore'])
|
||||||
|
return settings_default
|
||||||
|
# %%
|
||||||
|
|
||||||
|
def exec_file_remove_logic(cset, dry_run = False):
|
||||||
|
|
||||||
|
|
||||||
|
did_purge = False
|
||||||
|
if isinstance(cset, dict):
|
||||||
|
file_path = cset['.mp4']
|
||||||
|
else:
|
||||||
|
file_path = cset
|
||||||
|
cset = get_cset_match(file_path)
|
||||||
|
|
||||||
|
settings = get_ok_to_delete(file_path)
|
||||||
|
|
||||||
|
if settings['class_threshold'] > 1 or settings['class_threshold'] <= 0:
|
||||||
|
print(f"THRESHOLD SET TO ABOVE 1, SKIPPING: {file_path}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
if '.detection.npz' in cset and os.path.exists(cset['.detection.npz']):
|
||||||
|
ff = np.load(cset['.detection.npz'], allow_pickle = True)
|
||||||
|
det_results = dict(ff)
|
||||||
|
|
||||||
|
del_idx = list()
|
||||||
|
for idx, val in det_results['species_label_map'].item().items():
|
||||||
|
if val in settings['species_ignore']:
|
||||||
|
del_idx.append(idx)
|
||||||
|
|
||||||
|
keep_mask = ~np.isin(det_results['final_labels'], del_idx)
|
||||||
|
|
||||||
|
filt_scores = det_results['final_scores'][keep_mask]
|
||||||
|
filt_frames = det_results['final_frames'][keep_mask]
|
||||||
|
|
||||||
|
passes = filt_scores > settings['class_threshold']
|
||||||
|
|
||||||
|
n_frames_above = len(np.unique(filt_frames[passes]))
|
||||||
|
n_frames_scored = len(det_results['scored_frames'])
|
||||||
|
|
||||||
|
frac_frames_scored = n_frames_above / n_frames_scored
|
||||||
|
do_keep = frac_frames_scored > settings['frames_with_dets_threshold']
|
||||||
|
|
||||||
|
|
||||||
|
keep_reduced_mp4 = settings['keep_reduced_mp4']
|
||||||
|
if do_keep:
|
||||||
|
cpath = os.path.splitext(cset['.mp4'])[0] + '.has_objs'
|
||||||
|
with open(cpath,'w') as cc:
|
||||||
|
pass
|
||||||
|
did_purge = False
|
||||||
|
else:
|
||||||
|
did_purge = True
|
||||||
|
|
||||||
|
for ff, cf in cset.items():
|
||||||
|
if cf.endswith('npz') or cf.endswith('jpg'):
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
if not dry_run and os.path.exists(cf):
|
||||||
|
if '_reduced' in cf:
|
||||||
|
logger.info(f"Skipping reduced_mp4 deletion {pfm(cf)}")
|
||||||
|
continue
|
||||||
|
|
||||||
|
logger.info(f"Removing {pfm(cf)}")
|
||||||
|
else:
|
||||||
|
print(f'Skipping deleting {ff} because of dry run or path not exist')
|
||||||
|
return did_purge
|
||||||
|
|
||||||
|
def get_score_file(f):
|
||||||
|
return f.key().decode().strip('"')
|
||||||
|
|
||||||
|
from common_code.video_meta import FTPVideo
|
||||||
|
|
||||||
|
|
||||||
|
def perform_kafka_loop():
|
||||||
|
try:
|
||||||
|
# if True:
|
||||||
|
result = queue.poll(timeout=0.05)
|
||||||
|
if result is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
queue.commit()
|
||||||
|
file_to_score = resolve_file_location(get_score_file(result))
|
||||||
|
if file_to_score is None:
|
||||||
|
logger.info(f"Not found {pfm(file_to_score)}")
|
||||||
|
return
|
||||||
|
logger.info(f"Executing file operations {pfm(file_to_score)}")
|
||||||
|
did_purge = exec_file_remove_logic(get_cset_match(file_to_score))
|
||||||
|
if not did_purge:
|
||||||
|
did_convert = convert_file_with_check(file_to_score)
|
||||||
|
FTPVideo(file_to_score).frames_info;
|
||||||
|
|
||||||
|
logger.info(f"Finished file operations {pfm(file_to_score)}")
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Failed: {pfm(file_to_score)}, {str(e)}")
|
||||||
|
|
||||||
|
|
||||||
|
while True:
|
||||||
|
perform_kafka_loop()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
from CommonCode import wq
|
||||||
|
from CommonCode.video_meta import FTPVideo
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
|
||||||
|
|
||||||
|
sys.path.insert(0, "/home/thebears/Source/ml/sources_mltraining/scoring_scheduler")
|
||||||
|
sys.path.insert(0, "/home/thebears/Source/ml/sources_mltraining/model_runner/")
|
||||||
|
|
||||||
|
from trim_with_birds import execute_file_trimming
|
||||||
|
from video_reduce_resolution import convert_file_with_check
|
||||||
|
input_topic = wq.TOPICS.ml_vision_objdet_results_purge_skipped
|
||||||
|
output_if_success = wq.TOPICS.ml_vision_videos_modify_success
|
||||||
|
output_if_fail = wq.TOPICS.ml_vision_videos_modify_failed
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def perform_loop():
|
||||||
|
file_to_score = wq.consume(input_topic)
|
||||||
|
if file_to_score is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
did_trim = False# did_trim = execute_file_trimming(files_to_check = file_to_score)
|
||||||
|
did_convert = convert_file_with_check(file_to_score)
|
||||||
|
FTPVideo(file_to_score).frames_info;
|
||||||
|
wq.publish(output_if_success, file_to_score)
|
||||||
|
print(f"File trimmed:{did_trim}, did_downsize:{did_convert}, {file_to_score}")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
wq.publish(output_if_fail, {file_to_score: str(e)})
|
||||||
|
print(f"File fail to create {file_to_score}, {e}")
|
||||||
|
|
||||||
|
# %%
|
||||||
|
while True:
|
||||||
|
perform_loop()
|
||||||
|
time.sleep(1)
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
|
||||||
|
det_npz = '/srv/ftp/railing/2025/11/17/railing_00_20251117140039.detection.npz'
|
||||||
|
mp4_path = '/srv/ftp/railing/2025/11/17/railing_00_20251117140039.mp4'
|
||||||
|
import numpy as np
|
||||||
|
ff = np.load(det_npz, allow_pickle = True)
|
||||||
|
det_results = dict(ff)
|
||||||
|
|
||||||
|
del_idx = list()
|
||||||
|
from common_code.video_meta import FTPVideo
|
||||||
|
FTPVideo(mp4_path)
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
|
||||||
|
|
||||||
|
from CommonCode import wq, kwq
|
||||||
|
sys.path.insert(0, "/home/thebears/Source/ml/sources_mltraining/scoring_scheduler")
|
||||||
|
sys.path.insert(0, "/home/thebears/Source/ml/sources_mltraining/model_runner/")
|
||||||
|
from purge_without_birds import execute_file_purging
|
||||||
|
|
||||||
|
from video_reduce_resolution import convert_file
|
||||||
|
|
||||||
|
input_topic = wq.TOPICS.ml_vision_objdet_results_pg_success
|
||||||
|
output_if_success = wq.TOPICS.ml_vision_objdet_results_purge_success
|
||||||
|
output_if_fail = wq.TOPICS.ml_vision_objdet_results_purge_failed
|
||||||
|
output_if_skipped = wq.TOPICS.ml_vision_objdet_results_purge_skipped
|
||||||
|
|
||||||
|
|
||||||
|
topic_if_has_nuggets = kwq.TOPICS.exit_40_videos_with_nuggets
|
||||||
|
topic_if_no_nuggets = kwq.TOPICS.exit_40_videos_without_nuggets
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def perform_loop():
|
||||||
|
file_to_score = wq.consume(input_topic)
|
||||||
|
if file_to_score is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
purged_result = execute_file_purging(files_to_check=file_to_score)
|
||||||
|
did_purge = False
|
||||||
|
if purged_result is not None and len(purged_result) > 0:
|
||||||
|
did_purge = purged_result[0]
|
||||||
|
|
||||||
|
if did_purge:
|
||||||
|
wq.publish(output_if_success, file_to_score)
|
||||||
|
print(f"File purged {file_to_score}")
|
||||||
|
kwq.publish(topic_if_no_nuggets, file_to_score)
|
||||||
|
else:
|
||||||
|
wq.publish(output_if_skipped, file_to_score)
|
||||||
|
print(f"File not purged {file_to_score}")
|
||||||
|
kwq.publish(topic_if_has_nuggets, file_to_score)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
wq.publish(output_if_fail, {file_to_score: str(e)})
|
||||||
|
print(f"File failed to purge {file_to_score}, {e}")
|
||||||
|
|
||||||
|
|
||||||
|
# %%
|
||||||
|
while True:
|
||||||
|
perform_loop()
|
||||||
|
time.sleep(1)
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
from pymilvus import MilvusClient, DataType
|
||||||
|
import numpy as np
|
||||||
|
import time
|
||||||
|
from pymilvus.client.types import LoadState
|
||||||
|
client = MilvusClient(
|
||||||
|
uri="http://localhost:19530"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
res = client.get_load_state(
|
||||||
|
collection_name="nuggets_so400m"
|
||||||
|
)
|
||||||
|
if res['state'] == LoadState.Loaded:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
client.load_collection(collection_name = 'nuggets_so400m')
|
||||||
|
for i in range(10):
|
||||||
|
time.sleep(1)
|
||||||
|
if res['state'] == LoadState.Loaded:
|
||||||
|
break
|
||||||
|
|
||||||
|
|
||||||
|
def get_vec_path(vpath):
|
||||||
|
return os.path.splitext(vpath)[0]+'.oclip_embeds.npz'
|
||||||
|
|
||||||
|
def get_db_embed_done_path(vpath):
|
||||||
|
return os.path.splitext(vpath)[0]+'.db_has_oclip_embeds'
|
||||||
|
|
||||||
|
|
||||||
|
def upload_vector_file(vector_file_to_upload):
|
||||||
|
if os.path.exists(get_embed_done_path(vector_file_to_upload)):
|
||||||
|
print('Already exists in DB, skipping upload')
|
||||||
|
return
|
||||||
|
|
||||||
|
vector_file_to_upload = get_vec_path(vector_file_to_upload)
|
||||||
|
vf = np.load(vector_file_to_upload)
|
||||||
|
|
||||||
|
embeds = vf['embeds']
|
||||||
|
fr_nums = vf['frame_numbers']
|
||||||
|
|
||||||
|
fname_root = vector_file_to_upload.rsplit('/',1)[-1].split('.')[0]
|
||||||
|
fc = fname_root.split('_')[-1]
|
||||||
|
|
||||||
|
data = list()
|
||||||
|
filepath = vector_file_to_upload.replace('/srv/ftp/','').replace('/mergedfs/ftp','').split('.')[-0]
|
||||||
|
|
||||||
|
for embed, frame_num in zip(embeds, fr_nums):
|
||||||
|
fg = '{0:05g}'.format(frame_num)
|
||||||
|
id_num = int(fc+fg)
|
||||||
|
to_put = dict(primary_id= id_num, filepath=filepath, frame_number = int(frame_num), so400m=embed)
|
||||||
|
data.append(to_put)
|
||||||
|
|
||||||
|
client.insert(collection_name = 'nuggets_so400m', data = data)
|
||||||
|
print(f'Inserting into DB, {vector_file_to_upload}')
|
||||||
|
|
||||||
|
with open(get_embed_done_path(vector_file_to_upload),'w') as ff:
|
||||||
|
ff.write(str(time.time()))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
root_path = '/srv/ftp/railing/2026/'
|
||||||
|
to_put = list()
|
||||||
|
for root, dirs, files in os.walk(root_path):
|
||||||
|
for x in files:
|
||||||
|
if x.endswith('oclip_embeds.npz'):
|
||||||
|
to_put.append(os.path.join(root, x))
|
||||||
|
|
||||||
|
|
||||||
|
for x in to_put:
|
||||||
|
upload_vector_file(x)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -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