如何使用Python结合PIL、NumPy增大图片中文字之间的间距
你之前的操作仅为整张图片添加了外边框,没有调整文字内部的字间距、行间距。要实现需求,核心是先拆分出图片中的单字符和文字行,再在字符/行之间插入空白背景,具体可以按以下步骤实现:
实现步骤
- 图片二值化预处理
先将图片转为灰度图,设定阈值区分文字(深色像素)和背景(白色像素),方便后续扫描识别文字区域。 - 拆分文字行
逐行扫描整张图片的像素,统计每行的非背景像素总数:
- 总数大于0的行属于文字行,记录所有文字行的上下边界坐标
- 总数为0的行是原有行间距,可以直接过滤掉
- 拆分单个字符
对每一个文字行单独做列方向扫描,统计每列的非背景像素总数:
- 总数大于0的列属于字符区域,记录每个字符的左右边界坐标
- 总数为0的列是原有字间距,可以直接过滤掉
- 重建带自定义间距的新图片
根据你需要的行间距、字间距计算新图片的总尺寸,依次把拆分好的字符按行、按顺序粘贴到新图片的对应位置,字符之间留出自定义宽度的空白,行之间留出自定义高度的空白即可。
可运行示例代码
import numpy as np from PIL import Image # 读取图片并转RGBA格式 img = Image.open("without_space.png").convert("RGBA") np_img = np.array(img) height, width = np_img.shape[:2] # 二值化识别文字像素(非白色判定为文字,可根据实际图片调整阈值) is_text = (np_img[:,:,0] < 250) & (np_img[:,:,1] < 250) & (np_img[:,:,2] < 250) # ---------------------- 拆分文字行 ---------------------- row_text_count = np.sum(is_text, axis=1) text_rows = [] current_row = None for y in range(height): if row_text_count[y] > 0 and current_row is None: current_row = [y] elif row_text_count[y] == 0 and current_row is not None: current_row.append(y) text_rows.append(current_row) current_row = None if current_row is not None: current_row.append(height) text_rows.append(current_row) # ---------------------- 拆分每行的单个字符 ---------------------- all_chars = [] for (y_start, y_end) in text_rows: row_is_text = is_text[y_start:y_end, :] col_text_count = np.sum(row_is_text, axis=0) chars = [] current_char = None for x in range(width): if col_text_count[x] > 0 and current_char is None: current_char = [x] elif col_text_count[x] == 0 and current_char is not None: current_char.append(x) chars.append(current_char) current_char = None if current_char is not None: current_char.append(width) chars.append(current_char) all_chars.append({ "y_range": (y_start, y_end), "chars_x": chars }) # ---------------------- 自定义间距重建图片 ---------------------- char_space = 8 # 自定义字间距,单位:像素 line_space = 15 # 自定义行间距,单位:像素 pad = 20 # 整张图片的外围边距,单位:像素 # 计算新图总尺寸 new_height = pad * 2 + sum([y_end - y_start for (y_start, y_end) in text_rows]) + line_space * (len(text_rows) - 1) max_row_width = max([sum([x_end - x_start for (x_start, x_end) in row["chars_x"]]) + char_space * (len(row["chars_x"]) - 1) for row in all_chars]) new_width = pad * 2 + max_row_width # 新建白色不透明的空白背景图 new_np_img = np.ones((new_height, new_width, 4), dtype=np.uint8) * 255 new_np_img[:,:,3] = 255 # 逐个把字符粘贴到新图的对应位置 current_y = pad for row in all_chars: y_start, y_end = row["y_range"] char_height = y_end - y_start current_x = pad for (x_start, x_end) in row["chars_x"]: char_width = x_end - x_start new_np_img[current_y:current_y+char_height, current_x:current_x+char_width] = np_img[y_start:y_end, x_start:x_end] current_x += char_width + char_space current_y += char_height + line_space # 展示、保存结果 result_img = Image.fromarray(new_np_img) result_img.show() result_img.save("with_space.png")
内容的提问来源于stack exchange,提问作者Kevin
相关产品推荐
相关产品推荐

