def assignment_load_handler(obj_response, form_values): """ Load camera assignment from file. """ camera_assignment_old = redis_tools.get_dict(db, 'camera_assignment') mjpeg_info_dict = redis_tools.get_dict(db, 'mjpeg_info_dict') select_values = create_select_values(mjpeg_info_dict) # Load current camera assignment from file yaml_dict = file_tools.read_camera_assignment() camera_assignment_new = assignment_from_yaml_dict(yaml_dict) camera_assignment = {} for camera_id in camera_assignment_old: try: value = camera_assignment_new[camera_id] except KeyError: value = '--' if not value in select_values: value = '--' camera_assignment[camera_id] = value redis_tools.set_dict(db, 'camera_assignment', camera_assignment) set_camera_assignment(obj_response, camera_assignment, select_values) obj_response.attr('#message', 'style', 'color:black') obj_response.html('#message', 'Current camera assignment loaded') obj_response.attr('#message_table', 'style', 'display:none')
def index(): if flask.g.sijax.is_sijax_request: flask.g.sijax.register_callback('calibrate_button', calibrate_button_handler) flask.g.sijax.register_callback('save_button', save_button_handler) flask.g.sijax.register_callback('reset_button_ok', reset_button_ok_handler) flask.g.sijax.register_callback('reset_button_cancel', reset_button_cancel_handler) flask.g.sijax.register_callback('timer_update', timer_update_handler) return flask.g.sijax.process_request() else: # Get scale and compute image width scale, scale_options = common_args.get_scale(config,flask.request) redis_tools.set_str(db,'scale', scale) image_width, image_height = get_image_size(scale) ip_iface_ext = redis_tools.get_str(db,'ip_iface_ext') mjpeg_info = redis_tools.get_dict(db,'mjpeg_info_dict') camera_pairs = redis_tools.get_dict(db,'camera_pairs_dict') camera_pairs_mjpeg_info = get_camera_pairs_mjpeg_info(camera_pairs, mjpeg_info) calibration_info = get_calibration_info() render_dict = { 'scale': scale, 'scale_options': scale_options, 'image_width': image_width, 'image_height': image_height, 'ip_iface_ext': ip_iface_ext, 'camera_pairs': camera_pairs, 'camera_pairs_mjpeg_info': camera_pairs_mjpeg_info, 'calibration_info': calibration_info, } return flask.render_template('transform_2d_calibration.html',**render_dict)
def timer_update_handler(obj_response): """ Updates the camera assignment form to the latest values in the database. This function is from a timer on the client and is used to keep multiple instances of the interface in sync. """ camera_assignment = redis_tools.get_dict(db, 'camera_assignment') mjpeg_info_dict = redis_tools.get_dict(db, 'mjpeg_info_dict') select_values = create_select_values(mjpeg_info_dict) set_camera_assignment(obj_response, camera_assignment, select_values)
def get_extra_video_mjpeg_info(video): """ Returns a dictionary containing the mjpeg stream information for the extra video named video """ mjpeg_info_dict = redis_tools.get_dict(db, 'mjpeg_info_dict') extra_video_dict = redis_tools.get_dict(db, 'extra_video_dict') extra_video_topic = extra_video_dict[video] extra_video_mjpeg_info = {} for v in mjpeg_info_dict.values(): if extra_video_topic == v['image_topic']: extra_video_mjpeg_info['image_topic'] = v['image_topic'] extra_video_mjpeg_info['mjpeg_port'] = v['mjpeg_port'] break return extra_video_mjpeg_info
def save_button_handler(obj_response): # Collect calibration data for camera pairs pairs_dict = redis_tools.get_dict(db,'camera_pairs_dict') calibration_dict = {} calibration_list = [] for pairs_list in pairs_dict.values(): for camera0, camera1 in pairs_list: calibrator_name = get_calibrator_name(camera0,camera1) if transform_2d_calibrator.is_calibrated(calibrator_name): rot, tx, ty = transform_2d_calibrator.get_transform_2d(calibrator_name) calibration_dict[(camera0,camera1)] = { 'rotation': rot, 'translation_x': tx, 'translation_y': ty, } calibration_list.append((camera0,camera1)) file_tools.write_transform_2d_calibration(calibration_dict) table_data = [] for camera0, camera1 in calibration_list: table_data.append('<tr> <td>') table_data.append('{0}, {1}'.format(camera0,camera1)) table_data.append('</td> </tr>') table_data = '\n'.join(table_data) if calibration_dict: obj_response.html('#message', 'Saved calibrations for camera pairs:') obj_response.html('#message_table', table_data) obj_response.attr('#message_table', 'style', 'display:block') else: obj_response.html('#message', 'No data to save') obj_response.attr('#message_table', 'style', 'display:none')
def get_tab_list(): """ Generates list of tabs and their urls. """ regions_dict = redis_tools.get_dict(db, 'regions_dict') extra_video_dict = redis_tools.get_dict(db, 'extra_video_dict') tab_list = [] tab_list.append(('control', flask.url_for('show_control'))) for region in regions_dict: tab_list.append((region, flask.url_for('show_region', region=region))) for name in extra_video_dict: tab_list.append((name, flask.url_for('show_extra_video', video=name))) tab_list.sort() tab_list.append(('lighting', flask.url_for('lighting'))) tab_list.append(('ros', flask.url_for('show_ros_info'))) return tab_list
def reset_button_cancel_handler(obj_response): """ Callback for when the user clicks the cancel button and answers in the negative. """ target_info = redis_tools.get_dict(db, 'target_info') obj_response.html('#message', 'Reset canceled') obj_response.attr('#message_table', 'style', 'display:none')
def index(): # Get scale and compute image width scale, scale_options = common_args.get_scale(config,flask.request) redis_tools.set_str(db,'scale', scale) image_width, image_height = get_image_size(scale) ip_iface_ext = redis_tools.get_str(db,'ip_iface_ext') mjpeg_info_dict = redis_tools.get_dict(db,'mjpeg_info_dict') mjpeg_info = sorted(mjpeg_info_dict.items(), cmp=mjpeg_info_cmp) # Build dict of urls for single camera views single_view_url = {} for camera in mjpeg_info_dict: single_view_url[camera] = flask.url_for('single_camera_view.page',camera=camera) render_dict = { 'scale' : scale, 'scale_options' : scale_options, 'image_width' : image_width, 'image_height' : image_height, 'ip_iface_ext' : ip_iface_ext, 'mjpeg_info' : mjpeg_info, 'single_view_url' : single_view_url, } return flask.render_template('zoom_calibration.html',**render_dict)
def get_camera_calibration_info(): mjpeg_info_dict = redis_tools.get_dict(db,'mjpeg_info_dict') calibration_info = mct_introspection.get_camera_calibration_info() for camera in mjpeg_info_dict: if not camera in calibration_info: calibration_info[camera] = {'modified': ''} return calibration_info
def get_calibration_info(): """ Gets the last modified date for any existing homography calibration files. """ mjpeg_info_dict = redis_tools.get_dict(db, 'mjpeg_info_dict') calibration_info = mct_introspection.get_homography_calibration_info() for camera in mjpeg_info_dict: if not camera in calibration_info: calibration_info[camera] = {'modified': ''} return calibration_info
def index(): if flask.g.sijax.is_sijax_request: flask.g.sijax.register_callback('calibrate_button_onclick', calibrate_button_handler) flask.g.sijax.register_callback('save_button_onclick', save_button_handler) flask.g.sijax.register_callback('reset_button_ok', reset_button_ok_handler) flask.g.sijax.register_callback('reset_button_cancel', reset_button_cancel_handler) flask.g.sijax.register_callback('timer_update', timer_update_handler) return flask.g.sijax.process_request() else: # Get scale and compute image width scale, scale_options = common_args.get_scale(config,flask.request) redis_tools.set_str(db,'scale', scale) image_width, image_height = get_image_size(scale) ip_iface_ext = redis_tools.get_str(db,'ip_iface_ext') mjpeg_info_dict = redis_tools.get_dict(db,'mjpeg_info_dict') mjpeg_info = sorted(mjpeg_info_dict.items(), cmp=mjpeg_info_cmp) target_info = redis_tools.get_dict(db,'target_info') # Get list of current camera calibration files calibration_info = get_camera_calibration_info() # Build dict of urls for single camera views single_view_url = {} for camera in mjpeg_info_dict: single_view_url[camera] = flask.url_for('single_camera_view.page',camera=camera) render_dict = { 'scale' : scale, 'scale_options' : scale_options, 'image_width' : image_width, 'image_height' : image_height, 'ip_iface_ext' : ip_iface_ext, 'mjpeg_info' : mjpeg_info, 'target_info' : target_info, 'calibration_info' : calibration_info, 'single_view_url' : single_view_url, } return flask.render_template('camera_calibration.html',**render_dict)
def get_camera_calibration_info(): """ Gets the last modified date for any existing homography calibration files. """ regions_dict = redis_tools.get_dict(db, 'regions_dict') calibration_info = mct_introspection.get_camera_calibration_info() for region, camera_list in regions_dict.iteritems(): for camera in camera_list: if not camera in calibration_info: calibration_info[camera] = {'modified': ''} return calibration_info
def show_control(): """ Tracking program main control page. Enables users to start/stop recording and displays information about the running system. """ if flask.g.sijax.is_sijax_request: flask.g.sijax.register_callback('mode_change_request', mode_change_handler) flask.g.sijax.register_callback('timer_update', timer_update_handler) return flask.g.sijax.process_request() else: current_mode = redis_tools.get_str(db, 'current_mode') watchdog_mjpeg_info = get_watchdog_mjpeg_info() regions_dict = redis_tools.get_dict(db, 'regions_dict') extra_video_dict = redis_tools.get_dict(db, 'extra_video_dict') homography_cal_info = get_homography_calibration_info() transform_2d_cal_info = get_transform_2d_calibration_info() camera_cal_info = get_camera_calibration_info() logging_params_dict = redis_tools.get_dict(db, 'logging_params_dict') camera_assignment = get_camera_assignment() all_cameras_sorted = camera_assignment.keys() all_cameras_sorted.sort(cmp=camera_name_cmp) camera_pairs_dict = get_camera_pairs_dict() render_dict = get_base_render_dict() page_render_dict = { 'operating_modes': OPERATING_MODES, 'current_mode': current_mode, 'watchdog_mjpeg_info': watchdog_mjpeg_info, 'regions_dict': regions_dict, 'extra_video_dict': extra_video_dict, 'logging_params_dict': logging_params_dict, 'homography_cal_info': homography_cal_info, 'transform_2d_cal_info': transform_2d_cal_info, 'camera_cal_info': camera_cal_info, 'camera_assignment': camera_assignment, 'all_cameras_sorted': all_cameras_sorted, 'camera_pairs_dict': camera_pairs_dict, } render_dict.update(page_render_dict) return flask.render_template('tracking_2d_control.html', **render_dict)
def reset_button_ok_handler(obj_response): """ Callback for when the user clicks the reset button and answers in the affirmative. Requests that the calbirator_master node stop and re-start the individual camera calibrator nodes. """ calibrator_master.stop() target_info = redis_tools.get_dict(db, 'target_info') obj_response.html('#develop', str(type(target_info['square']))) calibrator_master.start(target_info['size'], target_info['square']) obj_response.html('#message', 'Resetting camera calibrators') obj_response.attr('#message_table', 'style', 'display:none')
def get_watchdog_mjpeg_info(): """ Returns a dictionary containing the mjpeg stream information for the watchdog information image stream. """ mjpeg_info_dict = redis_tools.get_dict(db, 'mjpeg_info_dict') watchdog_mjpeg_info = {} for v in mjpeg_info_dict.values(): if v['image_topic'] == '/image_frame_drop_watchdog': watchdog_mjpeg_info['image_topic'] = v['image_topic'] watchdog_mjpeg_info['mjpeg_port'] = v['mjpeg_port'] break return watchdog_mjpeg_info
def index(): if flask.g.sijax.is_sijax_request: flask.g.sijax.register_callback('assignment_change', assignment_change_handler) flask.g.sijax.register_callback('clear_form', clear_form_handler) flask.g.sijax.register_callback('assignment_save', assignment_save_handler) flask.g.sijax.register_callback('assignment_load', assignment_load_handler) flask.g.sijax.register_callback('timer_update', timer_update_handler) flask.g.sijax.register_callback('test', test_handler) return flask.g.sijax.process_request() else: # Get scale and compute image width scale, scale_options = common_args.get_scale(config, flask.request) image_width = int(config.camera_image['width'] * float(scale)) image_height = int(config.camera_image['height'] * float(scale)) camera_assignment = redis_tools.get_dict(db, 'camera_assignment') mjpeg_info_dict = redis_tools.get_dict(db, 'mjpeg_info_dict') ip_iface_ext = redis_tools.get_str(db, 'ip_iface_ext') select_values = create_select_values(mjpeg_info_dict) render_dict = { 'mjpeg_info_dict': mjpeg_info_dict, 'camera_assignment': camera_assignment, 'select_values': select_values, 'ip_iface_ext': ip_iface_ext, 'scale_options': scale_options, 'scale': scale, 'image_width': image_width, 'image_height': image_height, } redis_tools.set_dict(db, 'camera_assignment', camera_assignment) return flask.render_template('camera_assignment.html', **render_dict)
def show_extra_video(video): """ Handles requests to view the requested extra video streams. """ ip_iface_ext = redis_tools.get_str(db, 'ip_iface_ext') tab_list = get_tab_list() extra_video_mjpeg_info = get_extra_video_mjpeg_info(video) mjpeg_info_dict = redis_tools.get_dict(db, 'mjpeg_info_dict') render_dict = get_base_render_dict() page_render_dict = { 'extra_video_name': video, 'extra_video_mjpeg_info': extra_video_mjpeg_info, } render_dict.update(page_render_dict) return flask.render_template('tracking_2d_extra_video.html', **render_dict)
def get_empty_lighting_values(): """ Gets the lighting values from the controller """ lighting_values = [] lighting_params_dict = redis_tools.get_dict(db, 'lighting_params_dict') lighting_names_sorted = sorted(lighting_params_dict.keys()) for name in lighting_names_sorted: channel_values = [] for channel in lighting_params_dict[name]: channel_num = int(channel.split('_')[1]) values_dict = {'enable': False, 'imax': '', 'iset': ''} channel_values.append((channel, values_dict)) lighting_values.append((name, channel_values)) return lighting_values
def get_region_mjpeg_info(region): """ Returns a dictionary containing the mjpeg stream information for all of the images for the specified tracking region. """ mjpeg_info_dict = redis_tools.get_dict(db, 'mjpeg_info_dict') region_mjpeg_info = {} for v in mjpeg_info_dict.values(): image_topic_split = v['image_topic'].split('/') if region == image_topic_split[1]: image_name = image_topic_split[2] region_mjpeg_info[image_name] = { 'image_topic': v['image_topic'], 'mjpeg_port': v['mjpeg_port'], } return region_mjpeg_info
def get_calibration_info(): """ Gets the last modified date for any existing homography calibration files. """ camera_pairs_dict = redis_tools.get_dict(db,'camera_pairs_dict') calibration_info = mct_introspection.get_transform_2d_calibration_info() calibration_info_mod = {} for pairs_list in camera_pairs_dict.values(): for camera0, camera1 in pairs_list: pair_str = '{0}_{1}'.format(camera0,camera1) if not pair_str in calibration_info: calibration_info_mod[(camera0,camera1)] = {'modified': ''} else: calibration_info_mod[(camera0,camera1)] = calibration_info[pair_str] return calibration_info_mod
def assignment_change_handler(obj_response, form_values): """ Handles changes to the camera assignment """ camera_assignment_old = redis_tools.get_dict(db, 'camera_assignment') camera_assignment_new = json_tools.decode_dict(form_values) redis_tools.set_dict(db, 'camera_assignment', camera_assignment_new) message_str = '' for k, v in camera_assignment_new.iteritems(): if v != camera_assignment_old[k]: message_str = 'Assigned camera {0} to GUID {1}'.format(v, k) obj_response.attr('#message', 'style', 'color:black') obj_response.html('#message', message_str) obj_response.attr('#message_table', 'style', 'display:none')
def clear_form_handler(obj_response, form_values): """ Handles requests to clear form """ camera_assignment = json_tools.decode_dict(form_values) camera_assignment = dict((k, '--') for k in camera_assignment) redis_tools.set_dict(db, 'camera_assignment', camera_assignment) # Update form mjpeg_info_dict = redis_tools.get_dict(db, 'mjpeg_info_dict') select_values = create_select_values(mjpeg_info_dict) set_camera_assignment(obj_response, camera_assignment, select_values) # Update message obj_response.attr('#message', 'style', 'color:black') obj_response.html('#message', 'Camera assignment cleared') obj_response.attr('#message_table', 'style', 'display:none')
def test_handler(obj_response, form_values): """ Assign a test camera assignment - for development """ # Create a camera assignment camera_assignment = json_tools.decode_dict(form_values) cnt = 0 test_camera_assignment = {} for k in camera_assignment: cnt += 1 test_camera_assignment[k] = str(cnt) # Set camera assignment values mjpeg_info_dict = redis_tools.get_dict(db, 'mjpeg_info_dict') select_values = create_select_values(mjpeg_info_dict) set_camera_assignment(obj_response, test_camera_assignment, select_values) redis_tools.set_dict(db, 'camera_assignment', test_camera_assignment) obj_response.attr('#message', 'style', 'color:black') obj_response.html('#message', 'Created test assignment') obj_response.attr('#message_table', 'style', 'display:none')
def save_button_handler(obj_response): """ Handler for requests to run save the homography matrices """ mjpeg_info_dict = redis_tools.get_dict(db, 'mjpeg_info_dict') # Get dictionary of calibration data calibration_dict = {} for camera, info in mjpeg_info_dict.iteritems(): topic = info['image_topic'] calibrator_node = get_calibrator_from_topic(topic) if homography_calibrator.is_calibrated(calibrator_node): num_row, num_col, data = homography_calibrator.get_matrix( calibrator_node) calibration = { 'rows': num_row, 'cols': num_col, 'data': list(data), } calibration_dict[camera] = calibration # Save calibration data file_tools.write_homography_calibration(calibration_dict) table_data = [] camera_list = calibration_dict.keys() camera_list.sort(cmp=camera_name_cmp) for camera_name in camera_list: table_data.append('<tr> <td>') table_data.append(camera_name) table_data.append('</td> </tr>') table_data = '\n'.join(table_data) if calibration_dict: obj_response.html('#message', 'Saved calibrations for cameras:') obj_response.html('#message_table', table_data) obj_response.attr('#message_table', 'style', 'display:block') else: obj_response.html('#message', 'No data to save') obj_response.attr('#message_table', 'style', 'display:none')
def mode_change_handler(obj_response, new_mode): old_mode = redis_tools.get_str(db, 'current_mode') new_mode = str(new_mode) if old_mode == new_mode: return redis_tools.set_str(db, 'current_mode', new_mode) frame_rate = redis_tools.get_dict(db, 'frame_rate_dict')['tracking_2d'] regions_dict = redis_tools.get_dict(db, 'regions_dict') # Stop camera triggers camera_trigger.stop() time.sleep(0.5) # wait for all frames to pass throught the system reset_rand_sync() if old_mode == 'recording' or new_mode == 'recording': # Find logging and avi recording commands service_list = mct_introspection.get_services() logging_nodes = get_logging_nodes(service_list) recording_nodes = get_recording_nodes(service_list) if (old_mode == 'recording') and (new_mode != 'recording'): # Stop logging and recording for node in logging_nodes: tracking_pts_logger.stop_logging(node) for node in recording_nodes: avi_writer.stop_recording(node, 'dummy.avi', frame_rate) if new_mode == 'recording': # Create sub-directory for log files. log_dir_base = redis_tools.get_dict( db, 'logging_params_dict')['directory'] log_dir = os.path.join(log_dir_base, datetime.datetime.now().isoformat()) os.mkdir(log_dir) # Start loggers for node in logging_nodes: filename = '_'.join(node.split('/')[1:3]) filename = os.path.join(log_dir, '{0}.json'.format(filename)) tracking_pts_logger.start_logging(node, filename) # Start avi recordings for node in recording_nodes: filename = '_'.join(node.split('/')[1:3]) filename = os.path.join(log_dir, '{0}.avi'.format(filename)) avi_writer.start_recording(node, filename, frame_rate) if new_mode in ('preview', 'recording'): regions_dict = redis_tools.get_dict(db, 'regions_dict') # Reset frame drop correctors and restart camera triggers frame_drop_corrector.reset_all() frame_drop_watchdog.reset() # Reset image_stitcher and three_point_tracker synchronizer for all tracking regions for region in regions_dict: image_stitcher.reset(region) three_point_tracker_synchronizer.reset(region) camera_trigger.start(frame_rate)
def assignment_save_handler(obj_response, form_values): """ Handles requests to save the current camera assignment. The assignment is checked for unassigned guids and for duplicate assignments. """ camera_assignment = json_tools.decode_dict(form_values) # Check for unassigned GUIDs unassigned = [] for k, v in camera_assignment.iteritems(): if v == '--': unassigned.append(k) # Check for duplicate values assignment_cnt = {} for k, v in camera_assignment.iteritems(): try: assignment_cnt[v] += 1 except KeyError: assignment_cnt[v] = 1 duplicates = {} for k, v in camera_assignment.iteritems(): try: cnt = assignment_cnt[v] except KeyError: continue if cnt > 1 and v != '--': try: duplicates[v].append(k) except KeyError: duplicates[v] = [k] # Send response if unassigned: # Unable to save - there are unassigned cameras table_data = [] for k in unassigned: table_data.append('<tr>') table_data.append('<td> <b> GUID {0} </b> </td>'.format(k)) table_data.append('</tr>') table_data = '\n'.join(table_data) message = 'Unable to save: unassigned GUIDs' obj_response.attr('#message', 'style', 'color:red') obj_response.html('#message', message) obj_response.html('#message_table', table_data) obj_response.attr('#message_table', 'style', 'display:block') elif duplicates: # Unable to save - there exist duplicate camera assignemts table_data = [] for k, v in duplicates.iteritems(): table_data.append('<tr>') table_data.append('<td> <b> camera {0} </b> </td>'.format(k)) table_data.append('<td> → </td>') table_data.append('<td> <b> {0} </b> </td>'.format(str(v))) table_data.append('</tr>') table_data = '\n'.join(table_data) message = 'Unable to save: duplicate assignments exist' obj_response.attr('#message', 'style', 'color:red') obj_response.html('#message', message) obj_response.html('#message_table', table_data) obj_response.attr('#message_table', 'style', 'display:block') else: # Everthing is OK save camera assignment table_data = [] for k, v in camera_assignment.iteritems(): table_data.append('<tr>') table_data.append('<td> <b> camera {0} </b> </td>'.format(v)) table_data.append('<td> → </td>') table_data.append('<td> <b> GUID {0} </b> </td>'.format(k)) table_data.append('</tr>') table_data = '\n'.join(table_data) # Create camera assignment yaml dictionary and write to file mjpeg_info_dict = redis_tools.get_dict(db, 'mjpeg_info_dict') yaml_dict = create_yaml_dict(camera_assignment, mjpeg_info_dict) file_tools.write_camera_assignment(yaml_dict) message = 'Camera assignment saved' obj_response.attr('#message', 'style', 'color:green') obj_response.html('#message', message) obj_response.html('#message_table', table_data) obj_response.attr('#message_table', 'style', 'display:block')