Example #1
0
def form_post():
    """ Process a form submission (login, edit, etc)."""
    # The input is stored in Flask's request global.
    # Each submitted form has an input field named 'submit_X' for some X,
    # and is handled by a corresponding function submit_X()
    # if it passes its authorize_* permissions check.

    keys_named_submit = filter(lambda s: re.match('submit', s),
                               request.form.keys())
    print_debug(' handle_post : submit keys = "{}" '.format(keys_named_submit))
    submit_what = keys_named_submit[0]
    print_debug(' handle_post : submit_what = "{}" '.format(submit_what))

    if submit_what not in form_handlers:
        print_debug(' handle_post: OOPS - illegal submit_what ')
        flash('* incorrect form submission *', 'formerror')
        return request.base_url
    elif form_handlers[submit_what]['authorize']():
        result = form_handlers[submit_what]['handler']()
        print_debug(' handle_post : submit result = "{}" '.format(result))
        return result
    else:
        print_debug(' handle_post: form submission authorization failed ')
        flash('* authorization error *', 'formerror')
        return request.base_url
Example #2
0
async def main():
    if BILI_UID == '你的 Bilibili UID':
        print_status('** 未指定 Bilibili UID!')
        exit(1)
    if (APP_ID == '你的 Bangumi App ID'
            and APP_SECRET == '你的 Bangumi App Secret'):
        print_status('** 未指定 Bangumi 授权设置!')
        exit(1)

    print_debug('创建构造编号映射任务 -> [get_bili2bgm_map]')
    get_bili2bgm_map_task = loop.create_task(get_bili2bgm_map())

    print_debug('创建取得 Bilibili 授权任务 -> [auth_bili]')
    auth_bili_task = loop.create_task(auth_bili(SESSDATA, BILI_JCT, BUVID3))

    print_debug('创建取得 Bangumi 授权任务 -> [auth_bgm]')
    auth_bgm_task = loop.create_task(auth_bgm(APP_ID, APP_SECRET))

    print_debug('等待任务...')
    bili2bgm_map = await get_bili2bgm_map_task
    bili_auth_data = await auth_bili_task
    bgm_auth_data = await auth_bgm_task

    print_status('正在迁移...')
    print_debug('等待更新数据任务 -> [get_and_update]')
    await get_and_update(bili2bgm_map, bili_auth_data, BILI_UID, bgm_auth_data)
Example #3
0
def submit_removeuser():
    """ The user clicked "remove" on the sys/users page """
    print_debug(' submit_removeuser: '******'choose_remove']
    if username:
        message = request.page.course.drop(username)
        if message:
            flash(message, 'drop')
    return request.page.url
Example #4
0
def submit_permissions():
    """ handle setting folder permissions - .access.yaml stuff """
    rights = {
        'read': parse_access_string(request.form['read_access']),
        'write': parse_access_string(request.form['write_access'])
    }
    access_abspath = request.page.write_access_file(rights)
    print_debug(' submit_permissions : access path {} '.format(access_abspath))
    git.add_and_commit(request.page, access_abspath)
    return url_for('mainroute', pagepath=request.page.path, action='edit')
Example #5
0
def submit_enroll():
    """ Enroll someone in this course. """
    username = request.form['username']
    rolename = request.form['submit_enroll']
    print_debug(' submit_enroll: user={}, role={}'.format(username, rolename))
    user = Person.by_username(username)
    request.page.course.enroll(user,
                               rolename,
                               create_work=(rolename == 'student'))
    return request.page.url
Example #6
0
async def auth_bgm(app_id, app_secret):
    '''取得 Bangumi 授权'''
    code = None

    async def handler(request):
        '''Bangumi 授权请求处理器'''
        nonlocal code
        code = request.query['code']
        return web.Response(
            content_type='text/html',
            text='<!DOCTYPE html><html><body><h1 align="center">'
            'Bangumi 授权请求已接受,请关闭此页面。'
            '</h1></body></html>')

    print_debug('创建 Bangumi 授权请求处理器...')
    app = web.Application()
    app.add_routes([web.get('/', handler)])
    runner = web.AppRunner(app)
    await runner.setup()
    site = web.TCPSite(runner, 'localhost', 3000)
    await site.start()

    print_debug('打开 Bangumi 授权页面...')
    link = (
        f'https://bgm.tv/oauth/authorize?client_id={app_id}&response_type=code'
    )
    webbrowser_open(link)

    print_status('请在弹出的授权页面中点击授权。')
    print_status('若授权页面没有自动弹出,请手动复制链接至浏览器中打开:')
    print_status(f'{link}')

    print_debug('等待 Bangumi 授权请求...')
    while code is None:
        await sleep(0.001)
    await site.stop()
    await runner.shutdown()

    print_status('正在尝试取得授权...')

    print_debug('请求 Bangumi 授权码...')
    bgm_auth_data_raw = await try_for_times_async_json(  # 尝试五次
        5, lambda: client.post('https://bgm.tv/oauth/access_token',
                               data={
                                   'grant_type': 'authorization_code',
                                   'client_id': app_id,
                                   'client_secret': app_secret,
                                   'code': code,
                                   'redirect_uri': 'http://localhost:3000'
                               }))
    token = (f'{bgm_auth_data_raw["token_type"]}'
             f' {bgm_auth_data_raw["access_token"]}')
    print_debug('完成!')
    return token
