Пример #1
0
def main_handler():
    # set up logging to syslog
    # construct the argument parse and parse the arguments
  
    ap = argparse.ArgumentParser()
    ap.add_argument('-c', '--config', help='config file with path')
    ap.add_argument('-e', '--eventid', help='event ID to retrieve')
    ap.add_argument('-p',
                    '--eventpath',
                    help='path to store object image file',
                    default='')
    ap.add_argument('-m', '--monitorid', help='monitor id - needed for mask')
    ap.add_argument('-v',
                    '--version',
                    help='print version and quit',
                    action='store_true')

    ap.add_argument('-o', '--output-path',
                    help='internal testing use only - path for debug images to be written')

    ap.add_argument('-f',
                    '--file',
                    help='internal testing use only - skips event download')


    ap.add_argument('-r', '--reason', help='reason for event (notes field in ZM)')

    ap.add_argument('-n', '--notes', help='updates notes field in ZM with detections', action='store_true')
    ap.add_argument('-d', '--debug', help='enables debug on console', action='store_true')

    args, u = ap.parse_known_args()
    args = vars(args)

    if args.get('version'):
        print('hooks:{} pyzm:{}'.format(hooks_version, pyzm_version))
        exit(0)

    if not args.get('config'):
        print ('--config required')
        exit(1)

    if not args.get('file')and not args.get('eventid'):
        print ('--eventid required')
        exit(1)

    utils.get_pyzm_config(args)

    if args.get('debug'):
        g.config['pyzm_overrides']['dump_console'] = True
        g.config['pyzm_overrides']['log_debug'] = True
        g.config['pyzm_overrides']['log_level_debug'] = 5
        g.config['pyzm_overrides']['log_debug_target'] = None

    if args.get('monitorid'):
        log.init(name='zmesdetect_' + 'm' + args.get('monitorid'), override=g.config['pyzm_overrides'])
    else:
        log.init(name='zmesdetect',override=g.config['pyzm_overrides'])
    g.logger = log
    
    es_version='(?)'
    try:
        es_version=subprocess.check_output(['/usr/bin/zmeventnotification.pl', '--version']).decode('ascii')
    except:
        pass


    try:
        import cv2
    except ImportError as e:
        g.logger.Fatal (f'{e}: You might not have installed OpenCV as per install instructions. Remember, it is NOT automatically installed')

    g.logger.Info('---------| pyzm version:{}, hook version:{},  ES version:{} , OpenCV version:{}|------------'.format(pyzm_version, hooks_version, es_version, cv2.__version__))
   

    
    # load modules that depend on cv2
    try:
        import zmes_hook_helpers.image_manip as img
    except Exception as e:
        g.logger.Error (f'{e}')
        exit(1)
    g.polygons = []

    # process config file
    g.ctx = ssl.create_default_context()
    utils.process_config(args, g.ctx)


    # misc came later, so lets be safe
    if not os.path.exists(g.config['base_data_path'] + '/misc/'):
        try:
            os.makedirs(g.config['base_data_path'] + '/misc/')
        except FileExistsError:
            pass  # if two detects run together with a race here

    if not g.config['ml_gateway']:
        g.logger.Info('Importing local classes for Object/Face')
        import pyzm.ml.object as object_detection
       
    else:
        g.logger.Info('Importing remote shim classes for Object/Face')
        from zmes_hook_helpers.apigw import ObjectRemote, FaceRemote, AlprRemote
    # now download image(s)


    start = datetime.datetime.now()

    obj_json = []

    import pyzm.api as zmapi
    api_options  = {
    'apiurl': g.config['api_portal'],
    'portalurl': g.config['portal'],
    'user': g.config['user'],
    'password': g.config['password'] ,
    'logger': g.logger, # use none if you don't want to log to ZM,
    #'disable_ssl_cert_check': True
    }

    g.logger.Info('Connecting with ZM APIs')
    zmapi = zmapi.ZMApi(options=api_options)
    stream = args.get('eventid') or args.get('file')
    ml_options = {}
    stream_options={}
    secrets = None 
    
    if g.config['ml_sequence'] and g.config['use_sequence'] == 'yes':
        g.logger.Debug(2,'using ml_sequence')
        ml_options = g.config['ml_sequence']
        secrets = pyzmutils.read_config(g.config['secrets'])
        ml_options = pyzmutils.template_fill(input_str=ml_options, config=None, secrets=secrets._sections.get('secrets'))
        ml_options = ast.literal_eval(ml_options)
        g.config['ml_sequence'] = ml_options
    else:
        g.logger.Debug(2,'mapping legacy ml data from config')
        ml_options = utils.convert_config_to_ml_sequence()
    

    if g.config['stream_sequence'] and g.config['use_sequence'] == 'yes': # new sequence
        g.logger.Debug(2,'using stream_sequence')
        stream_options = g.config['stream_sequence']
        stream_options = ast.literal_eval(stream_options)
        g.config['stream_sequence'] = stream_options
    else: # legacy
        g.logger.Debug(2,'mapping legacy stream data from config')
        if g.config['detection_mode'] == 'all':
            g.config['detection_mode'] = 'most_models'
        frame_set = g.config['frame_id']
        if g.config['frame_id'] == 'bestmatch':
            if g.config['bestmatch_order'] == 's,a':
                frame_set = 'snapshot,alarm'
            else:
                frame_set = 'alarm,snapshot'
        stream_options['resize'] =int(g.config['resize']) if g.config['resize'] != 'no' else None

       
        stream_options['strategy'] = g.config['detection_mode'] 
        stream_options['frame_set'] = frame_set       

    # These are stream options that need to be set outside of supplied configs         
    stream_options['api'] = zmapi
    
    stream_options['polygons'] = g.polygons

    '''
    stream_options = {
            'api': zmapi,
            'download': False,
            'frame_set': frame_set,
            'strategy': g.config['detection_mode'],
            'polygons': g.polygons,
            'resize': int(g.config['resize']) if g.config['resize'] != 'no' else None

    }
    '''

   
    m = None
    matched_data = None
    all_data = None

    if not args['file'] and int(g.config['wait']) > 0:
        g.logger.Info('Sleeping for {} seconds before inferencing'.format(
            g.config['wait']))
        time.sleep(g.config['wait'])

    if g.config['ml_gateway']:
        stream_options['api'] = None
        stream_options['monitorid'] = args.get('monitorid')
        start = datetime.datetime.now()
        try:
            matched_data,all_data = remote_detect(stream=stream, options=stream_options, api=zmapi)
            diff_time = (datetime.datetime.now() - start)
            g.logger.Debug(1,'Total remote detection detection took: {}'.format(diff_time))
        except Exception as e:
            g.logger.Error ("Error with remote mlapi:{}".format(e))
            g.logger.Debug(2,traceback.format_exc())

            if g.config['ml_fallback_local'] == 'yes':
                g.logger.Debug (1, "Falling back to local detection")
                stream_options['api'] = zmapi
                from pyzm.ml.detect_sequence import DetectSequence
                m = DetectSequence(options=ml_options, logger=g.logger)
                matched_data,all_data = m.detect_stream(stream=stream, options=stream_options)
    

    else:
        from pyzm.ml.detect_sequence import DetectSequence
        m = DetectSequence(options=ml_options, logger=g.logger)
        matched_data,all_data = m.detect_stream(stream=stream, options=stream_options)
    


    #print(f'ALL FRAMES: {all_data}\n\n')
    #print (f"SELECTED FRAME {matched_data['frame_id']}, size {matched_data['image_dimensions']} with LABELS {matched_data['labels']} {matched_data['boxes']} {matched_data['confidences']}")
    #print (matched_data)
    '''
     matched_data = {
            'boxes': matched_b,
            'labels': matched_l,
            'confidences': matched_c,
            'frame_id': matched_frame_id,
            'image_dimensions': self.media.image_dimensions(),
            'image': matched_frame_img
        }
    '''

    # let's remove past detections first, if enabled 
    if g.config['match_past_detections'] == 'yes' and args.get('monitorid'):
        # point detections to post processed data set
        g.logger.Info('Removing matches to past detections')
        bbox_t, label_t, conf_t = img.processPastDetection(
            matched_data['boxes'], matched_data['labels'], matched_data['confidences'], args.get('monitorid'))
        # save current objects for future comparisons
        g.logger.Debug(1,
            'Saving detections for monitor {} for future match'.format(
                args.get('monitorid')))
        try:
            mon_file = g.config['image_path'] + '/monitor-' + args.get(
            'monitorid') + '-data.pkl'
            f = open(mon_file, "wb")
            pickle.dump(matched_data['boxes'], f)
            pickle.dump(matched_data['labels'], f)
            pickle.dump(matched_data['confidences'], f)
            f.close()
        except Exception as e:
            g.logger.Error(f'Error writing to {mon_file}, past detections not recorded:{e}')

        matched_data['boxes'] = bbox_t
        matched_data['labels'] = label_t
        matched_data['confidences'] = conf_t

    obj_json = {
        'labels': matched_data['labels'],
        'boxes': matched_data['boxes'],
        'frame_id': matched_data['frame_id'],
        'confidences': matched_data['confidences'],
        'image_dimensions': matched_data['image_dimensions']
    }

    # 'confidences': ["{:.2f}%".format(item * 100) for item in matched_data['confidences']],
    
    detections = []
    seen = {}
    pred=''
    prefix = ''

    if matched_data['frame_id'] == 'snapshot':
        prefix = '[s] '
    elif matched_data['frame_id'] == 'alarm':
        prefix = '[a] '
    else:
        prefix = '[x] '
        #g.logger.Debug (1,'CONFIDENCE ARRAY:{}'.format(conf))
    for idx, l in enumerate(matched_data['labels']):
        if l not in seen:
            if g.config['show_percent'] == 'no':
                pred = pred + l + ','
            else:
                pred = pred + l + ':{:.0%}'.format(matched_data['confidences'][idx]) + ' '
            seen[l] = 1

    if pred != '':
        pred = pred.rstrip(',')
        pred = prefix + 'detected:' + pred
        g.logger.Info('Prediction string:{}'.format(pred))
        jos = json.dumps(obj_json)
        g.logger.Debug(1,'Prediction string JSON:{}'.format(jos))
        print(pred + '--SPLIT--' + jos)

        if (matched_data['image'] is not None) and (g.config['write_image_to_zm'] == 'yes' or g.config['write_debug_image'] == 'yes'):
            debug_image = pyzmutils.draw_bbox(image=matched_data['image'],boxes=matched_data['boxes'], 
                                              labels=matched_data['labels'], confidences=matched_data['confidences'],
                                              polygons=g.polygons, poly_thickness = g.config['poly_thickness'])

            if g.config['write_debug_image'] == 'yes':
                for _b in matched_data['error_boxes']:
                    cv2.rectangle(debug_image, (_b[0], _b[1]), (_b[2], _b[3]),
                        (0,0,255), 1)
                filename_debug = g.config['image_path']+'/'+os.path.basename(append_suffix(stream, '-{}-debug'.format(matched_data['frame_id'])))
                g.logger.Debug (1,'Writing bound boxes to debug image: {}'.format(filename_debug))
                cv2.imwrite(filename_debug,debug_image)

            if g.config['write_image_to_zm'] == 'yes' and args.get('eventpath'):
                g.logger.Debug(1,'Writing detected image to {}/objdetect.jpg'.format(
                    args.get('eventpath')))
                cv2.imwrite(args.get('eventpath') + '/objdetect.jpg', debug_image)
                jf = args.get('eventpath')+ '/objects.json'
                g.logger.Debug(1,'Writing JSON output to {}'.format(jf))
                try:
                    with open(jf, 'w') as jo:
                        json.dump(obj_json, jo)
                        jo.close()
                except Exception as e:
                    g.logger.Error(f'Error creating {jf}:{e}')
                    
        if args.get('notes'):
            url = '{}/events/{}.json'.format(g.config['api_portal'], args['eventid'])
            try:
                ev = zmapi._make_request(url=url,  type='get')
            except Exception as e:
                g.logger.Error ('Error during event notes retrieval: {}'.format(str(e)))
                g.logger.Debug(2,traceback.format_exc())
                exit(0) # Let's continue with zmdetect

            new_notes = pred
            if ev.get('event',{}).get('Event',{}).get('Notes'): 
                old_notes = ev['event']['Event']['Notes']
                old_notes_split = old_notes.split('Motion:')
                old_d = old_notes_split[0] # old detection
                try:
                    old_m = old_notes_split[1] 
                except IndexError:
                    old_m = ''
                new_notes = pred + 'Motion:'+ old_m
                g.logger.Debug (1,'Replacing old note:{} with new note:{}'.format(old_notes, new_notes))
                

            payload = {}
            payload['Event[Notes]'] = new_notes
            try:
                ev = zmapi._make_request(url=url, payload=payload, type='put')
            except Exception as e:
                g.logger.Error ('Error during notes update: {}'.format(str(e)))
                g.logger.Debug(2,traceback.format_exc())

        if g.config['create_animation'] == 'yes':
            if not args.get('eventid'):
                g.logger.Error ('Cannot create animation as you did not pass an event ID')
            else:
                g.logger.Debug(1,'animation: Creating burst...')
                try:
                    img.createAnimation(matched_data['frame_id'], args.get('eventid'), args.get('eventpath')+'/objdetect', g.config['animation_types'])
                except Exception as e:
                    g.logger.Error('Error creating animation:{}'.format(e))
                    g.logger.Error('animation: Traceback:{}'.format(traceback.format_exc()))
