Exemple #1
0
    def freehand_annotation_record():
        slide_id = request.args.get('slide_id', default=1, type=int)
        annotator_id = request.args.get('annotator_id', default=1, type=int)
        annotation_project = request.args.get('project',
                                              default="None",
                                              type=str)
        slide_uuid = request.args.get('slide_uuid', default="", type=str)

        annotation_root_folder = freehand_annotation_data_root + annotation_project + '/' + slide_uuid + '/'

        if not os.path.exists(annotation_root_folder):
            os.mkdir(annotation_root_folder)
        annotaion_db = annotation_root_folder + 'a' + str(annotator_id) + '.db'

        req_form = request.form
        num_of_points = int(len(req_form) / 3)

        pt_list_att = ('[x]', '[y]', '[grading]')

        db = freehand_annotation_sqlite.SqliteConnector(annotaion_db)

        # In one round, the grading and pslv could be updated only once.
        data = []
        branch_id = -1
        branch_id_find = []
        for i in range(num_of_points):
            if int(req_form[str(i) + '[grading]']) > 0:
                if i == 0:
                    continue
                if (int(req_form[str(i - 1) + '[x]']) == int(req_form[str(i) + '[x]'])) \
                        and (int(req_form[str(i - 1) + '[y]']) == int(req_form[str(i) + '[y]'])):
                    continue
                data.append(
                    tuple([
                        int(req_form[str(i - 1) + '[x]']),
                        int(req_form[str(i - 1) + '[y]']),
                        int(req_form[str(i) + '[x]']),
                        int(req_form[str(i) + '[y]']),
                        int(req_form[str(i) + '[grading]'])
                    ]))
            elif int(req_form[str(i) + '[grading]']) == 0:
                db.delete_points(int(req_form[str(i) + '[x]']),
                                 int(req_form[str(i) + '[y]']))
            elif int(req_form[str(i) + '[grading]']) == -1:
                db.delete_lines(int(req_form[str(i) + '[x]']),
                                int(req_form[str(i) + '[y]']))
            elif int(req_form[str(i) + '[grading]']) == -2:
                branch_id_find = db.find_lines(int(req_form[str(i) + '[x]']),
                                               int(req_form[str(i) + '[y]']))
        if len(data):
            branch_id = db.incert_lines(data)

        return jsonify(pt_false_x=[],
                       pt_false_y=[],
                       region_id=0,
                       branch_id=branch_id,
                       branch_id_find=branch_id_find)
Exemple #2
0
    def freehand_annotation_update_image():
        slide_id = request.args.get('slide_id', default=1, type=int)
        annotator_id = request.args.get('annotator_id', default=1, type=int)
        annotation_project = request.args.get('project',
                                              default="None",
                                              type=str)
        slide_uuid = request.args.get('slide_uuid', default="", type=str)

        annotation_root_folder = freehand_annotation_data_root + annotation_project + '/' + slide_uuid + '/'

        if not os.path.exists(annotation_root_folder):
            os.mkdir(annotation_root_folder)
        annotaion_db = annotation_root_folder + 'a' + str(annotator_id) + '.db'

        error_message = 'N/A'
        request_status = 0

        v1 = request.args.get('var1', 0, type=int)  # Top-left x coordinate
        v2 = request.args.get('var2', 0, type=int)  # Top-left y coordinate
        v3 = request.args.get('var3', 0, type=int)  # Bottom-right x
        v4 = request.args.get('var4', 0, type=int)  # Bottom-right y
        v5 = request.args.get('var5', 0, type=int)  # Viewer width (pixel)
        v6 = request.args.get('var6', 0, type=int)  # Viewer height (pixel)

        loc_tl_coor = (v1, v2)
        loc_viewing_size = (v3 - v1, v4 - v2)
        loc_viewer_size = (v5, v6)

        # Update URL configuration
        slide_url = 'static/cache/' + str(uuid.uuid1())[:13] + '.png'

        mask = numpy.zeros([v6, v5, 4])

        db = freehand_annotation_sqlite.SqliteConnector(annotaion_db)
        color = [[0, 0, 255, 255], [0, 255, 0, 255], [255, 0, 0, 255],
                 [0, 0, 0, 255]]
        # print(db.get_lines())

        for temp in db.get_lines_in_area(int(v1), int(v2), int(v3), int(v4)):
            cv2.line(mask, (int(
                (temp[1] - v1) /
                (v3 - v1) * v5), int((temp[2] - v2) / (v4 - v2) * v6)), (int(
                    (temp[3] - v1) /
                    (v3 - v1) * v5), int((temp[4] - v2) / (v4 - v2) * v6)),
                     color[temp[5] - 1], 3)
        write_url = slide_url
        cv2.imwrite(write_url, mask)

        return jsonify(slide_url=slide_url + '?a=' + str(uuid.uuid1()),
                       top_left_x=loc_tl_coor[0],
                       top_left_y=loc_tl_coor[1],
                       viewing_size_x=loc_viewing_size[0],
                       viewing_size_y=loc_viewing_size[1],
                       exit_code=request_status,
                       error_message=error_message)
