Пример #1
0
    def generate_chromosome_cluster(karyotyping_image,
                                    save_dir=None,
                                    popup=None):
        chromosome_size = 256
        chromosomes = data_utils.process_karyotyping_image(karyotyping_image,
                                                           verbose=True)
        chromosome_cluster = 255 - np.zeros(
            shape=(chromosome_size * 7, chromosome_size * 7, 3), dtype='uint8')

        i, j = 0, 0
        for chromosome in chromosomes:
            chromosome = cv2.resize(chromosome, (256, 256))
            chromosome_cluster[i * chromosome_size: (i + 1) * chromosome_size, j * chromosome_size: (j + 1) * chromosome_size] = \
                chromosome[0:chromosome_size, 0:chromosome_size]

            # this is equivalent to 2 for-loops
            j += 1
            i += int(j / 7)
            j = j % 7

        if save_dir is not None:
            general_utils.create_directory(save_dir)
            cv2.imwrite(save_dir + "/chromosome_cluster.bmp",
                        chromosome_cluster)

        return chromosome_cluster
Пример #2
0
    def run(image_file, save_dir, model_path):
        general_utils.create_directory(save_dir + "/pipeline")

        image = Pipeline.read_image(image_file)

        image = Pipeline.generate_chromosome_cluster(
            image,
            save_dir=save_dir + "/pipeline/1_generate_chromosome_cluster")

        chromosomes = Pipeline.extract_chromosomes(
            image, save_dir=save_dir + "/pipeline/2_extract_chromosomes")

        straightened_chromosomes = Pipeline.straighten_chromosomes(
            chromosomes,
            save_dir=save_dir + "/pipeline/3_straighten_chromosomes")

        interesting_points = Pipeline.detect_interesting_points(
            straightened_chromosomes,
            save_dir=save_dir + "/pipeline/4_detect_interesting_points",
            model_path=model_path)

        classified_chromosomes = Pipeline.classify_chromosomes(
            straightened_chromosomes, interesting_points)

        karyotyping_image = Pipeline.organize_chromosomes(
            classified_chromosomes,
            save_dir=save_dir + "/pipeline/5_organize_chromosomes")

        return karyotyping_image
Пример #3
0
def image_files_to_bounding_box_csv(image_files,
                                    labels,
                                    csv_dir,
                                    prefix="",
                                    verbose=False):
    general_utils.create_directory(csv_dir)

    boxes = list()
    for image_file in image_files:
        image = image_utils.read_image(image_file, cmap="rgb")
        box = image_utils.get_chromosome_bounding_box(image)
        boxes.append(box)

    train_data, val_data, test_data = data_utils.split_multiple_data_lists(
        [image_files, boxes, labels])

    annotations_train_file = csv_dir + "/" + prefix + "annotations_train.csv"
    image_and_bounding_boxes_to_csv(*train_data, annotations_train_file)

    annotations_val_file = csv_dir + "/" + prefix + "annotations_val.csv"
    image_and_bounding_boxes_to_csv(*val_data, annotations_val_file)

    annotations_test_file = csv_dir + "/" + prefix + "annotations_test.csv"
    image_and_bounding_boxes_to_csv(*test_data, annotations_test_file)

    class_mapping = [[str(i), i] for i in range(len(labels))]
    class_mapping_file = csv_dir + "/" + prefix + "class_mapping.csv"
    general_utils.write_list_to_csv(class_mapping, class_mapping_file)

    if verbose:
        print("Train: ", annotations_train_file)
        print("Validation: ", annotations_val_file)
        print("Test: ", annotations_test_file)
        print("Class mapping:", class_mapping_file)
Пример #4
0
    def extract_chromosomes(image, save_dir=None, popup=None):
        chromosomes = data_utils.process_karyotyping_image(image)

        if save_dir is not None:
            general_utils.create_directory(save_dir)
            for idx in range(len(chromosomes)):
                cv2.imwrite(save_dir + "/" + str(idx + 1) + ".bmp",
                            chromosomes[idx])

        return chromosomes