Example #7
0
def submit_delete():
    """ handle folder delete form """
    # example request.form would be {'submit_delete':'delete',
    #                                '/full/path/file1.md':'checkboxdelete',
    #                                '/full/path/folder2/':'checkboxdelete'}
    abspaths = list(
        filter(lambda path: request.form[path] == 'checkboxdelete',
               request.form.keys()))
    print_debug(' submit_delete : {}'.format(abspaths))
    git.rm_and_commit(request.page, abspaths)
    return url_for('mainroute', pagepath=request.page.path, action='edit')
Example #8
0
def submit_edituser():
    """ edit existing user - admin only """
    username = request.form['username']
    name = request.form['name']
    email = request.form['email']
    password = request.form['password']
    print_debug(' submit_edituser: '******'username={} name="{}" email={} password=""'.format(
                username, name, email, password))
    Person.edit_person(username, name, email, password)
    return request.base_url + '?username=' + username
Example #9
0
def submit_newuser():
    """ create new user """
    username = request.form['username']
    name = request.form['name']
    email = request.form['email']
    password = request.form['password']
    print_debug(' create_person: ' + \
                'username={} name="{}" email={} password=""'.format(
                username, name, email, password))
    Person.create_person(username, name, email, password)
    return url_base + '/sys/user?username=' + username
Example #10
0
def next_level():
    # advance to the next level
    message('You go down a floor.', tcod.light_violet)
    settings.save_level_state()
    settings.dungeon_level += 1
    try:
        settings.load_level_state()
    except:
        print_debug("map not found. making new map")
        make_map()
        settings.save_level_state()
    initialize_fov()
Example #11
0
def submit_password():
    password = request.form['password']
    if not safe.check(password):
        flash('Oops: that password is too easily guessed. ' + \
              'Try again with a longer one using a mix of numbers, ' + \
              'symbols, upper and lower case.', 'user')
        print_debug(
            ' submit_password: failed safe.check("{}")'.format(password))
        return request.base_url + '?action=edit'
    else:
        request.page.user.set_password(password)
        print_debug(' submit_password: password reset')
        return request.base_url
Example #12
0
async def get_one_bili_data(data: SimpleNamespace, page: int):
    '''获取单个 Bilibili 追番数据'''
    print_debug(f'获取追番数据 @ {page} ...')
    bangumi_data = await try_for_times_async_chain(  # 尝试三次
        3,
        lambda: data.user.get_subscribed_bangumis(page, BangumiType.BANGUMI))
    data.bangumi_total += len(bangumi_data['list'])
    data.bangumi_remaining.extend(
        map(lambda bangumi: (bangumi['media_id'], bangumi['follow_status']),
            bangumi_data['list']))
    data.bili_processed_count += 1
    if page == 1:
        return ceil(bangumi_data['total'] / 15)  # 计算并返回总页数
Example #13
0
async def auth_bili(sessdata, bili_jct, buvid3):
    '''取得 Bilibili 授权'''
    if (sessdata != '你的 Bilibili SESSDATA'
            and bili_jct != '你的 Bilibili bili_jct'
            and buvid3 != '你的 Bilibili buvid3'):
        credential = Credential(sessdata=sessdata,
                                bili_jct=bili_jct,
                                buvid3=buvid3)
    else:
        print_debug('未指定 Bilibili 授权设置!')
        credential = Credential()
    print_debug('完成!')
    return credential
