File size: 6,296 Bytes
ca46a75
 
 
 
 
 
 
 
 
 
d5d20be
 
 
ca46a75
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d5d20be
 
 
 
 
ca46a75
d5d20be
 
 
 
 
 
ca46a75
d5d20be
 
 
 
 
ca46a75
d5d20be
 
 
 
 
ca46a75
d5d20be
 
 
 
 
 
ca46a75
d5d20be
 
 
 
 
ca46a75
d5d20be
 
 
 
 
 
 
 
 
ec5a4d3
d5d20be
 
 
 
 
ca46a75
 
d5d20be
ca46a75
d5d20be
 
 
ca46a75
 
 
 
 
 
 
 
 
d5d20be
ca46a75
 
d5d20be
 
 
 
 
 
 
 
ca46a75
 
d5d20be
 
 
 
ca46a75
 
ec5a4d3
 
 
 
ca46a75
ec5a4d3
434720c
d5d20be
 
434720c
 
d5d20be
 
434720c
 
d5d20be
 
929aa8b
 
434720c
d5d20be
434720c
 
d5d20be
 
ca46a75
 
 
d5d20be
434720c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d5d20be
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
177
178
179
#!/usr/bin/env python
# -*- coding: utf-8 -*-
r"""
@DATE: 2024/9/5 21:35
@File: layout_calculator.py
@IDE: pycharm
@Description:
    布局计算器
"""

import cv2.detail
import numpy as np


def judge_layout(
    input_width,
    input_height,
    PHOTO_INTERVAL_W,
    PHOTO_INTERVAL_H,
    LIMIT_BLOCK_W,
    LIMIT_BLOCK_H,
):
    centerBlockHeight_1, centerBlockWidth_1 = (
        input_height,
        input_width,
    )  # 由证件照们组成的一个中心区块(1 代表不转置排列)
    centerBlockHeight_2, centerBlockWidth_2 = (
        input_width,
        input_height,
    )  # 由证件照们组成的一个中心区块(2 代表转置排列)

    # 1.不转置排列的情况下:
    layout_col_no_transpose = 0  # 行
    layout_row_no_transpose = 0  # 列
    for i in range(1, 4):
        centerBlockHeight_temp = input_height * i + PHOTO_INTERVAL_H * (i - 1)
        if centerBlockHeight_temp < LIMIT_BLOCK_H:
            centerBlockHeight_1 = centerBlockHeight_temp
            layout_row_no_transpose = i
        else:
            break
    for j in range(1, 9):
        centerBlockWidth_temp = input_width * j + PHOTO_INTERVAL_W * (j - 1)
        if centerBlockWidth_temp < LIMIT_BLOCK_W:
            centerBlockWidth_1 = centerBlockWidth_temp
            layout_col_no_transpose = j
        else:
            break
    layout_number_no_transpose = layout_row_no_transpose * layout_col_no_transpose

    # 2.转置排列的情况下:
    layout_col_transpose = 0  # 行
    layout_row_transpose = 0  # 列
    for i in range(1, 4):
        centerBlockHeight_temp = input_width * i + PHOTO_INTERVAL_H * (i - 1)
        if centerBlockHeight_temp < LIMIT_BLOCK_H:
            centerBlockHeight_2 = centerBlockHeight_temp
            layout_row_transpose = i
        else:
            break
    for j in range(1, 9):
        centerBlockWidth_temp = input_height * j + PHOTO_INTERVAL_W * (j - 1)
        if centerBlockWidth_temp < LIMIT_BLOCK_W:
            centerBlockWidth_2 = centerBlockWidth_temp
            layout_col_transpose = j
        else:
            break
    layout_number_transpose = layout_row_transpose * layout_col_transpose

    if layout_number_transpose > layout_number_no_transpose:
        layout_mode = (layout_col_transpose, layout_row_transpose, 2)
        return layout_mode, centerBlockWidth_2, centerBlockHeight_2
    else:
        layout_mode = (layout_col_no_transpose, layout_row_no_transpose, 1)
        return layout_mode, centerBlockWidth_1, centerBlockHeight_1