Пример #5
0
    def straighten_chromosomes(chromosomes, save_dir=None, popup=None):
        num_chromosome = len(chromosomes)
        """ Handle popup """
        popup_counter = 1
        if popup is not None:
            popup.set_text("0/" + str(num_chromosome) +
                           " chromosomes processed.")

        straightened_chromosomes = list()
        for idx in range(num_chromosome):
            chromosome = chromosomes[idx].copy()
            gray = cv2.cvtColor(chromosome, cv2.COLOR_RGB2GRAY)
            _, binary = cv2.threshold(gray, 254, 255, cv2.THRESH_BINARY_INV)

            # get 2 end points of the best line
            x1, y1, x2, y2 = image_utils.find_best_line_hough_transform(binary)

            # make the first point higher than the second point
            if y1 > y2:
                x1, x2 = math_utils.swap(x1, x2)
                y1, y2 = math_utils.swap(y1, y2)

            angle = math_utils.get_angle_between_two_points([x1, y1], [x2, y2])

            straightened_chromosome = image_utils.rotate_image(
                chromosome, angle + 90)

            if save_dir is not None:
                general_utils.create_directory(save_dir)

                chromosome_with_line = cv2.line(chromosome.copy(), (x1, y1),
                                                (x2, y2), (0, 255, 0), 2)
                straightened_line = image_utils.rotate_points(
                    [[x1, y1], [x2, y2]], angle + 90, shape=chromosome.shape)
                rotated_x1, rotated_y1 = straightened_line[0]
                rotated_x2, rotated_y2 = straightened_line[1]
                straightened_chromosome_with_line = cv2.line(
                    straightened_chromosome.copy(), (rotated_x1, rotated_y1),
                    (rotated_x2, rotated_y2), (0, 255, 0), 2)
                """ Save images """
                cv2.imwrite(save_dir + "/" + str(idx) + ".bmp",
                            chromosome_with_line)
                cv2.imwrite(save_dir + "/" + str(idx) + "_straightened.bmp",
                            straightened_chromosome_with_line)

            straightened_chromosomes.append(straightened_chromosome)
            """ Handle popup """
            if popup is not None:
                popup.set_text(
                    str(popup_counter) + "/" + str(num_chromosome) +
                    " chromosomes processed.")
                popup_counter += 1

        return straightened_chromosomes
Пример #6
0
    def organize_chromosomes(chromosomes, debug=False, save_dir=None):
        template = 255 - np.zeros(shape=(800, 2048, 3), dtype='uint8')
        blocks = {
            "1": [0, 0, 256, 200],
            "2": [256, 0, 512, 200],
            "3": [512, 0, 768, 200],
            "4": [1536, 0, 1792, 200],
            "5": [1792, 0, 2048, 200],
            "6": [0, 200, 256, 400],
            "7": [256, 200, 512, 400],
            "8": [512, 200, 768, 400],
            "9": [768, 200, 1024, 400],
            "10": [1024, 200, 1280, 400],
            "11": [1280, 200, 1536, 400],
            "12": [1536, 200, 1792, 400],
            "13": [0, 400, 256, 600],
            "14": [256, 400, 512, 600],
            "15": [512, 400, 768, 600],
            "16": [1280, 400, 1536, 600],
            "17": [1536, 400, 1792, 600],
            "18": [1792, 400, 2048, 600],
            "19": [0, 600, 256, 800],
            "20": [256, 600, 512, 800],
            "21": [768, 600, 1024, 800],
            "22": [1024, 600, 1280, 800],
            "x": [1536, 600, 1792, 800],
            "y": [1792, 600, 2048, 800],
        }

        chromosome_ids = [
            "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12",
            "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "x",
            "y"
        ]

        for idx in chromosome_ids:
            x1, y1, x2, y2 = blocks[idx]
            block_image = image_utils.get_block_image(chromosomes[idx],
                                                      idx,
                                                      shape=(200, 256, 3))
            template[y1:y2, x1:x2] = block_image
            if debug:
                image_utils.get_block_image(chromosomes[idx],
                                            idx,
                                            shape=(200, 256, 3))

        if save_dir is not None:
            general_utils.create_directory(save_dir)
            cv2.imwrite(save_dir + "/karyotyping.bmp", template)

        return template