Example #14
0
def submit_login():
    """ handle <input name='submit_login' ...> form submission. """
    # invoked from handle_post()
    print_debug(' submit_login: username = "******" '.format(
        request.form['username']))
    user = Person.by_username(request.form['username'])
    print_debug(' submit_login: user = "******"'.format(user))
    if user.is_anonymous() or \
       not user.check_password(request.form['password']):
        flash('Oops: wrong username or password.', 'login')
        return url_for('mainroute', pagepath=request.page.path, action='login')
    else:
        user.logged_in = True
        login_user(user)
        return url_for('mainroute', pagepath=request.page.path)
Example #15
0
    def __init__(self, description: str):
        """Create an instance of the detector class

        Parameters
        ----------
        description (str): A few-word description of the specific detector model
        """

        from lib.squeezedet_keras.main.config.create_config import load_dict, squeezeDet_config
        from lib.squeezedet_keras.main.model.modelLoading import load_only_possible_weights

        print_debug(f'\nPreparing {description}...')

        self.keras_model: Model
        self.description = description

        # Load configuration from config.json and set a few custom values
        config_dictionary: Dict[str, Any] = {
            **squeezeDet_config(''),
            **load_dict(os.path.abspath('config.json')),
            'SCORE_THRESHOLD': 0.5,
        }
        self.config: Any = EasyDict(config_dictionary)

        # Only supports one image in each batch yet
        self.config.BATCH_SIZE = 1

        # Load the model using the class' implemented "load_model" method
        print_debug('Loading model...')
        model_file = self.load_model()

        # If the model is loaded and a weights file is given, set the input layer's shape to be the
        # expected shape of the input image (from config.json)
        if hasattr(self, 'keras_model'
                   ) and self.keras_model is not None and model_file != '':
            # Create new (fix-sized) input layer
            new_input: Tensor = layers.Input(
                batch_shape=(1, self.config.IMAGE_HEIGHT,
                             self.config.IMAGE_WIDTH, 3))
            new_layers: Model = self.keras_model(new_input)
            self.keras_model = Model(new_input, new_layers)

            # Load weights for each layer if it exist
            load_only_possible_weights(self.keras_model, model_file)
Example #16
0
async def update_one_bgm_data(data: SimpleNamespace, bgm_id: int, status: str):
    '''更新单个 Bangumi 动画数据'''
    print_debug(f'开始更新 @ {bgm_id} -> {status} ...')
    update_flag = True
    if SKIP_COLLECTED:
        # 获取当前收藏状态
        collection_status_json = await try_for_times_async_json(  # 尝试三次
            3,
            lambda: client.get(f'https://api.bgm.tv/collection/{bgm_id}',
                               headers={'Authorization': data.bgm_auth_data}))
        if ('status' in collection_status_json
                and collection_status_json['status']['type'] == status):
            update_flag = False

    if update_flag:
        if status == 'collect':  # 看过 -> 更新分集进度
            # 获取分集总数
            subject_data = await try_for_times_async_json(  # 尝试三次
                3, lambda: client.get(f'https://api.bgm.tv/subject/{bgm_id}',
                                      headers=
                                      {'Authorization': data.bgm_auth_data}))
            eps_count = subject_data['eps_count']
            print_debug(f'更新分集进度 @ {bgm_id} -> {eps_count} ...')
            if not READ_ONLY:
                response = await try_for_times_async_chain(  # 尝试三次
                    3, lambda: client.post(
                        f'https://api.bgm.tv'
                        f'/subject/{bgm_id}/update/watched_eps',
                        data={'watched_eps': eps_count},
                        headers={'Authorization': data.bgm_auth_data}))
                response.raise_for_status()
        print_debug(f'更新收藏 @ {bgm_id} -> {status} ...')
        if not READ_ONLY:
            response = await try_for_times_async_chain(  # 尝试三次
                3, lambda: client.post(
                    f'https://api.bgm.tv/collection/{bgm_id}/update',
                    data={'status': status},
                    headers={'Authorization': data.bgm_auth_data}))
            response.raise_for_status()
    else:
        print_debug(f'跳过 @ {bgm_id} -> {status} ...')
    data.bangumi_processed_count += 1
    print_debug(f'完成 @ {bgm_id}!')