Пример #2
0
if len(sys.argv) == 1:
    eid = input('Enter event ID to analyze:')
else:
    eid = sys.argv[1]
'''
api_options = {
    'apiurl': 'https://demo.zoneminder.com/zm/api',
    'portalurl': 'https://demo.zoneminder.com/zm',
    'user': '******',
    'password': '******',
    'logger': logger, # use none if you don't want to log to ZM,
    #'disable_ssl_cert_check': True
}
'''

conf = utils.read_config('/etc/zm/secrets.ini')
api_options = {
    'apiurl': utils.get(key='ZM_API_PORTAL', section='secrets', conf=conf),
    'portalurl': utils.get(key='ZM_PORTAL', section='secrets', conf=conf),
    'user': utils.get(key='ZM_USER', section='secrets', conf=conf),
    'password': utils.get(key='ZM_PASSWORD', section='secrets', conf=conf),
    'logger': logger,  # use none if you don't want to log to ZM,
    #'disable_ssl_cert_check': True
}

zmapi = zmapi.ZMApi(options=api_options, logger=logger)
ml_options = {
    'general': {
        'model_sequence': 'object,face,alpr',
        'disable_locks': 'no'
    },
Пример #3
0
api = Api(app, prefix='/api/v1')
app.config['UPLOAD_FOLDER'] = g.config['images_path']
app.config['MAX_CONTENT_LENGTH'] = g.MAX_FILE_SIZE_MB * 1024 * 1024
app.config['JWT_SECRET_KEY'] = g.config['mlapi_secret_key']
app.config['JWT_ACCESS_TOKEN_EXPIRES'] = g.ACCESS_TOKEN_EXPIRES
app.config['PROPAGATE_EXCEPTIONS'] = True
app.debug = False
jwt = JWTManager(app)

db = Database.Database()

api.add_resource(Login, '/login')
api.add_resource(Detect, '/detect/object')
api.add_resource(Health, '/health')

secrets_conf = pyzmutils.read_config(g.config['secrets'])

api_options  = {
    'apiurl': pyzmutils.get(key='ZM_API_PORTAL', section='secrets', conf=secrets_conf),
    'portalurl':pyzmutils.get(key='ZM_PORTAL', section='secrets', conf=secrets_conf),
    'user': pyzmutils.get(key='ZM_USER', section='secrets', conf=secrets_conf),
    'password': pyzmutils.get(key='ZM_PASSWORD', section='secrets', conf=secrets_conf),
    'disable_ssl_cert_check':False if g.config['allow_self_signed']=='no' else True
}

g.log.set_level(5)

if not api_options.get('apiurl') or not api_options.get('portalurl'):
    g.log.Fatal('Missing API and/or Portal URLs. Your secrets file probably doesn\'t have these values')

zmapi = zmapi.ZMApi(options=api_options, logger=g.log)
Пример #4
0
# Desktop notifications of zm alarms using pyzm

import pyzm, getpass, traceback, gi, time, playsound, argparse, os, datetime
import pyzm.api as zmapi
import pyzm.ZMMemory as zmmemory
import pyzm.helpers.utils as utils
from pyzm.helpers.Base import ConsoleLog
from gi.repository import Notify

zmPath = os.path.realpath(__file__).replace('/zmNotify.py', '')
logFile = os.path.join(zmPath, "zmNotify.log")
alertSoundFile = os.path.join(zmPath, 'alert.ogg')
lastidFile = os.path.join(zmPath, 'lastid')
logger = ConsoleLog()
logger.set_level(1)  # 2 will display each poll
conf = utils.read_config(os.path.join(zmPath, 'secrets.ini'))
Notify.init("zmNotifyMessage")

api_options = {
    'apiurl': utils.get(key='ZM_API_PORTAL', section='secrets', conf=conf),
    'portalurl': utils.get(key='ZM_PORTAL', section='secrets', conf=conf),
    'user': utils.get(key='ZM_USER', section='secrets', conf=conf),
    'password': utils.get(key='ZM_PASSWORD', section='secrets', conf=conf),
    'logger': logger
}

zmapi = zmapi.ZMApi(options=api_options)

event_filter = {
    'object_only': True,
    'min_alarmed_frames': 2,
Пример #5
0
def process_config(args):
    # parse config file into a dictionary with defaults

    g.config = {}

    has_secrets = False
    secrets_file = None

    def _correct_type(val, t):
        if t == 'int':
            return int(val)
        elif t == 'eval' or t == 'dict':
            return ast.literal_eval(val) if val else None
        elif t == 'str_split':
            return str_split(val) if val else None
        elif t == 'string':
            return val
        elif t == 'float':
            return float(val)
        else:
            g.logger.Error(
                'Unknown conversion type {} for config key:{}'.format(
                    e['type'], e['key']))
            return val

    def _set_config_val(k, v):
        # internal function to parse all keys
        val = config_file[v['section']].get(k, v['default'])

        if val and val[0] == '!':  # its a secret token, so replace
            g.logger.Debug(1, 'Secret token found in config: {}'.format(val))
            if not has_secrets:
                raise ValueError(
                    'Secret token found, but no secret file specified')
            if secrets_file.has_option('secrets', val[1:]):
                vn = secrets_file.get('secrets', val[1:])
                #g.logger.Debug (1,'Replacing {} with {}'.format(val,vn))
                val = vn
            else:
                raise ValueError(
                    'secret token {} not found in secrets file {}'.format(
                        val, secrets_filename))

        g.config[k] = _correct_type(val, v['type'])
        if k.find('password') == -1:
            dval = g.config[k]
        else:
            dval = '***********'
        #g.logger.Debug (1,'Config: setting {} to {}'.format(k,dval))

    # main
    try:
        config_file = ConfigParser(interpolation=None,
                                   inline_comment_prefixes='#')
        config_file.read(args['config'])

        g.config['pyzm_overrides'] = {}
        if config_file.has_option('general', 'pyzm_overrides'):
            pyzm_overrides = config_file.get('general', 'pyzm_overrides')
            g.config['pyzm_overrides'] = ast.literal_eval(
                pyzm_overrides) if pyzm_overrides else {}
            if args.get('debug'):
                g.config['pyzm_overrides']['dump_console'] = True
                g.config['pyzm_overrides']['log_debug'] = True
                g.config['pyzm_overrides']['log_level_debug'] = 5
                g.config['pyzm_overrides']['log_debug_target'] = None

        if config_file.has_option('general', 'use_zm_logs'):
            use_zm_logs = config_file.get('general', 'use_zm_logs')
            if use_zm_logs == 'yes':
                try:
                    import pyzm.ZMLog as zmlog
                    zmlog.init(name='zm_mlapi',
                               override=g.config['pyzm_overrides'])
                except Exception as e:
                    g.logger.Error(
                        'Not able to switch to ZM logs: {}'.format(e))
                else:
                    g.log = zmlog
                    g.logger = g.log
                    g.logger.Info('Switched to ZM logs')
                    g.logger.Info('Reading config from: {}'.format(
                        args.get('config')))

        g.logger.Info('Reading config from: {}'.format(args.get('config')))

        if config_file.has_option('general', 'secrets'):
            secrets_filename = config_file.get('general', 'secrets')
            g.config['secrets'] = secrets_filename
            g.logger.Info('Reading secrets from: {}'.format(secrets_filename))
            has_secrets = True
            secrets_file = ConfigParser(interpolation=None,
                                        inline_comment_prefixes='#')
            try:
                with open(secrets_filename) as f:
                    secrets_file.read_file(f)
            except:
                raise
        else:
            g.logger.Debug(1, 'No secrets file configured')
        # now read config values

        g.polygons = []
        # first, fill in config with default values
        for k, v in g.config_vals.items():
            val = v.get('default', None)
            g.config[k] = _correct_type(val, v['type'])
            #print ('{}={}'.format(k,g.config[k]))

        # now iterate the file
        for sec in config_file.sections():
            if sec == 'secrets':
                continue

            # Move monitor specific stuff to a different structure
            if sec.lower().startswith('monitor-'):
                ts = sec.split('-')
                if len(ts) != 2:
                    g.logger.Error(
                        'Skipping section:{} - could not derive monitor name. Expecting monitor-NUM format'
                    )
                    continue

                mid = ts[1]
                g.logger.Debug(
                    2, 'Found monitor specific section for monitor: {}'.format(
                        mid))

                g.monitor_polygons[mid] = []
                g.monitor_config[mid] = {}
                g.monitor_zone_patterns[mid] = {}
                # Copy the sequence into each monitor because when we do variable subs
                # later, we will use this for monitor specific work
                try:
                    ml = config_file.get('ml', 'ml_sequence')
                    g.monitor_config[mid]['ml_sequence'] = ml
                except:
                    g.logger.Debug(2, 'ml sequence not found in globals')

                try:
                    ss = config_file.get('ml', 'stream_sequence')
                    g.monitor_config[mid]['stream_sequence'] = ss
                except:
                    g.logger.Debug(2, 'stream sequence not found in globals')

                for item in config_file[sec].items():
                    k = item[0]
                    v = item[1]
                    if k.endswith('_zone_detection_pattern'):
                        zone_name = k.split('_zone_detection_pattern')[0]
                        g.logger.Debug(
                            2, 'found zone specific pattern:{} storing'.format(
                                zone_name))
                        g.monitor_zone_patterns[mid][zone_name] = v
                        continue
                    else:
                        if k in g.config_vals:
                            # This means its a legit config key that needs to be overriden
                            g.logger.Debug(
                                2,
                                '[{}] overrides key:{} with value:{}'.format(
                                    sec, k, v))
                            g.monitor_config[mid][k] = _correct_type(
                                v, g.config_vals[k]['type'])
                        # g.monitor_config[mid].append({ 'key':k, 'value':_correct_type(v,g.config_vals[k]['type'])})
                        else:
                            if k.startswith(('object_', 'face_', 'alpr_')):
                                g.logger.Debug(
                                    2,
                                    'assuming {} is an ML sequence'.format(k))
                                g.monitor_config[mid][k] = v
                            else:
                                try:
                                    p = str2tuple(
                                        v
                                    )  # if not poly, exception will be thrown
                                    g.monitor_polygons[mid].append({
                                        'name':
                                        k,
                                        'value':
                                        p,
                                        'pattern':
                                        None
                                    })
                                    g.logger.Debug(
                                        2,
                                        'adding polygon: {} [{}]'.format(k, v))
                                except Exception as e:
                                    g.logger.Debug(
                                        2,
                                        '{} is not a polygon, adding it as unknown string key'
                                        .format(k))
                                    g.monitor_config[mid][k] = v

                            # TBD only_triggered_zones

            # Not monitor specific stuff
            else:
                for (k, v) in config_file.items(sec):
                    if k in g.config_vals:
                        _set_config_val(k, g.config_vals[k])
                    else:
                        g.config[k] = v

        # Parameter substitution

        g.logger.Debug(2, 'Doing parameter substitution for globals')
        p = r'{{(\w+?)}}'
        for gk, gv in g.config.items():
            #input ('Continue')
            gv = '{}'.format(gv)
            #if not isinstance(gv, str):
            #    continue
            while True:
                matches = re.findall(p, gv)
                replaced = False
                for match_key in matches:
                    if match_key in g.config:
                        replaced = True
                        new_val = g.config[gk].replace(
                            '{{' + match_key + '}}', str(g.config[match_key]))
                        g.config[gk] = new_val
                        gv = new_val
                    else:
                        g.logger.Debug(
                            2,
                            'substitution key: {} not found'.format(match_key))
                if not replaced:
                    break

        g.logger.Debug(
            2, 'Doing parameter substitution for monitor specific entities')
        p = r'{{(\w+?)}}'
        for mid in g.monitor_config:
            for key in g.monitor_config[mid]:
                #input ('Continue')
                gk = key
                gv = g.monitor_config[mid][key]
                gv = '{}'.format(gv)
                #if not isinstance(gv, str):
                #    continue
                while True:
                    matches = re.findall(p, gv)
                    replaced = False
                    for match_key in matches:
                        if match_key in g.monitor_config[mid]:
                            replaced = True
                            new_val = gv.replace(
                                '{{' + match_key + '}}',
                                str(g.monitor_config[mid][match_key]))
                            gv = new_val
                            g.monitor_config[mid][key] = gv
                        elif match_key in g.config:
                            replaced = True
                            new_val = gv.replace('{{' + match_key + '}}',
                                                 str(g.config[match_key]))
                            gv = new_val
                            g.monitor_config[mid][key] = gv
                        else:
                            g.logger.Debug(
                                2, 'substitution key: {} not found'.format(
                                    match_key))
                    if not replaced:
                        break

            secrets = pyzmutils.read_config(g.config['secrets'])
            #g.monitor_config[mid]['ml_sequence'] = pyzmutils.template_fill(input_str=g.monitor_config[mid]['ml_sequence'], config=None, secrets=secrets._sections.get('secrets'))
            #g.monitor_config[mid]['ml_sequence'] = ast.literal_eval(g.monitor_config[mid]['ml_sequence'])

            #g.monitor_config[mid]['stream_sequence'] = pyzmutils.template_fill(input_str=g.monitor_config[mid]['stream_sequence'], config=None, secrets=secrets._sections.get('secrets'))
            #g.monitor_config[mid]['stream_sequence'] = ast.literal_eval(g.monitor_config[mid]['stream_sequence'])

        #print ("GLOBALS={}".format(g.config))
        #print ("\n\nMID_SPECIFIC={}".format(g.monitor_config))
        #print ("\n\nMID POLYPATTERNS={}".format(g.monitor_polypatterns))
        #print ('FINAL POLYS={}'.format(g.monitor_polygons))
        #exit(0)
    except Exception as e:
        g.logger.Error('Error parsing config:{}'.format(args['config']))
        g.logger.Error('Error was:{}'.format(e))
        g.logger.Fatal('error: Traceback:{}'.format(traceback.format_exc()))
        exit(0)
Пример #6
0
    def post(self):
        args = parse_args()
        req = request.get_json()

        fi = None
        stream_options = {}
        stream = None
        ml_overrides = {}
        config_copy = None
        poly_copy = None
        ml_options = None
        mid = None

        if not req:
            req = {}
        if req.get('mid') and str(req.get('mid')) in g.monitor_config:
            mid = str(req.get('mid'))
            g.logger.Debug(
                1,
                'Monitor ID {} provided & matching config found in mlapi, ignoring objectconfig.ini'
                .format(mid))
            config_copy = copy.copy(g.config)
            poly_copy = copy.copy(g.polygons)
            g.polygons = copy.copy(g.monitor_polygons[mid])

            for key in g.monitor_config[mid]:
                # This will also take care of copying over mid specific stream_options
                g.logger.Debug(
                    2, 'Overriding global {} with {}...'.format(
                        key, g.monitor_config[mid][key][:30]))
                g.config[key] = g.monitor_config[mid][key]

            # stupid mlapi and zm_detect config incompatibility
            if not g.config.get('image_path') and g.config.get('images_path'):
                g.config['image_path'] = g.config['images_path']

            # At this stage, polygons has a copy of that monitor polygon set
            # g.config has overriden values of config from the mid

            r = req.get('reason')
            if r and g.config['only_triggered_zm_zones'] == 'yes' and g.config[
                    'import_zm_zones'] == 'yes':
                g.logger.Debug(
                    2, 'Only filtering polygon names that have {}'.format(r))
                g.logger.Debug(
                    2, 'Original polygons being used: {}'.format(g.polygons))

                g.polygons[:] = [
                    item for item in g.polygons
                    if utils.findWholeWord(item['name'])(r)
                ]
                g.logger.Debug(
                    2, 'Final polygons being used: {}'.format(g.polygons))

            if g.config['ml_sequence'] and g.config['use_sequence'] == 'yes':
                g.log.Debug(2, 'using ml_sequence')
                ml_options = g.config['ml_sequence']
                secrets = pyzmutils.read_config(g.config['secrets'])
                ml_options = pyzmutils.template_fill(
                    input_str=ml_options,
                    config=None,
                    secrets=secrets._sections.get('secrets'))
                ml_options = ast.literal_eval(ml_options)
                #print (ml_options)
            else:
                g.logger.Debug(2, 'mapping legacy ml data from config')
                ml_options = utils.convert_config_to_ml_sequence()

            g.logger.Debug(2, 'Overwriting ml_sequence of pre loaded model')
            m.set_ml_options(ml_options)
        else:
            g.logger.Debug(
                1,
                'Monitor ID not specified, or not found in mlapi config, using zm_detect overrides'
            )
            ml_overrides = req.get('ml_overrides', {})
            if g.config['ml_sequence'] and g.config['use_sequence'] == 'yes':
                g.log.Debug(2, 'using ml_sequence')
                ml_options = g.config['ml_sequence']
                secrets = pyzmutils.read_config(g.config['secrets'])
                ml_options = pyzmutils.template_fill(
                    input_str=ml_options,
                    config=None,
                    secrets=secrets._sections.get('secrets'))
                ml_options = ast.literal_eval(ml_options)
                #print (ml_options)
            else:
                g.logger.Debug(2, 'mapping legacy ml data from config')
                ml_options = utils.convert_config_to_ml_sequence()

            #print (ml_options)

        if g.config.get('stream_sequence'):
            g.logger.Debug(
                2,
                'Found stream_sequence in mlapi config, ignoring objectconfig.ini'
            )
            stream_options = ast.literal_eval(g.config.get('stream_sequence'))
        else:
            stream_options = req.get('stream_options')
        if not stream_options:
            if config_copy:
                g.log.Debug(2, 'Restoring global config & ml_options')
                g.config = config_copy
                g.polygons = poly_copy
            abort(400, msg='No stream options found')
        stream_options['api'] = zmapi
        stream_options['polygons'] = g.polygons

        stream = req.get('stream')

        if args['type'] == 'face':
            g.log.Debug(1, 'Face Recognition requested')

        elif args['type'] == 'alpr':
            g.log.Debug(1, 'ALPR requested')

        elif args['type'] in [None, 'object']:
            g.log.Debug(1, 'Object Recognition requested')
            #m = ObjectDetect.Object()
        else:
            if config_copy:
                g.log.Debug(2, 'Restoring global config & ml_options')
                g.config = config_copy
                g.polygons = poly_copy
            abort(400, msg='Invalid Model:{}'.format(args['type']))

        if not stream:
            g.log.Debug(1, 'Stream info not found, looking at args...')
            fip, ext = get_file(args)
            fi = fip + ext
            stream = fi

            #image = cv2.imread(fi)
        #bbox,label,conf = m.detect(image)

        stream_options['mid'] = mid
        if not stream_options.get('delay') and g.config.get('wait'):
            stream_options['delay'] = g.config.get('wait')
        g.log.Debug(1, 'Calling detect streams')
        matched_data, all_matches = m.detect_stream(stream=stream,
                                                    options=stream_options,
                                                    ml_overrides=ml_overrides)

        if matched_data['image_dimensions']:
            oldh = matched_data['image_dimensions']['original'][0]
            oldw = matched_data['image_dimensions']['original'][1]

        if config_copy:
            g.log.Debug(2, 'Restoring global config & ml_options')
            g.config = config_copy
            g.polygons = poly_copy

        matched_data['image'] = None
        if args.get('response_format') == 'zm_detect':
            resp_obj = {
                'matched_data': matched_data,
                'all_matches': all_matches,
            }
            g.log.Debug(1, 'Returning {}'.format(resp_obj))
            return resp_obj

        # legacy format
        bbox = matched_data['boxes']
        label = matched_data['labels']
        conf = matched_data['confidences']

        detections = []
        for l, c, b in zip(label, conf, bbox):
            c = "{:.2f}%".format(c * 100)
            obj = {'type': 'object', 'label': l, 'confidence': c, 'box': b}
            detections.append(obj)

        if args['delete'] and fi:
            #pass
            os.remove(fi)
        return detections