def check_freehand_annotation(annotation_file):
    global freehand_annotation_flag
    if not annotation_file in freehand_annotation_flag.keys() or \
            freehand_annotation_flag[annotation_file][1] != os.stat(annotation_file).st_mtime:
        freehand_annotation_flag[annotation_file] = [
            len(
                freehand_annotation_sqlite.SqliteConnector(
                    annotation_file).get_lines()),
            os.stat(annotation_file).st_mtime
        ]
    return freehand_annotation_flag[annotation_file][0]
Exemple #4
0
    def freehand_annotation_clear_lines():
        slide_id = request.args.get('slide_id', default=1, type=int)
        annotator_id = request.args.get('annotator_id', default=1, type=int)
        annotation_project = request.args.get('project',
                                              default="None",
                                              type=str)
        slide_uuid = request.args.get('slide_uuid', default="", type=str)

        annotation_root_folder = freehand_annotation_data_root + annotation_project + '/' + slide_uuid + '/'

        if not os.path.exists(annotation_root_folder):
            os.mkdir(annotation_root_folder)
        annotaion_db = annotation_root_folder + 'a' + str(annotator_id) + '.db'

        db = freehand_annotation_sqlite.SqliteConnector(annotaion_db)
        db.delete_all_lines()
        return jsonify(exit_code=True, )