Example #17
0
def submit_newcourse():
    """ create new course """
    #print_debug('submit_newcourse: {}'.format(request.form))
    name = request.form['name']  # e.g. "Intro Programming"
    path = request.form[
        'path']  # should have form term/folder e.g. fall2018/cs1
    copyfrom = request.form['copyfrom']  # e.g. "fall2017/cs1"
    startdate = path_to_startdate(path)
    title = name_to_htmltitle(name)
    print_debug(' submit_newcourse: name = "{}"'.format(name))
    print_debug('                   path = "{}"'.format(path))
    print_debug('                   copyfrom = "{}"'.format(copyfrom))
    newcourse = Course.create_course(name,
                                     path,
                                     start=startdate,
                                     name_as_title=title,
                                     copyfrom=copyfrom)
    for name in request.form['faculty'].split(','):
        try:
            faculty = Person.get(username=name.strip())
        except:
            faculty = None
        if not faculty:
            try:
                faculty = Person.get(username=name.strip())
            except:
                faculty = None
        if faculty:
            today = str(Time())[:10]
            newcourse.enroll(faculty, 'faculty', today, create_work=False)
    return newcourse.url
Example #18
0
def __quantize_model(converter: tensorflow.lite.TFLiteConverter,
                     model: Detector) -> Any:
    print_debug('\nConverting model, this will take some time...')

    # Get sample data to be used during converstion
    image_files: List[str] = [
        os.path.abspath(os.path.join(IMAGES_PATH, image))
        for image in os.listdir(IMAGES_PATH)
    ]
    annotation_files: List[str] = [
        os.path.abspath(os.path.join(ANNOTATIONS_PATH, annotations))
        for annotations in os.listdir(ANNOTATIONS_PATH)
    ]

    try:
        # Set optimizations to perform on model to be compatible with edge TPUs
        converter.optimizations = [tensorflow.lite.Optimize.DEFAULT]
        converter.representative_dataset = lambda: __input_data_generator(
            model, image_files, annotation_files)

        converter.target_spec.supported_ops = [
            tensorflow.lite.OpsSet.TFLITE_BUILTINS_INT8
        ]
        converter.inference_input_type = tensorflow.uint8
        converter.inference_output_type = tensorflow.uint8

        # Start conversion
        return converter.convert()
    except Exception as exception:  # pylint: disable=broad-except
        print_debug('Error: Could not convert model to TFLite')
        print_debug(str(exception))
Example #19
0
def submit_assignments():
    """ handle assignment editing """
    print_debug(' submit_assignments: ')
    print_debug('   request.form is {}'.format(request.form))
    assignment_data = parse_assignment_data(request.form)
    print_debug('   len(assignment_data) = {}'.format(len(assignment_data)))
    request.page.course.update_assignments(assignment_data)
    return request.base_url  #  reload assignments page without edit
Example #20
0
async def update_bgm_data(data: SimpleNamespace):
    '''更新 Bangumi 动画数据'''
    print_debug('创建更新单个 Bangumi 数据任务...')
    while not data.get_bili_data_task.done():
        await check_and_update_bgm_data(data)
        await sleep(0.001)
    await check_and_update_bgm_data(data)

    print_debug('等待更新单个 Bangumi 数据任务...')
    await gather(*data.update_one_bgm_data_tasks)

    print_debug('完成!')
Example #21
0
async def get_bili_data(data: SimpleNamespace):
    '''获取 Bilibili 追番数据'''
    print_debug('获取第一页 Bilibili 追番数据...')
    try:
        data.bili_total_count = await get_one_bili_data(data, 1)
    except ResponseCodeException:
        print_status('** Bilibili 授权设置不正确,无法读取隐私设置' '未公开的 Bilibili 追番数据!')
        exit(1)

    print_debug('创建并等待获取单个 Bilibili 追番数据任务...')
    await gather(*(loop.create_task(get_one_bili_data(data, page))
                   for page in range(2, data.bili_total_count + 1)))
    print_debug('完成!')
Example #22
0
async def get_and_update(bili2bgm_map, bili_auth_data, bili_uid,
                         bgm_auth_data):
    '''获取 Bilibili 番剧数据并更新 Bangumi 动画数据'''
    data = SimpleNamespace(
        bili2bgm_map=bili2bgm_map,
        user=User(bili_uid, bili_auth_data),
        bili_auth_data=bili_auth_data,
        bgm_auth_data=bgm_auth_data,
        bili_processed_count=0,
        bili_total_count=None,
        bangumi_total=0,
        # [(bili media id, 1: 想看 | 2: 在看 | 3: 看过), ...]
        bangumi_remaining=deque(),
        bangumi_processed_count=0,
        bangumi_failed=deque(),
        bangumi_failed_count=0,
        animation_points=1,
        get_bili_data_task=None,
        update_bgm_data_task=None,
        update_one_bgm_data_tasks=deque(),
        print_unknown_tasks=deque())

    print_debug('创建获取 Bilibili 数据任务 -> [get_bili_data]')
    data.get_bili_data_task = loop.create_task(get_bili_data(data))

    print_debug('创建更新 Bangumi 数据任务 -> [update_bgm_data]')
    data.update_bgm_data_task = loop.create_task(update_bgm_data(data))

    print_debug('等待任务...')

    while data.bili_total_count is None:
        await sleep(0.001)

    while not (data.get_bili_data_task.done()
               and data.update_bgm_data_task.done()):
        await print_progress(data)
        await sleep(0.1)

    await data.get_bili_data_task
    await data.update_bgm_data_task

    await print_progress(data)
    await gather(*data.print_unknown_tasks)
    await print_progress(data)

    print()
