def get_only_line(mode, image):

    if mode == 0:
        ret, image_bin = cv2.threshold(image[:, :, mode], 200, 255,
                                       cv2.THRESH_BINARY)
        img_bin = image_utils.dilate(
            image_utils.erode(
                image_utils.dilate(image_utils.erode(image_bin, 3), 3), 3), 3)
    elif mode == 1:
        img_bin = image_utils.erode(
            image_utils.dilate(image_utils.erode(image[:, :, mode], 2), 2), 2)
    else:
        img_bin = []

    return img_bin
예제 #2
0
import cv2
import image_utils

for i in range(0, 10):
    video = cv2.VideoCapture('test samples/video-' + str(i) + '.avi')

    if video.isOpened() == 0:
        print("Error!!!")

    idx = 0
    while video.isOpened():

        ret, frame = video.read()

        if ret:

            removed_noise_frame = image_utils.image_bin(image_utils.image_gray(frame), 200)
            removed_noise_frame = image_utils.erode(image_utils.dilate(removed_noise_frame))

            cv2.imwrite('noiseless_videos/video_' + str(i) + '/frame_' + str(idx) + '.jpg', removed_noise_frame)
            if cv2.waitKey(1) & 0xFF == ord('q'):
                break

        else:
            break

        print(idx)
        idx = idx + 1

    video.release()