Пример #7
0
    def classify_chromosomes(chromosomes, points, save_dir=None, popup=None):
        """
        This function randomly classifies chromosomes.

        :param chromosomes:
        :param points:
        :param save_dir:
        :param popup:
        :return:
        """

        # TODO: Remove this in the future
        if chromosomes is None:
            print("No chromosomes. Return None.")
            return None
        """ Default chromosome ids """
        chromosome_ids = [
            "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12",
            "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "x",
            "y"
        ]
        """ Duplicate chromosomes ids (because of having 2 chromosomes/id, 'x' and 'y' excepted) and shuffle all """
        all_chromosome_ids = chromosome_ids + chromosome_ids
        all_chromosome_ids.remove("x")
        all_chromosome_ids.remove("y")

        from random import shuffle
        shuffle(all_chromosome_ids)
        """ Put chromosomes to ids """
        classified_chromosomes = dict()
        for i in range(len(chromosomes)):
            idx = all_chromosome_ids[i]
            if idx not in classified_chromosomes:
                classified_chromosomes[idx] = [chromosomes[i]]
            else:
                classified_chromosomes[idx].append(chromosomes[i])

        if save_dir is not None:
            counter = 0
            general_utils.create_directory(save_dir)
            for idx in chromosome_ids:
                for chromosome in classified_chromosomes[idx]:
                    cv2.imwrite(save_dir + "/" + str(counter) + ".bmp",
                                chromosome)
                    counter += 1

        return classified_chromosomes
Пример #8
0
    def detect_interesting_points(chromosomes,
                                  model_path="default",
                                  verbose=False,
                                  save_dir=None,
                                  popup=None):
        """ Local import """
        from script.pipeline.detection import detect_interesting_points, load_model

        interesting_points = list()
        model = load_model(model_path=model_path)
        for idx in range(len(chromosomes)):
            chromosome = chromosomes[idx]
            points, draw, image_with_points = detect_interesting_points(
                chromosome, model, verbose=verbose)

            if save_dir is not None:
                general_utils.create_directory(save_dir)
                cv2.imwrite(save_dir + "/" + str(idx + 1) + "_draw.bmp", draw)
                cv2.imwrite(save_dir + "/" + str(idx + 1) + "_points.bmp",
                            image_with_points)

            interesting_points.append(points)

        return interesting_points