Example #23
0
def submit_edit():
    """ handle file edit form """
    # ... including student work pages.
    # invoked from handle_post()
    # the form text data is in the form dict key, i.e. request.form['edit_text']
    # print_debug(' submit_edit: request.form : {}'.format(request.form.items()))
    #
    # request.form will look something like
    #  { 'submit_edit' : u'save page',                     # submit button
    #    'edit_text'   : u'page content\r\n===\r\n etc'    # textarea
    #  }
    #
    # If this is a work page, then update the Work database object.
    # (The Work object is created in Page.get_from_path)
    if request.page.is_work:
        now = str(Time())  # string with current time
        with db.atomic():
            if request.page.user_role.name == 'faculty':
                page = request.page
                page.work.faculty_modified = now
                # If checkbox for 'submitted' and that didn't have a value,
                # then set it - used to mark work as submitted,
                # i.e. student emails work & faculty submits.
                if "submitted_checkbox" in request.form \
                     and not page.work.submitted:
                    due = Time(page.work_due)
                    print_debug(" submit_edit: due = {}".format(str(due)))
                    if "on_time_checkbox" in request.form:
                        due.shift_minutes(-5)
                    else:
                        due.shift_minutes(5)
                    page.work.submitted = str(due)
                    print_debug(" submit_edit: submitted set to {}".format( \
                                page.work.submitted))
                if 'grade' in request.form:
                    page.work.grade = str(request.form['grade'])
            else:
                request.page.work.student_modified = now
                if not request.page.work.submitted:
                    request.page.work.submitted = now
            request.page.work.save()
    # Save the page content to a file and to git.
    bytes_written = request.page.write_content(request.form['edit_text'])
    print_debug(' submit_edit: bytes_written = {}'.format(bytes_written))
    git.add_and_commit(request.page)
    return request.base_url  # ... and reload it without ?action=edit
Example #24
0
def submit_createfolder():
    """ handle folder creation """
    # example request.form is {'submit_createfolder': 'create',
    #                          'foldername': 'testfolder'}
    # page.abs path is current directory i.e. /User/mahoney/.../folder1/
    foldername = request.form['foldername']
    print_debug(' submit_createfolder : foldername="{}" '.format(foldername))
    if not is_clean_folder_name(foldername):
        print_debug(' submit_createfolder: illegal chars in foldername')
        flash('Oops: folder names may only contain ' + \
              'lowercase letters, numbers, or underbar.', 'folder')
        flash(foldername)
        return url_for('mainroute', pagepath=request.page.path, action='edit')
    folderpath = os.path.join(request.page.path, foldername)
    folderabspath = os.path.join(request.page.abspath, foldername)
    print_debug(
        ' submit_createfolder : newfolderabspath="{}" '.format(folderabspath))
    Page.new_folder(folderabspath, user=request.page.user)
    return url_for('mainroute', pagepath=request.page.path, action='edit')
Example #25
0
def __evaluate_models():
    # Uncomment the line below to disable GPU in tensorflow, so that models can be benchmarked on
    # CPU only
    # os.environ['CUDA_VISIBLE_DEVICES'] = "-1"

    initialize_environment()

    # Uncomment line below to run detection on video displaying the bounding boxes on it
    # SSDTFLite().evaluate_performance(0, is_display=True)

    models = [
        'RetinaNet',
        'SSD TFLite v2',
        'SSD TFLite v1',
        'YOLOv3',
    ]

    # Evaluate accuracy of models one-by-one
    statistics = [
        __evaluate_model(RetinaNet()),
        __evaluate_model(SSDTFLite('v2')),
        __evaluate_model(SSDTFLite('v1')),
        __evaluate_model(YOLOv3()),
    ]

    # Convert the statistics to the correct format to be passed to the tabulate library
    aggregated_statistics = [[models[index], *current_statistics, fps]
        for index, (current_statistics, fps) in enumerate(statistics)]

    # Show evaluation results in a table in command line
    print_debug(f'\nResults on {SAMPLE_COUNT} samples\n')
    print_debug(tabulate(
        aggregated_statistics,
        headers=['Model', 'Precision', 'Recall', 'F1 Score', 'mAP', 'FPS']
    ))

    print_debug('\nExiting...')