def export_freehand_annotation_data(manifest_file_url,
                                    manifest_txt=None,
                                    export_file=None):
    annotation_project_root = freehand_annotation_root + manifest_file_url.rsplit(
        "/", 1)[1][:-4] + '/'
    if manifest_txt != None:
        export_annotation_root_temp = "static/cache/" + str(uuid.uuid4()) + "/"
        if export_file == None:
            export_file = export_annotation_root_temp.replace("/cache",
                                                              "")[:-1] + '.zip'
        print(export_file)
        if os.path.exists(export_file):
            os.remove(export_file)

        export_path = export_annotation_root_temp
        if os.path.exists(export_path):
            shutil.rmtree(export_path)
        os.mkdir(export_path)
    else:
        manifest_txt = open(manifest_file_url).readlines()

        if not (not (manifest_file_url.rsplit("/", 1)[1][:-4] == "")
                and not (manifest_file_url.rsplit("/", 1)[1][:-4] is None)):
            print(manifest_file_url.rsplit("/", 1)[1][:-4])
            return
        export_file = export_annotation_root + manifest_file_url.rsplit(
            "/", 1)[1][:-4] + '_freehand_annotation.zip'
        if os.path.exists(export_file):
            os.remove(export_file)

        export_path = export_annotation_root + manifest_file_url.rsplit(
            "/", 1)[1][:-4] + '/freehand_annotation/'
        if os.path.exists(export_path):
            shutil.rmtree(export_path)
        elif not os.path.exists(export_annotation_root +
                                manifest_file_url.rsplit("/", 1)[1][:-4]):
            os.mkdir(export_annotation_root +
                     manifest_file_url.rsplit("/", 1)[1][:-4])
        os.mkdir(export_path)

    annotator_no = 6
    for annotator_id in range(annotator_no):
        os.mkdir(export_path + 'a' + str(annotator_id + 1) + '/')

    down = 4
    down_save = 32
    wsi_count = 1
    # print(manifest_txt)
    for wsi in manifest_txt:
        print(wsi)
        print(
            time.asctime(time.localtime(time.time())),
            "start export freehand annotation:" + str(wsi_count) + '/' +
            str(len(manifest_txt)))
        wsi_count += 1
        info = wsi.split('\t')
        if not os.path.exists(annotation_project_root + info[0] + '/'):
            continue
        dimensions = None
        for annotator_id in range(annotator_no):
            if os.path.exists(annotation_project_root + info[0] + '/' +
                              'a' + str(annotator_id + 1) + '.db') and \
                    len(freehand_annotation_sqlite.SqliteConnector(annotation_project_root + info[0] + '/' +
                                        'a' + str(annotator_id + 1) + '.db').get_lines()) > 0:
                if not dimensions:
                    try:
                        dimensions = openslide.open_slide(original_data_root +
                                                          info[0] + '/' +
                                                          info[1]).dimensions
                    except Exception as e:
                        print('Error:', e)
                        continue

                img_height = dimensions[1]
                img_width = dimensions[0]

                if not os.path.exists(export_path + 'a' +
                                      str(annotator_id + 1) + '/' +
                                      'Background'):
                    os.mkdir(export_path + 'a' + str(annotator_id + 1) + '/' +
                             'Background')

                oslide = openslide.OpenSlide(original_data_root + info[0] +
                                             '/' + info[1])
                level = oslide.get_best_level_for_downsample(16)
                reading_size = [
                    int(img_width / oslide.level_downsamples[level]),
                    int(img_height / oslide.level_downsamples[level])
                ]
                try:
                    mask = oslide.read_region((0, 0), level, reading_size)
                except Exception as e:
                    print('Error:', e)
                    continue

                mask = numpy.array(mask)
                mask = cv2.resize(mask,
                                  (int(img_width / 16), int(img_height / 16)))
                r, g, b, a = cv2.split(mask)
                mask = cv2.merge([r, g, b])

                mask = cv2.cvtColor(mask, cv2.COLOR_RGB2GRAY)
                mask = cv2.GaussianBlur(mask, (61, 61), 0)
                ret, mask = cv2.threshold(mask, 0, 255,
                                          cv2.THRESH_BINARY + cv2.THRESH_OTSU)
                write_url = export_path + 'a' + str(annotator_id + 1) + '/' + 'Background' + '/' \
                            + info[0] + '.png'
                mask = cv2.resize(
                    mask,
                    (int(img_width / down_save), int(img_height / down_save)))
                cv2.imwrite(write_url, mask)
                oslide.close()

                db = freehand_annotation_sqlite.SqliteConnector(
                    annotation_project_root + info[0] + '/' + 'a' +
                    str(annotator_id + 1) + '.db')
                for grade in range(1, 5):
                    mask = numpy.zeros(
                        [int(img_height / down),
                         int(img_width / down), 1], numpy.uint8)
                    if not os.path.exists(export_path + 'a' +
                                          str(annotator_id + 1) + '/' +
                                          'Grade' + str(grade)):
                        os.mkdir(export_path + 'a' + str(annotator_id + 1) +
                                 '/' + 'Grade' + str(grade))

                    for temp in db.get_lines():
                        if temp[5] != grade:
                            continue
                        if temp[1] < down_save:
                            temp1 = down_save
                        elif temp[1] >= img_width - down_save:
                            temp1 = img_width - down_save
                        else:
                            temp1 = temp[1]

                        if temp[2] < down_save:
                            temp2 = down_save
                        elif temp[2] >= img_height - down_save:
                            temp2 = img_height - down_save
                        else:
                            temp2 = temp[2]

                        if temp[3] < down_save:
                            temp3 = down_save
                        elif temp[3] >= img_width - down_save:
                            temp3 = img_width - down_save
                        else:
                            temp3 = temp[3]

                        if temp[4] < down_save:
                            temp4 = down_save
                        elif temp[4] >= img_height - down_save:
                            temp4 = img_height - down_save
                        else:
                            temp4 = temp[4]

                        cv2.line(mask, (int(temp1 / down), int(temp2 / down)),
                                 (int(temp3 / down), int(temp4 / down)), 255,
                                 4)
                    # kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
                    # mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel)

                    # contours, hierarchy = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
                    # cv2.drawContours(mask, contours, -1, 255, -1)
                    #
                    # mask_new = mask.copy()
                    # contours_new, hierarchy_new = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
                    # cv2.drawContours(mask_new, contours_new, -1, 255, -1)
                    #
                    # while not (mask_new == mask).all():
                    #     mask = mask_new.copy()
                    #     contours_new, hierarchy_new = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
                    #     cv2.drawContours(mask_new, contours_new, -1, 255, -1)
                    #
                    # mask = mask_new.copy()

                    contours, hierarchy = cv2.findContours(
                        mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
                    mask = numpy.zeros(
                        [int(img_height / down),
                         int(img_width / down), 1], numpy.uint8)
                    # print(hierarchy)
                    for index in range(len(contours)):
                        if hierarchy[0][index][3] != -1:
                            cv2.drawContours(mask, contours, index, 255, -1)

                    # kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
                    # mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel)

                    write_url = export_path + 'a' + str(annotator_id + 1) + '/' + 'Grade' + str(grade) + '/' \
                                + info[0] + '.png'
                    mask = cv2.resize(mask, (int(
                        img_width / down_save), int(img_height / down_save)))
                    cv2.imwrite(write_url, mask)

                contours_list = []
                for grade in range(1, 5):
                    temp = cv2.imread(export_path + 'a' + str(annotator_id + 1) + '/' + 'Grade' + str(grade) + '/' \
                                      + info[0] + '.png', 0)
                    contours, hierarchy = cv2.findContours(
                        temp, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
                    contours_list.append(contours)

                mask = numpy.zeros([
                    int(img_height / down_save),
                    int(img_width / down_save), 3
                ], numpy.uint8)

                color = [(0, 0, 255), (0, 255, 0), (255, 0, 0), (0, 0, 0)]
                for loop_times in range(5):
                    for grade in range(4):
                        contours_temp = contours_list[grade].copy()
                        for index in range(len(contours_temp)):
                            mask_new = mask.copy()
                            cv2.drawContours(mask_new, contours_temp, index,
                                             color[grade], 1)
                            if not (mask_new == mask).all():
                                cv2.drawContours(mask_new, contours_temp,
                                                 index, color[grade], -1)
                                mask = mask_new.copy()
                            else:
                                for i in range(len(contours_list[grade])):
                                    try:
                                        if ((contours_list[grade][i]) == (
                                                contours_temp[index])).all():
                                            contours_list[grade].pop(i)
                                            break
                                    except:
                                        if (contours_list[grade][i]) == (
                                                contours_temp[index]):
                                            contours_list[grade].pop(i)
                                            break
                if not os.path.exists(export_path + 'a' +
                                      str(annotator_id + 1) + '/' + 'summary'):
                    os.mkdir(export_path + 'a' + str(annotator_id + 1) + '/' +
                             'summary')
                write_url = export_path + 'a' + str(annotator_id + 1) + '/' + 'summary' + '/' \
                            + info[0] + '.png'
                cv2.imwrite(write_url, mask)

    annotator_no = 6
    for annotator_id in range(annotator_no):
        if not os.listdir(export_path + 'a' + str(annotator_id + 1)):
            shutil.rmtree(export_path + 'a' + str(annotator_id + 1))
    if os.listdir(export_path):
        make_archive_threadsafe(export_file, export_path)
    return export_file
Exemple #6
0
def print_logs(project=""):
    # project = request.args.get('project', default="", type=str)
    if project == "":
        abort(404)
    else:
        data = []
        count = 0
        if os.path.exists('export/' + project + '_slide_table.txt'):
            for wsi in open('export/' + project +
                            '_slide_table.txt').readlines():
                slide_id = int(wsi.split('\t')[0])
                temp = {
                    "id": slide_id,
                    "text": wsi.replace('\t', ' ').replace('\n', '')
                }
                data.append(temp)

    def takeSecond(elem):
        return elem["id"]

    for index in range(len(data)):
        nuclei_annotation_root = "Data/nuclei_annotation_data/"
        annotation_project_root = nuclei_annotation_root + project + '/'
        # if not os.path.exists(annotation_project_root + data[index]["text"].split(" ")[1] + '/'):
        #     continue
        tba_list_db = annotation_project_root + data[index]["text"].split(
            " ")[1] + '/' + 'tba_list.db'
        if not os.path.exists(tba_list_db):
            data[index]["text"] += " 0 0 0 0 0 0 0"
            continue
        db = nuclei_annotation_sqlite.SqliteConnector(tba_list_db)
        tba_result = db.get_RegionID_Centre()
        data[index]["text"] += " " + str(len(tba_result))
        for annotator_id in range(1, 7):
            annotated = 0
            for item in tba_result:
                if os.path.exists(annotation_project_root + data[index]["text"].split(" ")[1] + '/' +
                                  'a' + str(annotator_id) + '_r' + str(item[0]) + "_annotation.txt") and \
                        sum(numpy.loadtxt(annotation_project_root + data[index]["text"].split(" ")[1] + '/' +
                                          'a' + str(annotator_id) + '_r' + str(item[0]) + "_annotation.txt")) > 0:
                    annotated += 1
            data[index]["text"] += " " + str(annotated)

    for index in range(len(data)):
        for annotator_id in range(1, 7):
            nuclei_annotation_root = "Data/freehand_annotation_data/"
            annotation_project_root = nuclei_annotation_root + project + '/'
            if not os.path.exists(annotation_project_root +
                                  data[index]["text"].split(" ")[1] + '/'):
                data[index]["text"] += " 0"
                continue
            if os.path.exists(annotation_project_root + data[index]["text"].split(" ")[1] + '/' +
                              'a' + str(annotator_id) + '.db') and \
                    len(freehand_annotation_sqlite.SqliteConnector(annotation_project_root +
                                                                   data[index]["text"].split(" ")[1] + '/' +
                                                                   'a' + str(annotator_id) + '.db').get_lines()) > 0:
                data[index]["text"] += " 1"
            else:
                data[index]["text"] += " 0"

    data.sort(key=takeSecond)
    for index in range(len(data)):
        count += 1
        data[index]["text"] = str(count) + " " + data[index]["text"]
    output = "ID SlideID UUID SVS_File " \
             "NucleiTotal Nuclei1 Nuclei2 Nuclei3 Nuclei4 Nuclei5 Nuclei6 " \
             "Freehand1 Freehand2 Freehand3 Freehand4 Freehand5 Freehand6\n"
    for index in range(len(data)):
        output += data[index]["text"] + '\n'
    return Response(output, mimetype='text/plain')