File size: 7,513 Bytes
8fb99cf
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
import numpy as np
import cv2
def calculate_sr_hw_split_ratio(
    HB_m_offset_list, HB_n_offset_list, 
    HB_m_scale_list, HB_n_scale_list
):
    """
    Calculate SR_hw_split_ratio without overlapping regions.

    Args:
        HB_m_offset_list (List[float]): Offsets of bounding boxes in the horizontal dimension.
        HB_n_offset_list (List[float]): Offsets of bounding boxes in the vertical dimension.
        HB_m_scale_list (List[float]): Scales of bounding boxes in the horizontal dimension.
        HB_n_scale_list (List[float]): Scales of bounding boxes in the vertical dimension.

    Returns:
        str: SR_hw_split_ratio based on the condition checks.
    """
    def has_overlap(offset_list, scale_list):
        """
        Check if any boxes in the given dimension overlap.

        Args:
            offset_list (List[float]): Offsets of bounding boxes in the dimension.
            scale_list (List[float]): Scales of bounding boxes in the dimension.

        Returns:
            bool: True if there is overlap, False otherwise.
        """
        for i in range(len(offset_list)):
            for j in range(i + 1, len(offset_list)):
                if not (offset_list[i] + scale_list[i] <= offset_list[j] or
                        offset_list[j] + scale_list[j] <= offset_list[i]):
                    return True
        return False

    def redistribute_regions(offset_list, scale_list):
        """
        Redistribute the regions to ensure no overlap and full coverage.

        Args:
            offset_list (List[float]): Offsets of bounding boxes.
            scale_list (List[float]): Scales of bounding boxes.

        Returns:
            List[float]: Adjusted proportions for each region.
        """
        adjusted_ratios = []

        for i in range(len(offset_list)):
            if i == 0:
                split_ratio = offset_list[i] + scale_list[i] + (offset_list[i + 1] - offset_list[i] - scale_list[i]) / 2
                adjusted_ratios.append(split_ratio)
            elif i+1 < len(offset_list):
                mid_point = offset_list[i] + scale_list[i] + (offset_list[i + 1] - offset_list[i] - scale_list[i]) / 2
                region_ratio = mid_point - sum(adjusted_ratios)
                adjusted_ratios.append(region_ratio)
            else:
                final_ratio = 1.0 - sum(adjusted_ratios)
                adjusted_ratios.append(final_ratio)

        normalized_ratios = [ratio / sum(adjusted_ratios) for ratio in adjusted_ratios]

        return normalized_ratios

    def generate_regions(adjusted_ratios, separator):
        """
        Generate normalized regions as a string.

        Args:
            adjusted_ratios (List[float]): Adjusted proportions for each region.
            separator (str): Separator for the output string.

        Returns:
            str: Normalized regions as a string.
        """
        return separator.join(f"{region:.2f}" for region in adjusted_ratios)

    # Check for overlaps
    vertical_overlap = has_overlap(HB_m_offset_list, HB_m_scale_list)
    horizontal_overlap = has_overlap(HB_n_offset_list, HB_n_scale_list)

    # Determine which SR_hw_split_ratio to return
    if not vertical_overlap and horizontal_overlap:
        adjusted_ratios = redistribute_regions(HB_m_offset_list, HB_m_scale_list)
        return generate_regions(adjusted_ratios, ",")
    elif vertical_overlap and not horizontal_overlap:
        adjusted_ratios = redistribute_regions(HB_n_offset_list, HB_n_scale_list)
        return generate_regions(adjusted_ratios, ";")
    elif not vertical_overlap and not horizontal_overlap:
        adjusted_ratios = redistribute_regions(HB_m_offset_list, HB_m_scale_list)
        return generate_regions(adjusted_ratios, ",")
    else:
        raise ValueError("Invalid condition: Both dimensions either overlap or do not overlap.")