Example #26
0
    def evaluate_performance(self,
                             video_path: Union[str, int],
                             is_display: bool = False) -> float:
        """Evaluates the performance of the current model in terms of frames per second

        Parameters
        ----------
        video_path (Union[str, int]): Path of the video used for evaluating model performance

        is_display (bool, optional (default: false)): Switch to enable or disable displaying the
            video and the detection boxes while doing the performance evaluation

        Returns
        -------
        float: Mean FPS count for the duration of the evaluation

        Raises
        ------
        IOError: The error if the given video can't be opened
        """

        print_debug('\nEvaluating performance...')

        # Open video feed
        video = cv2.VideoCapture(video_path)
        if not video.isOpened():
            raise IOError("Couldn't open webcam or video")

        # Initialize timings and fps counter
        elapsed_time = 0.0
        frames_in_second = 0
        previous_time = time.time()

        fps_measurements = []
        fps_text = 'N/A'

        if is_display:
            # Initialize window for video display
            cv2.namedWindow('result', cv2.WINDOW_NORMAL)
            cv2.resizeWindow('result', (960, 720))

        while True:
            # Read a frame from video
            result, frame = video.read()
            if not result:
                break

            # Run object detection using the current model (self)
            predictions = self.__detect_batch(([Image.fromarray(frame)],
                                               cast(BatchAnnotations,
                                                    numpy.zeros((0, 0, 10)))))

            batch_boxes = predictions[0] if len(predictions) > 0 else []
            boxes = batch_boxes[0][0] if len(batch_boxes) > 0 else []

            # Calculate elapsed and detection time
            current_time = time.time()
            detection_time = current_time - previous_time
            previous_time = current_time

            elapsed_time += detection_time
            frames_in_second = frames_in_second + 1

            if elapsed_time > 1:
                # If one second elapsed, save current fps measurement and reset fps counter
                elapsed_time = elapsed_time - 1
                fps_measurements.append(frames_in_second)
                frames_in_second = 0

                fps_text = str(fps_measurements[-1])
                print_debug(f'FPS: {fps_text}')

                if len(fps_measurements) > 9 and not is_display:
                    break

            if is_display:
                # If display is turned on, show the current detection result (bounding box on image)
                for [ymin, xmin, ymax, xmax] in boxes:
                    cv2.rectangle(frame, (ymin, xmin), (ymax, xmax),
                                  (0, 255, 0), 4)

                cv2.putText(frame,
                            text=f'FPS: {fps_text}',
                            org=(3, 15),
                            fontFace=cv2.FONT_HERSHEY_SIMPLEX,
                            fontScale=0.50,
                            color=(0, 255, 0),
                            thickness=2)
                cv2.imshow('result', frame)

            # Interrupt performance evaluation if q is pressed
            if cv2.waitKey(1) & 0xFF == ord('q'):
                break

        # Print the mean of all the measured fps values
        mean_fps = statistics.mean(fps_measurements)
        print_debug(f'Mean FPS: {mean_fps}')

        return mean_fps