def generate_layout_array(input_height, input_width, LAYOUT_WIDTH=1795, LAYOUT_HEIGHT=1205):
    # 1.基础参数表
    PHOTO_INTERVAL_H = 30  # 证件照与证件照之间的垂直距离
    PHOTO_INTERVAL_W = 30  # 证件照与证件照之间的水平距离
    SIDES_INTERVAL_H = 50  # 证件照与画布边缘的垂直距离
    SIDES_INTERVAL_W = 70  # 证件照与画布边缘的水平距离
    LIMIT_BLOCK_W = LAYOUT_WIDTH - 2 * SIDES_INTERVAL_W
    LIMIT_BLOCK_H = LAYOUT_HEIGHT - 2 * SIDES_INTERVAL_H

    # 2.创建一个 1180x1746 的空白画布
    white_background = np.zeros([LAYOUT_HEIGHT, LAYOUT_WIDTH, 3], np.uint8)
    white_background.fill(255)

    # 3.计算照片的 layout(列、行、横竖朝向),证件照组成的中心区块的分辨率
    layout_mode, centerBlockWidth, centerBlockHeight = judge_layout(
        input_width,
        input_height,
        PHOTO_INTERVAL_W,
        PHOTO_INTERVAL_H,
        LIMIT_BLOCK_W,
        LIMIT_BLOCK_H,
    )
    # 4.开始排列组合
    x11 = (LAYOUT_WIDTH - centerBlockWidth) // 2
    y11 = (LAYOUT_HEIGHT - centerBlockHeight) // 2
    typography_arr = []
    typography_rotate = False
    if layout_mode[2] == 2:
        input_height, input_width = input_width, input_height
        typography_rotate = True

    for j in range(layout_mode[1]):
        for i in range(layout_mode[0]):
            xi = x11 + i * input_width + i * PHOTO_INTERVAL_W
            yi = y11 + j * input_height + j * PHOTO_INTERVAL_H
            typography_arr.append([xi, yi])

    return typography_arr, typography_rotate


def generate_layout_image(
    input_image, typography_arr, typography_rotate, width=295, height=413, 
    crop_line:bool=False,
    LAYOUT_WIDTH=1795, 
    LAYOUT_HEIGHT=1205,
):
  
    # 创建一个白色背景的空白画布
    white_background = np.zeros([LAYOUT_HEIGHT, LAYOUT_WIDTH, 3], np.uint8)
    white_background.fill(255)
    
    # 如果输入图像的高度不等于指定高度,则调整图像大小
    if input_image.shape[0] != height:
        input_image = cv2.resize(input_image, (width, height))
    
    # 如果需要旋转排版,则对图像进行转置和垂直镜像
    if typography_rotate:
        input_image = cv2.transpose(input_image)
        input_image = cv2.flip(input_image, 0)  # 0 表示垂直镜像

        # 交换高度和宽度
        height, width = width, height
    
    # 将图像按照排版数组中的位置放置到白色背景上
    for arr in typography_arr:
        locate_x, locate_y = arr[0], arr[1]
        white_background[locate_y : locate_y + height, locate_x : locate_x + width] = (
            input_image
        )

    if crop_line:
        # 添加裁剪线
        line_color = (200, 200, 200)  # 浅灰色
        line_thickness = 1

        # 初始化裁剪线位置列表
        vertical_lines = []
        horizontal_lines = []

        # 根据排版数组添加裁剪线
        for arr in typography_arr:
            x, y = arr[0], arr[1]
            if x not in vertical_lines:
                vertical_lines.append(x)
            if x + width not in vertical_lines:
                vertical_lines.append(x + width)
            if y not in horizontal_lines:
                horizontal_lines.append(y)
            if y + height not in horizontal_lines:
                horizontal_lines.append(y + height)

        # 绘制垂直裁剪线
        for x in vertical_lines:
            cv2.line(white_background, (x, 0), (x, LAYOUT_HEIGHT), line_color, line_thickness)

        # 绘制水平裁剪线
        for y in horizontal_lines:
            cv2.line(white_background, (0, y), (LAYOUT_WIDTH, y), line_color, line_thickness)

    # 返回排版后的图像
    return white_background