File size: 5,634 Bytes
54cb6c5
8cc93d2
54cb6c5
 
db4d0c4
54cb6c5
d4675c1
54cb6c5
 
7fef374
 
 
d2ae102
 
 
 
 
 
7fef374
 
 
54cb6c5
 
7fef374
 
54cb6c5
 
 
db4d0c4
54cb6c5
 
7fef374
 
 
54cb6c5
 
7fef374
54cb6c5
 
7fef374
 
 
54cb6c5
 
 
 
 
 
d6f71e3
54cb6c5
d4675c1
 
54cb6c5
d4675c1
 
 
 
 
 
 
 
 
 
 
 
 
54cb6c5
 
 
8cc93d2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d2ae102
 
 
 
 
 
 
 
 
8cc93d2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
dc882c7
 
8cc93d2
 
dc882c7
8cc93d2
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
import cv2 as cv
import numpy as np

from .config import default_config
from .simplify_image import simplify_image, downsample_image
from .gen_islands import GenerateIslands
from .numbered_islands import create_islands, add_numbers_to_image

class ColorByNumber:
    def __init__(self, image_path, 
                 color_list = None, num_colors = None,
                 config = default_config):
        """
        Args:
            image_path: Path to the image file.
            color_list: List of colors in (R, G, B) format.
            config: Dictionary of configuration parameters (optional).
        """
        assert color_list is not None or num_colors is not None, \
            "Either color_list or num_colors must be provided."

        self.image_path = image_path
        self.config = config
        self.color_list = color_list
        self.num_colors = num_colors

        image = cv.imread(self.image_path)
        image = cv.cvtColor(image, cv.COLOR_BGR2RGB)
        image = downsample_image(image)
        self.image = image

    def create_color_by_number(self):

        simplified_image, indices_color_choices, color_list = simplify_image(
            image=self.image, 
            color_list=self.color_list,
            num_colors=self.num_colors,
            config=self.config
            )
        # Assigning the color_list to the one returned by simplify_image
        # because if it was initially None, it would have been assigned a value.
        self.color_list = color_list
        self.simplified_image = simplified_image

        generate_islands_obj = GenerateIslands(indices_color_choices)
        island_borders_list, centroid_coords_list = generate_islands_obj.get_islands(config=self.config)
        self.generate_islands_obj = generate_islands_obj
        self.island_borders_list = island_borders_list
        self.centroid_coords_list = centroid_coords_list

        # Create the islands image
        self.islands_image = create_islands(
            islands = self.island_borders_list, 
            image_shape = self.image.shape, 
            padding = self.config["border_padding"], 
            border_color = self.config["border_color"]
            )

        # Add numbers to the islands image
        self.numbered_islands = add_numbers_to_image(
            image=self.islands_image,
            centroid_coords_list=self.centroid_coords_list,
            color_id_list=[color_id for color_id, _ in self.island_borders_list],
            font_size=self.config["font_size"],
            font_color=self.config["font_color"],
            font_thickness=self.config["font_thickness"]
            )

        return self.numbered_islands
    
    def generate_color_legend(self,
                            cols=7,
                            rows=None, 
                            square_size=100, 
                            margin=10, 
                            gap_horizontal=5, gap_vertical=30, 
                            font=cv.FONT_HERSHEY_SIMPLEX, 
                            font_size=1, 
                            border_color=(0, 0, 0)
                            ):
        """
        Generates a grid of colored squares with labels below them.

        Args:
            cols: Number of columns in the grid.
            rows: Number of rows in the grid.
            square_size: Size of each square in the grid.
            margin: Margin around the grid.
            gap_horizontal: Horizontal gap between squares.
            gap_vertical: Vertical gap between squares.
            font: Font for the labels.
            font_size: Font size for the labels.
            border_color: Color of the border around each square.
        """

        # Calculate grid dimensions if not provided
        if rows is None and cols is None:
            num_colors = len(self.color_list)
            rows = cols = int(np.sqrt(num_colors)) + 1

        elif rows is None:
            cols = min(cols, len(self.color_list))
            rows = int(np.ceil(len(self.color_list) / cols))

        # Calculate total width and height based on margins, gaps, and squares
        total_width = 2 * margin + (cols + 1) * square_size + (cols - 1) * gap_horizontal
        total_height = 2 * margin + (rows + 1) * square_size + (rows - 1) * gap_vertical

        # Create a white image
        image = np.ones((total_height, total_width, 3), dtype=np.uint8) * 255

        # Fill squares with colors
        for i, color in enumerate(self.color_list):
            row = i // cols
            col = i % cols

            start_col = margin + col * (square_size + gap_horizontal)
            end_col = start_col + square_size

            start_row = margin + row * (square_size + gap_vertical)
            end_row = start_row + square_size

            # Fill square with color
            image[start_row:end_row, start_col:end_col] = color

            # Draw border around that color
            image[start_row, start_col:end_col] = border_color # Top Border
            image[end_row, start_col:end_col] = border_color # Bottom Border
            image[start_row:end_row, start_col] = border_color # Left Border
            image[start_row:end_row, end_col] = border_color # Right Border

            # Draw text label below the square
            text = str(i + 1)
            text_size, _ = cv.getTextSize(text, font, font_size, 1)
            text_row = (end_row + text_size[1]) + 5
            text_col = start_col + (square_size // 2) - (text_size[0] // 2)
            cv.putText(image, text, (text_col, text_row), font, font_size, (0, 0, 0), 1)

        return image