Example #27
0
    def evaluate(
        self,
        images_path: str,
        annotations_path: str,
        total_samples: int,
        video_path: str,
    ) -> Tuple[List[StatisticsEntry], float]:
        """Evaluates the current model in terms of its image detection quality and performance

        Parameters
        ----------
        images_path (str): Path of the image directory, where the evaluation images can be loaded
            from

        annotations_path (str): Path of the annotations directory, where the correct annotations for
            the evaluation images can be loaded from

        total_samples (int): Number of samples to use to evaluate the model's detection quality

        video_path (str): Path of the video to use for performance evaluation

        Returns
        -------
        Tuple[List[StatisticsEntry], float]: Tuple of model evaluation statistics (precision,
            recall, F1 score, mAP) and the performance metric (FPS)

        Raises
        ------
        IOError: The error if the given video can't be opened
        """

        from lib.squeezedet_keras.main.model.evaluation import compute_statistics

        print_debug(
            f'\nEvaluating {self.description} on {total_samples} samples...')

        # Load image names and annotations
        image_files: List[str] = [
            os.path.abspath(os.path.join(images_path, image))
            for image in os.listdir(images_path)
        ]
        annotation_files: List[str] = [
            os.path.abspath(os.path.join(annotations_path, annotations))
            for annotations in os.listdir(annotations_path)
        ]

        # Get predictions in batches
        boxes: List[Boxes] = []
        classes: List[Classes] = []
        scores: List[Scores] = []
        annotations: List[BatchAnnotations] = []

        sample_count = 0
        for data in self.data_generator(image_files, annotation_files,
                                        total_samples):
            _, batch_annotations = data
            (batch_boxes, batch_classes,
             batch_scores) = self.__detect_batch(data)

            boxes.append(batch_boxes[0])
            classes.append(batch_classes[0])
            scores.append(batch_scores[0])
            annotations.append(batch_annotations)

            sample_count += 1

            if sample_count % 10 == 0:
                print_debug(f'{sample_count}/{total_samples}')

        # Increment class ids, because evaluation script removes zero-labels
        incremented_class_ids = {
            'CLASS_TO_IDX':
            {name: id + 1
             for name, id in self.config.CLASS_TO_IDX.items()}
        }

        # Get statistics on prediction results
        model_statistics: Statistics = compute_statistics(
            boxes, classes, scores, annotations,
            EasyDict({
                **self.config,
                **incremented_class_ids
            }))

        # Print evaluation results (precision, recall, f1, AP)
        statistics_zip = cast(
            Iterator[Tuple[float, float, float, List[float]]],
            zip(*model_statistics))

        accuracy_statistics: List[StatisticsEntry] = []
        for index, (precision, recall, f1_score,
                    average_precision) in enumerate(statistics_zip):
            print_debug(
                f'{self.config.CLASS_NAMES[index]} - precision: {precision}, '
                f'recall: {recall}, f1: {f1_score}, '
                f'mAP: {statistics.mean(average_precision)}')

            accuracy_statistics.append((precision, recall, f1_score,
                                        statistics.mean(average_precision)))

        return accuracy_statistics, self.evaluate_performance(video_path)