예제 #3
0
        # Find the corners, skipping the image on failure
        try:
            corners = corner_finding.find_corner_marks(prepared_image,
                                                       save_path=debug_path)
        except corner_finding.CornerFindingError:
            progress.set_status(
                f"Error with '{image_path.name}': couldn't find corners. Skipping..."
            )
            time.sleep(1)
            continue

        # Dilates the image - removes black pixels from edges, which preserves
        # solid shapes while destroying nonsolid ones. By doing this after noise
        # removal and thresholding, it eliminates irregular things like W and M
        morphed_image = image_utils.dilate(prepared_image,
                                           save_path=debug_path)

        # Establish a grid
        grid = grid_r.Grid(corners,
                           grid_i.GRID_HORIZONTAL_CELLS,
                           grid_i.GRID_VERTICAL_CELLS,
                           morphed_image,
                           save_path=debug_path)
        # Calculate the fill threshold
        threshold = grid_r.calculate_bubble_fill_threshold(
            grid, save_path=debug_path)

        # Get the answers for questions
        answers = [
            grid_r.read_answer_as_string(i, grid, multi_answers_as_f,
                                         threshold)
예제 #4
0
    print(v_w)
    print(v_h)

    new_video = cv2.VideoWriter('test samples/video_gr-' + str(i) + '.avi',
                                cv2.VideoWriter_fourcc('M', 'J', 'P', 'G'), 40,
                                (v_w, v_h))

    idx = 0
    while video.isOpened():

        ret, frame = video.read()
        if ret:

            img = image_utils.image_bin(image_utils.image_gray(frame))
            img_bin = image_utils.erode(image_utils.dilate(img))

            selected_regions, numbers = video_utils.select_roi(
                frame.copy(), img_bin, idx, i)
            cv2.imwrite(
                "contoured_frames/video_" + str(i) + "/frame_" + str(idx) +
                ".jpg", selected_regions)

            new_video.write(selected_regions)
            cv2.imshow("Video" + str(i), selected_regions)

            idx = idx + 1
            if cv2.waitKey(1) & 0xFF == ord('q'):
                break

        else:
예제 #5
0
def process_input(image_paths: tp.List[Path], output_folder: Path,
                  multi_answers_as_f: bool, empty_answers_as_g: bool,
                  keys_file: tp.Optional[Path],
                  arrangement_file: tp.Optional[Path], sort_results: bool,
                  output_mcta: bool, debug_mode_on: bool,
                  form_variant: grid_i.FormVariant,
                  progress_tracker: tp.Optional[ProgressTrackerWidget],
                  files_timestamp: tp.Optional[datetime]):
    """Takes input as parameters and process it for either gui or cli.
    
    Parameter progress_tracker determines whith interface in use.
    If progress_tracker is given, function runs in gui mode.
    If progress_tracker parameter is None, prints all progress statuses to stdout.
    """

    answers_results = data_exporting.OutputSheet([x for x in grid_i.Field],
                                                 form_variant.num_questions)
    keys_results = data_exporting.OutputSheet(
        [grid_i.Field.TEST_FORM_CODE, grid_i.Field.IMAGE_FILE],
        form_variant.num_questions)

    rejected_files = data_exporting.OutputSheet([grid_i.Field.IMAGE_FILE], 0)

    debug_dir = output_folder / (
        data_exporting.format_timestamp_for_file(files_timestamp) + "debug")
    if debug_mode_on:
        data_exporting.make_dir_if_not_exists(debug_dir)

    try:
        for image_path in image_paths:
            if debug_mode_on:
                debug_path = debug_dir / image_path.stem
                data_exporting.make_dir_if_not_exists(debug_path)
            else:
                debug_path = None

            if progress_tracker:
                progress_tracker.set_status(f"Processing '{image_path.name}'.")
            else:
                print(f"Processing '{image_path.name}'.")

            image = image_utils.get_image(image_path, save_path=debug_path)
            prepared_image = image_utils.prepare_scan_for_processing(
                image, save_path=debug_path)

            try:
                corners = corner_finding.find_corner_marks(
                    prepared_image, save_path=debug_path)
            except corner_finding.CornerFindingError:
                rejected_files.add({grid_i.Field.IMAGE_FILE: image_path.name},
                                   [])
                continue

            # Dilates the image - removes black pixels from edges, which preserves
            # solid shapes while destroying nonsolid ones. By doing this after noise
            # removal and thresholding, it eliminates irregular things like W and M
            morphed_image = image_utils.dilate(prepared_image,
                                               save_path=debug_path)

            # Establish a grid
            grid = grid_r.Grid(corners,
                               grid_i.GRID_HORIZONTAL_CELLS,
                               grid_i.GRID_VERTICAL_CELLS,
                               morphed_image,
                               save_path=debug_path)

            # Calculate fill percent for every bubble
            field_fill_percents = {
                key: grid_r.get_group_from_info(value,
                                                grid).get_all_fill_percents()
                for key, value in form_variant.fields.items()
                if value is not None
            }
            answer_fill_percents = [
                grid_r.get_group_from_info(question,
                                           grid).get_all_fill_percents()
                for question in form_variant.questions
            ]

            # Calculate the fill threshold
            threshold = grid_r.calculate_bubble_fill_threshold(
                field_fill_percents,
                answer_fill_percents,
                save_path=debug_path,
                form_variant=form_variant)

            # Get the answers for questions
            answers = [
                grid_r.read_answer_as_string(i, grid, multi_answers_as_f,
                                             threshold, form_variant,
                                             answer_fill_percents[i])
                for i in range(form_variant.num_questions)
            ]

            field_data: tp.Dict[grid_i.RealOrVirtualField, str] = {
                grid_i.Field.IMAGE_FILE: image_path.name,
            }

            # Read the Student ID. If it indicates this exam is a key, treat it as such
            student_id = grid_r.read_field_as_string(
                grid_i.Field.STUDENT_ID, grid, threshold, form_variant,
                field_fill_percents[grid_i.Field.STUDENT_ID])
            if student_id == grid_i.KEY_STUDENT_ID:
                form_code_field = grid_i.Field.TEST_FORM_CODE
                field_data[form_code_field] = grid_r.read_field_as_string(
                    form_code_field, grid, threshold, form_variant,
                    field_fill_percents[form_code_field]) or ""
                keys_results.add(field_data, answers)

            else:
                for field in form_variant.fields.keys():
                    field_value = grid_r.read_field_as_string(
                        field, grid, threshold, form_variant,
                        field_fill_percents[field])
                    if field_value is not None:
                        field_data[field] = field_value
                answers_results.add(field_data, answers)
            if progress_tracker:
                progress_tracker.step_progress()

        answers_results.clean_up(
            replace_empty_with="G" if empty_answers_as_g else "")
        answers_results.save(output_folder,
                             "results",
                             sort_results,
                             timestamp=files_timestamp)

        if rejected_files.row_count == 0:
            success_string = "✔️ All exams processed and saved.\n"
        else:
            success_string = "❗ Some files could not be processed (see rejected_files output).\nAll other exams were processed and saved.\n"
            rejected_files.save(output_folder,
                                "rejected_files",
                                sort=False,
                                timestamp=files_timestamp)

        if keys_file:
            keys_results.add_file(keys_file)

        if (keys_results.row_count == 0):
            success_string += "No exam keys were found, so no scoring was performed."
        elif (arrangement_file and keys_results.row_count == 1):
            answers_results.reorder(arrangement_file)
            keys_results.data[1][keys_results.field_columns.index(
                grid_i.Field.TEST_FORM_CODE)] = ""

            answers_results.save(output_folder,
                                 "rearranged_results",
                                 sort_results,
                                 timestamp=files_timestamp)
            success_string += "✔️ Results rearranged based on arrangement file.\n"

            keys_results.delete_field_column(grid_i.Field.TEST_FORM_CODE)
            keys_results.save(output_folder,
                              "key",
                              sort_results,
                              timestamp=files_timestamp,
                              transpose=True)

            success_string += "✔️ Key processed and saved.\n"

            scores = scoring.score_results(answers_results, keys_results,
                                           form_variant.num_questions)
            scores.save(output_folder,
                        "rearranged_scores",
                        sort_results,
                        timestamp=files_timestamp)
            success_string += "✔️ Scored results processed and saved."
        elif (arrangement_file):
            success_string += "❌ Arrangement file and keys were ignored because more than one key was found."
        else:
            keys_results.save(output_folder,
                              "keys",
                              sort_results,
                              timestamp=files_timestamp)
            success_string += "✔️ All keys processed and saved.\n"
            scores = scoring.score_results(answers_results, keys_results,
                                           form_variant.num_questions)
            scores.save(output_folder,
                        "scores",
                        sort_results,
                        timestamp=files_timestamp)
            success_string += "✔️ All scored results processed and saved."

        if (output_mcta):
            transform_and_save_mcta_output(answers_results, keys_results,
                                           files_timestamp, output_folder)

        if progress_tracker:
            progress_tracker.set_status(success_string, False)
        else:
            print(success_string)
    except (RuntimeError, ValueError) as e:
        wrapped_err = "\n".join(textwrap.wrap(str(e), 70))
        if progress_tracker:
            progress_tracker.set_status(f"Error: {wrapped_err}", False)
        else:
            print(f'Error: {wrapped_err}')
        if debug_mode_on:
            raise
    if progress_tracker:
        progress_tracker.show_exit_button_and_wait()
예제 #6
0
                lines_blue = line_utils.get_line(img_blue)
                lines_green = line_utils.get_line(img_green)

                #img_bin = image_utils.erode_large(image_utils.dilate_large(img)) #dodata spolj dilatacija
                #sa dvostruke spolj dil promenjeno na bez spolj dil

                #ovde je bilo umesto frame img_bin, da vidimo kakve cu rez dobiti sa ovim

                lines_blue_pixels = line_utils.convert_lines_to_pixels(
                    lines_blue, image_utils.image_gray(frame))
                lines_green_pixels = line_utils.convert_lines_to_pixels(
                    lines_green, image_utils.image_gray(frame))

                img_bin = image_utils.image_bin(image_utils.image_gray(frame),
                                                200)
                img_bin_ed = image_utils.dilate(
                    image_utils.erode(image_utils.dilate(img_bin, 1), 1), 2)

                cv2.imwrite(
                    'noiseless_videos/video_' + str(i) + '/frame_' + str(idx) +
                    '.jpg', img_bin_ed)

                selected_regions, numbers, dimensions = video_utils.select_roi(
                    frame.copy(), img_bin_ed, idx, i)

                blue_regions, blue_dimensions = line_utils.check_close_ones(
                    numbers, dimensions, lines_blue_pixels, i)
                green_regions, green_dimensions = line_utils.check_close_ones(
                    numbers, dimensions, lines_green_pixels, i)

                #f1 = open('results/close_blue' + str(i) + '.txt', "a")
                #f2 = open('results/close_green' + str(i) + '.txt', "a")