def generate_parameters(bbox_inputs, prompt_width, prompt_height):
    """
    Converts bbox_inputs to offset and scale lists for HB format.
    
    Args:
        bbox_inputs (List[List[int]]): List of bounding boxes, each defined by [x1, y1, x2, y2].
        prompt_width (int): Width of the entire image.
        prompt_height (int): Height of the entire image.
    
    Returns:
        Tuple[List[float], List[float], List[float], List[float]]: 
            HB_m_offset_list, HB_n_offset_list, HB_m_scale_list, HB_n_scale_list.
    """
    HB_m_offset_list = [box[0] / prompt_width for box in bbox_inputs]
    HB_n_offset_list = [box[1] / prompt_height for box in bbox_inputs]
    HB_m_scale_list = [(box[2] - box[0]) / prompt_width for box in bbox_inputs]
    HB_n_scale_list = [(box[3] - box[1]) / prompt_height for box in bbox_inputs]

    SR_hw_split_ratio = calculate_sr_hw_split_ratio(HB_m_offset_list, HB_n_offset_list, HB_m_scale_list, HB_n_scale_list)
    

    return HB_m_offset_list, HB_n_offset_list, HB_m_scale_list, HB_n_scale_list, SR_hw_split_ratio


def visualize(HB_m_offset_list, HB_n_offset_list, HB_m_scale_list, HB_n_scale_list, SR_hw_split_ratio, prompt_width, prompt_height):
    # 创建一个白色背景的图像
    image = np.ones((prompt_height, prompt_width, 3), dtype=np.uint8) * 255

    for m_offset, n_offset, m_scale, n_scale in zip(HB_m_offset_list, HB_n_offset_list, HB_m_scale_list, HB_n_scale_list):
        x = int(m_offset * prompt_width)
        y = int(n_offset * prompt_height)
        width = int(m_scale * prompt_width)
        height = int(n_scale * prompt_height)
        # 绘制边界框
        cv2.rectangle(image, (x, y), (x + width, y + height), (255, 0, 0), 2)

    if ',' in SR_hw_split_ratio:
        split_ratios = [float(ratio) for ratio in SR_hw_split_ratio.split(',')]
        orientation = 'vertical'
    elif ';' in SR_hw_split_ratio:
        split_ratios = [float(ratio) for ratio in SR_hw_split_ratio.split(';')]
        orientation = 'horizontal'
    else:
        split_ratios = [float(SR_hw_split_ratio)]
        orientation = 'horizontal'

    colors = [(0, 0, 255), (0, 255, 0), (255, 255, 0), (125, 125, 0), (255, 0, 255),(0, 125, 255), (125, 255, 0), (255, 255, 125), (125, 0, 0), (125, 0, 255)]
    current_pos = 0

    if orientation == 'vertical':
        total_length = prompt_width
        for i, ratio in enumerate(split_ratios):
            region_width = int(ratio * total_length)
            # 绘制分割区域
            cv2.rectangle(image, (current_pos, 0), (current_pos + region_width, prompt_height), colors[i % len(colors)], 2)
            current_pos += region_width
    else:
        total_length = prompt_height
        for i, ratio in enumerate(split_ratios):
            region_height = int(ratio * total_length)
            # 绘制分割区域
            cv2.rectangle(image, (0, current_pos), (prompt_width, current_pos + region_height), colors[i % len(colors)], 2)
            current_pos += region_height

    return image


if __name__ == "__main__":
    bbox_inputs = [[5, 20, 100, 150], [160, 20, 190, 210], [230,5,290,290]]
    # bbox_inputs = [[40, 5, 210, 160], [100, 180, 180, 270]]
    prompt_width = 300
    prompt_height = 300

    HB_m_offset_list, HB_n_offset_list, HB_m_scale_list, HB_n_scale_list,SR_hw_split_ratio = generate_parameters(bbox_inputs, prompt_width, prompt_height)

    print("HB_m_offset_list:", HB_m_offset_list)
    print("HB_n_offset_list:", HB_n_offset_list)
    print("HB_m_scale_list:", HB_m_scale_list)
    print("HB_n_scale_list:", HB_n_scale_list)
    print("SR_hw_split_ratio:",SR_hw_split_ratio)