Example #28
0
def mainroute(pagepath):

    # home page for default 'umber' course
    if pagepath == '' or pagepath == 'home':
        return redirect('/' + url_base + '/site/docs/home')

    print_debug('- ' * 30)
    print_debug(' mainroute: pagepath = "{}"'.format(pagepath))
    print_debug(' mainroute: request.url = "{}"'.format(request.url))
    print_debug(' mainroute: request.args = "{}"'.format(request.args))
    print_debug(' mainroute: current_user = {}'.format(current_user))

    # -- testing session & cookie ---
    #print_debug(' mainroute: session = {}'.format(session))
    #color = 'red'
    #if color != '':
    #    session['color'] = color
    # -------------------------------

    # If the url is 'foo.md' then redirect to canonical url 'foo'.
    (basepath, extension) = os.path.splitext(pagepath)
    if extension == '.md':
        (ignore1, ignore2, query) = split_url(request.url)
        redirect_url = '/' + url_base + '/' + basepath
        if query:
            redirect_url += '?' + query
        print_debug('redirecting to "{}"'.format(redirect_url))
        return redirect(redirect_url)

    # Get the corresponding Page object and its file settings.
    page = Page.get_from_path(pagepath,
                              revision=request.args.get('revision', None),
                              action=request.args.get('action', None),
                              user=current_user)

    print_debug(' mainroute: page.abspath = {}'.format(page.abspath))

    # If a course for the isn't found, a special 'error' course
    # will be returned as a signal.
    if page.course.name == 'error':
        return abort(404)  # "not found"

    print_debug(' mainroute: course.name = "{}"'.format(page.course.name))
    print_debug(' mainroute: course.url = "{}"'.format(page.course.url))
    print_debug(' mainroute: page.access = {}'.format(page.access))
    print_debug(' mainroute: page can read = {}, write = {}'.format(
        page.can['read'], page.can['write']))
    print_debug((' mainroute: page exists = {},' + \
        ' is_file = {}, is_dir = {}').format(
        page.exists, page.is_file, page.is_dir))

    # Redirect directories which don't end in '/' to '/'.
    if page.is_dir and len(pagepath) > 0 and pagepath[-1] != '/':
        print_debug('redirecting directory to /')
        return redirect(url_for('mainroute', pagepath=pagepath) + '/')

    # Redirect directories to index.md or index.html if either exists.
    if page.is_dir:
        for index in ('index.md', 'index.html'):
            if os.path.exists(os.path.join(page.abspath, index)):
                indexpath = os.path.join(pagepath, index)
                return redirect(url_for('mainroute', pagepath=indexpath))

    # Redirect nonexisting nonystem editable pages to ?action=edit
    # ... but not if this is the POST that is trying to create it.
    if page.can['write'] and not page.exists and not page.action and \
                             not page.is_sys and not page.is_dir and \
                             not request.method == 'POST' :
        return redirect(page.url + '?action=edit')

    # Don't serve up any invisible "dot" files - reload enclosing folder.
    # This includes (.access.yaml, .keep) among possible others.
    if len(page.name) > 0 and page.name[0] == '.':
        url = page.url
        while page.url[-1] != '/' and len(page.url) > 0:
            url = url[:-1]
        if len(page.url) > 12 and page.url[-12:] == '.access.yaml':
            return redirect(page.url[:-12])
        else:
            return redirect(page.course.url)

    # Store the page object (and therefore page.course and page.user)
    # in the request, so that the request action handler doesn't need args.
    request.page = page

    if request.method == 'POST' and 'dropzone' in request.args:
        print_debug('-- dropzone file upload --')  # i.e. handle dropzonejs.com
        return ajax_upload()

    elif request.method == 'POST':
        print_debug(' mainroute: POST')
        reload_url = form_post()
        return redirect(reload_url)

    elif (not page.is_dir and (page.ext == '' or not page.ext in ('.md'))
          and page.can['read'] and page.exists):

        # readable pages that shouldn't be in umber's window pane :
        # just serve up their content.
        # (If the page isn't readable, then render_template(main.html) below
        # will show the error page within the umber setting.)
        # TODO: Do the right thing for actions like ?version=xxx or ?history ?
        # TODO: Handle what was _html for .py and .html
        #       with ?something (?html , ?source, ?pretty) ?
        # TODO: forward these sorts of requests to apache or other server??
        # TODO: handle unknown mimetype better, perhaps don't send file at all?

        print_debug(' -- mainroute - raw-ish content ')
        print_debug('   mimetype={}'.format(page.get_mimetype()))
        print_debug('   page.name_with_ext = {}'.format(page.name_with_ext))
        print_debug('   page.path = {}'.format(page.path))
        print_debug('   request.args = {}'.format(str(request.args)))
        _content = page.content()
        _mimetype = page.get_mimetype()
        if 'html' in request.args:
            print_debug('   pygmentizing ...')
            _content = pygmentize(_content, filename=page.name_with_ext)
            _mimetype = 'text/html'
        return Response(_content, mimetype=_mimetype)

    else:

        # umber page : folder or *.md or sys/*
        return render_template('main.html',
                               name='main',
                               page=page,
                               user=page.user,
                               course=page.course,
                               debug=True)
Example #29
0
def ajax_upload():
    """ handle ajax file upload """
    # dropzone sends one ajax request per file, so this invocation is for
    # one file even if multiple files have been dropped on the web page.

    page = request.page
    print_debug(' ajax_upload ')
    print_debug('   request.form.keys() : {}'.format(request.form.keys()))
    print_debug('   destination : "{}"'.format(page.abspath))
    print_debug('   page.url : {}'.format(page.url))

    # Make sure that this user is authorized to put files here.
    if not page.can['write']:
        return ajax_response(False,
                             'Oops - invalid permissions for file upload.')

    if page.is_dir:
        abspath = page.abspath
    else:
        # create .attachments folder if need be
        abspath = page.attachments_folder()
        if not os.path.exists(abspath):
            try:
                os.mkdir(abspath)
            except:
                print_debug(' submit_createfolder: os.makedir failed')
                return ajax_response(False,
                                     'error creating attachments folder')

    for upload in request.files.getlist("file"):
        # Should be only one file when using dropbox, I think.

        # TODO: send something other than success if there's a problem here,
        # probably with a try: except: block.

        filename = secure_filename(upload.filename)
        print_debug('   file : "{}"'.format(filename))
        destination = os.path.join(abspath, filename)
        upload.save(destination)

        # TODO: do the github stuff asyncronously ?
        git.add_and_commit(page, abspath=destination)

    print_debug(" sending ajax response ")
    return ajax_response(True, 'upload success')
Example #30
0
def submit_grades():
    """ handle setting all course grades from grid """
    print_debug('submit grades')
    print_debug(request.form)
    Work.edit_grades(request.form)
    return url_for('mainroute', pagepath=request.page.path)