Spaces:
Runtime error
Runtime error
| import cv2 | |
| import base64 | |
| import gradio as gr | |
| import json | |
| import numpy as np | |
| VIDEO_HEIGHT = 700 | |
| # annotation_btn.clock - switches to annotation tab and starts load_annotation | |
| def prepare_annotation(state, result, result_index): | |
| state['annotation_index'] = result_index | |
| state['frame_index'] = 0 | |
| # output for [annotation_progress, master_tabs] | |
| if result["aris_input"][result_index]: | |
| return [ | |
| gr.update(value="<p id='annotation_info' style='display:none'>[]</p><!--" + str(np.random.rand()) + "-->", visible=True), | |
| gr.update(selected=2) | |
| ] | |
| return [gr.update(), gr.update()] | |
| # annotation_progress.change - loads annotation frames in batches - called after prepare_annotation | |
| def load_annotation(state, result, progress_bar): | |
| # Get result index | |
| result_index = state['annotation_index'] | |
| set_progress = lambda pct, msg: progress_bar(pct, desc=msg) | |
| if state['frame_index'] == 0: | |
| if set_progress: set_progress(0, "Loading Frames") | |
| # Check that frames remain to be loaded | |
| if state['frame_index'] < len(result['json_result'][result_index]['frames']): | |
| # load frames and annotation | |
| annotation_info, state['frame_index'] = init_frames(result["aris_input"][result_index], result['json_result'][result_index], state['frame_index'], gp=set_progress) | |
| # save as html element | |
| annotation_content = "<p id='annotation_info' style='display:none'>" + json.dumps(annotation_info) + "</p>" | |
| # output for [annotation_editor, annotation_progress] | |
| return [gr.update(), gr.update(value=annotation_content)] | |
| # If complete, start annotation editor | |
| annotation_html = "" | |
| # Header | |
| annotation_html += "<div id='annotation_header'>" | |
| annotation_html += " <h1 id='annotation_frame_nbr'>Frame 0/100</h1>" | |
| annotation_html += " <p id='annotation_edited'>(edited)</p>" | |
| annotation_html += "</div>" | |
| # Annotation Body | |
| annotation_html += "<div style='display:flex'>" | |
| annotation_html += " <canvas id='canvas' style='width:50%' onmousedown='mouse_down(event)' onmousemove='mouse_move(event)' onmouseup='mouse_up()' onmouseleave='mouse_up()'></canvas>" | |
| annotation_html += " <div id='annotation_display' style='width:50%'></div>" | |
| annotation_html += "</div>" | |
| # Dummy objects | |
| annotation_html += "<img id='annotation_img' onload='draw()' style='display:none'></img>" | |
| annotation_html += "<!--" + str(np.random.rand()) + "-->" | |
| # output for [annotation_editor, annotation_progress] | |
| return [gr.update(value=annotation_html, visible=True), gr.update(visible=False)] | |
| # called by load_annotation - read frames from dataloader and formats tracks | |
| def init_frames(dataset, preds, index, gp=None): | |
| """Load frames for annotation editing | |
| Returns: | |
| list({ | |
| frame: frame image as base64 string, | |
| annotations: list( | |
| bbox: dict of int defining bounding box {left, right, top, bottom}, | |
| id: id of fish as int, | |
| conf: confidence in bbox as float | |
| ) | |
| }) | |
| """ | |
| images = dataset.didson.load_frames(start_frame=0, end_frame=1) | |
| # assumes all frames the same size | |
| h, w = images[0].shape | |
| # enforce a standard size so that text/box thickness is consistent | |
| scale_factor = VIDEO_HEIGHT / h | |
| h = VIDEO_HEIGHT | |
| w = int(scale_factor*w) | |
| annotations = [] | |
| if gp: gp(0, "Extracting Frames") | |
| if len(preds['frames']): | |
| end_index = min(index+1000, len(preds['frames'])) | |
| for i, frame_info in enumerate(preds['frames'][index:end_index]): | |
| if gp: gp((index + i)/len(preds['frames']), "Extracting Frames") | |
| # Extract frames | |
| img_raw = dataset.didson.load_frames(start_frame=index+i, end_frame=index+i+1)[0] | |
| image = cv2.resize(cv2.cvtColor(img_raw, cv2.COLOR_GRAY2BGR), (w, h)) | |
| retval, buffer = cv2.imencode('.jpg', image) | |
| b64 = base64.b64encode(buffer).decode("utf-8") | |
| # Extract annotations | |
| frame = { | |
| 'annotations': [], | |
| 'base64': b64 | |
| } | |
| for fish in frame_info['fish']: | |
| xmin, ymin, xmax, ymax = fish['bbox'] | |
| frame['annotations'].append({ | |
| 'bbox': { | |
| 'left': int(round(xmin * w)), | |
| 'right': int(round(xmax * w)), | |
| 'top': int(round(ymin * h)), | |
| 'bottom': int(round(ymax * h)), | |
| }, | |
| 'id': str(fish['fish_id']), | |
| 'conf': fish['conf'] | |
| }) | |
| annotations.append(frame) | |
| return annotations, end_index | |
| # javascript code that retrieves the data from load_annotation and saves it to the javascript window | |
| js_store_frame_info = """ | |
| () => { | |
| info_string = document.getElementById("annotation_info").innerHTML; | |
| info = JSON.parse(info_string); | |
| console.log(info) | |
| if (info.length == 0) { | |
| window.annotation_info = []; | |
| return false; | |
| } | |
| window.annotation_info = window.annotation_info.concat(info) | |
| console.log(window.annotation_info) | |
| return true; | |
| } | |
| """ | |
| annotation_css = """ | |
| #annotation_frame_nbr { | |
| left: calc(50% - 100px); | |
| position: absolute; | |
| width: 200px; | |
| text-align: center; | |
| font-size: x-large; | |
| } | |
| #annotation_header { | |
| height: 40px; | |
| } | |
| #annotation_frame_nbr { | |
| left: calc(50% - 100px); | |
| position: absolute; | |
| width: 200px; | |
| text-align: center; | |
| font-size: x-large; | |
| } | |
| #annotation_edited { | |
| right: 0px; | |
| position: absolute; | |
| margin-top: 5px; | |
| } | |
| """ |