Пример #9
0
def process_karyotyping_images(directory,
                               chromosome_type="xx",
                               debug=False,
                               load_karyotype_info=False,
                               max_p=None,
                               need_confirm=False):
    last_chromosome = chromosome_type[1]
    chromosome_ids = [
        1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
        21, 22, "x", "y"
    ]
    save_directory = directory + "/" + chromosome_type + "/chromosome"
    karyotype_directory = directory + "/" + chromosome_type

    if debug:
        print("Save directory: " + save_directory)
        print("Karyotype directory: " + karyotype_directory)

    general_utils.create_directory(save_directory)

    if not load_karyotype_info:
        # Create directories to store output images
        for idx in chromosome_ids:
            general_utils.create_directory(save_directory + "/" + str(idx))

        karyotypes = dict()
        image_files = general_utils.get_all_files(karyotype_directory)

        for image_file in image_files:
            if not image_file.endswith(".bmp"):
                continue
            if debug:
                print(image_file)

            image = cv2.imread(karyotype_directory + "/" + image_file, 0)
            # ret, thresh = threshold.partial_otsu_threshold(image, minval=0, maxval=255, dark_background=False)
            ret, thresh = cv2.threshold(image, 254, 255, cv2.THRESH_BINARY_INV)
            # if debug:
            #     image_utils.show_image(thresh)

            _, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE,
                                                      cv2.CHAIN_APPROX_SIMPLE)

            num_contour = len(contours)

            # Find area threshold - taking the 46-th largest area
            areas = list()
            for idx in range(num_contour):
                is_outer_contour = hierarchy[0][idx][3] == -1
                if is_outer_contour:
                    area = cv2.contourArea(contours[idx])
                    areas.append(area)
            areas.sort(reverse=True)
            if len(areas) < 46:
                print("Wrong at " + image_file)
                continue
            area_threshold = areas[45] - 0.01

            chosen_contours = list()
            for idx in range(num_contour):
                contour = contours[idx]
                if cv2.contourArea(contour) < area_threshold:
                    continue
                chosen_contours.append(contour)

            if len(chosen_contours) < 46:
                print("Wrong at " + image_file)
                continue

            contour_info = list()
            for contour in chosen_contours:
                x, y, w, h = cv2.boundingRect(contour)
                contour_info.append([x, y, w, h, contour])

            def sorted_by(a, b):
                x_a, y_a, w_a, h_a, _ = a
                x_b, y_b, w_b, h_b, _ = b
                if (y_a + h_a) < y_b:
                    return -1
                if x_a < x_b:
                    return -1
                return 1

            cmp = functools.cmp_to_key(sorted_by)
            contour_info.sort(key=cmp)

            if need_confirm:
                rgb_image = np.stack((image, ) * 3, axis=-1)
                image_utils.show_image(image_utils.get_image_with_contours(
                    rgb_image, chosen_contours, thickness=-1),
                                       cmap=None)
                user_input = input()
                if "yes".startswith(user_input):
                    karyotypes[image_file] = contour_info
                else:
                    print("Skipping: " + image_file)
            else:
                rgb_image = np.stack((image, ) * 3, axis=-1)
                image_utils.show_image(image_utils.get_image_with_contours(
                    rgb_image, chosen_contours, thickness=-1),
                                       cmap=None)
                karyotypes[image_file] = contour_info

        # Save data in case of bugs
        pickle.dump(
            karyotypes,
            open(directory + "/" + chromosome_type + "_karyotype_info.data",
                 'wb'))
    else:
        with open(directory + "/" + chromosome_type + "_karyotype_info.data",
                  'rb') as f:
            karyotypes = pickle.load(f)

    # Find maximum perimeter
    if max_p is None:
        max_p = -1
        for idx in karyotypes.keys():
            contour_info = karyotypes[idx]

            if len(contour_info) != 46:
                print("Skipping:" + idx)
                continue

            con_1 = contour_info[0][4]
            con_2 = contour_info[1][4]
            p_1 = cv2.arcLength(con_1, True)
            p_2 = cv2.arcLength(con_2, True)
            max_p = max(p_1, max_p)
            max_p = max(p_2, max_p)

    if debug:
        print("Max p: " + str(max_p))

    # Resize all images according to max perimeter
    for image_file in karyotypes.keys():
        image = cv2.imread(karyotype_directory + "/" + image_file, 0)
        contour_info = karyotypes[image_file]
        if debug:
            print(image_file)

        if len(contour_info) != 46:
            print("Skipping:" + image_file)
            continue

        # Get max perimeter of two chromosome 1
        con_1 = contour_info[0][4]
        con_2 = contour_info[1][4]
        p_1 = cv2.arcLength(con_1, True)
        p_2 = cv2.arcLength(con_2, True)
        local_max_p = max(p_1, p_2)

        # Get scale according to above local max
        scale = max_p * 1.0 / local_max_p
        print(scale)

        component_size = 512
        counter = 1
        pixel_open = 0

        for idx in range(len(contour_info)):
            x, y, w, h, contour = contour_info[idx]

            # open the bounding box a little bit
            x -= pixel_open
            y -= pixel_open
            w += pixel_open
            h += pixel_open

            # create a white image of size 512
            white_image = 255 - np.zeros(shape=(component_size,
                                                component_size))

            # calculate corresponding top-left point in white image
            new_x = int((component_size - w) / 2)
            new_y = int((component_size - h) / 2)

            # copy bounding box patch from karyotype image into white image
            white_image[new_y:(new_y + h),
                        new_x:(new_x + w)] = image[y:(y + h), x:(x + w)]

            # rescale chromosome image
            white_image = cv2.resize(
                white_image,
                (int(component_size * scale), int(component_size * scale)))
            white_image = white_image.astype('uint8')

            # get the center patch of size 512
            white_image = image_utils.get_center_sub_image(white_image,
                                                           size=component_size)

            # get current chromosome name (1, 2, ..., x, y)
            chromosome_name = str(chromosome_ids[int(idx / 2)])
            # the last chromosome name depends on what karyotype image (xx or xy)
            if idx == 45:
                chromosome_name = last_chromosome

            # save the patch contain only 1 chromosome
            cv2.imwrite(
                save_directory + "/" + chromosome_name + "/" +
                chromosome_type + "_" + image_file + "_" + str(idx),
                white_image)
            counter += 1