1.确定特定字体类型;
2.收集合适的图片作为背景
3.在背景图上填写特定字体的字符内容
1)字体无法确认时怎么办?
方法一:可以将文本行裁剪出来去网站上确认,网站链接:字体识别-在线扫一扫图片找字体-搜字体!
方法二:将文字输入到文档文件中,更换不同的字体,看是否与字体目标匹配;
字体可以去网上下载,也可以在本机查找;本机的字体所在位置:
个人用户字体文件:~/.local/share/fonts
系统字体文件:/usr/share/fonts
字体配置文件:/etc/fonts/
下面是我处理的代码,仅供参考:
- def check_dir1(path):
- if not os.path.exists(path):
- os.mkdir(path)
- else:
- files = os.listdir(path)
- for file in files:
- file_path = os.path.join(path, file)
- os.remove(file_path)
- '''
- 制作一些文本行数据
- '''
- from PIL import ImageFont, ImageDraw
- import PIL.Image as PImage
- import random
- import os
- import numpy as np
- import cv2
- from rec.temporary_boundary.line_process import cut_line3_1
- from result_process.preprocess import check_dir1
-
- if __name__=='__main__':
- cha_list = ['A','B','C','D','E','F','G','H','I','J','K',\
- 'L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z']
-
-
- save_dir = '/home/fuxueping/4tdisk/data/certificate_reader/北京现场测试数据/20240614针对识别问题/SAU_name'
- check_dir1(save_dir)
- txt_parh = '/home/fuxueping/4tdisk/data/certificate_reader/北京现场测试数据/20240614针对识别问题/SAU_name.txt'
- bg_img_dir = '/home/fuxueping/4tdisk/data/certificate_reader/北京现场测试数据/20240614针对识别问题/bg'
- bg_imgs = os.listdir(bg_img_dir)
-
- f_save = open(txt_parh, 'w', encoding='utf-8')
- check_dir1(save_dir)
- num = 50
- while num:
- all_num = 0
- bg_img = random.choice(bg_imgs)
- num1=random.choice([2, 3])
- chr_str = ''
- all_num += num1
- while num1:
- chr_ = random.choice(cha_list)
- chr_str += chr_
- num1 -=1
-
- char_med = ''
- for i in range(3):
- num2=random.choice([5,6,7,8])
- chr_str2=''
- all_num += num2
- while num2:
- chr_ = random.choice(cha_list)
- chr_str2 += chr_
- num2 -= 1
- if i == 0:
- char_med += chr_str2+', '
- elif i == 1:
- char_med += chr_str2 + ' '
- elif i == 2:
- char_med += chr_str2 + ' '
-
- chr_1 = random.choice(cha_list)
-
- result_str = chr_str+' '+char_med+chr_1
- all_num += 1
-
-
-
-
- im = PImage.open(os.path.join(bg_img_dir, bg_img))
- w, h = im.size
-
- font_size = 24
- w_len = int(0 + all_num * (font_size-3) + 4)
- if w_len > w:
- num -= 1
- continue
- name_font = ImageFont.truetype('/home/fuxueping/4tdisk/data/certificate_reader/北京现场测试数据/20240614针对识别问题/fonts/n019003l.pfb', font_size)
- draw = ImageDraw.Draw(im)
- y_len = random.randint(0, h-font_size-5)
- color = tuple([random.randint(0, 20) for _ in range(3)])
- draw.text((2, y_len), result_str, fill=color, font=name_font)
-
- box = (0, y_len, w_len, y_len+font_size+5)
- rect_img = im.crop(box)
- image_array = np.array(rect_img)
- cv2_image = cv2.cvtColor(image_array, cv2.COLOR_RGB2BGR)
- result, _ = cut_line3_1(cv2_image)
- if len(result):
- region_rec = cv2_image[result[1]:result[3], result[0]:min(w, result[2]+2)] # 裁剪出待识别的区域
- image_array = cv2.cvtColor(region_rec, cv2.COLOR_BGR2RGB)
- rect_img = PImage.fromarray(image_array)
- # image_array = cv2.cvtColor(cv2_image, cv2.COLOR_BGR2RGB)
- # rect_img = PImage.fromarray(image_array)
-
- save_path = os.path.join(save_dir, str(num)+'_'+result_str+'.jpg')
- line = save_path+'\t'+result_str+'\n'
- f_save.write(line)
- rect_img.save(save_path)
- num -= 1
- f_save.close()
- # 根据设定的阈值和图片直方图,找出波峰,用于分隔字符
- def find_waves_row(threshold, histogram):#行数是59
- # up_point = -1 # 上升点
- # is_peak = False
- # if histogram[0] >= threshold:
- up_point = 0 #起始位置
- is_peak = True
- wave_peaks = []
- top_cut = []
- for i, x in enumerate(histogram): #x是对应的像素和,i是行
- if is_peak and x >= threshold:
- if i - up_point >=2 :
- # top_cut.append((up_point, i)) #加这一行,相当于裁减掉多于的空行
- up_point = i-1
- else:
- up_point = i
- is_peak = False
- elif not is_peak and x < threshold:#随后找到字符消失的位置
- is_peak = True
- if 1 < i < histogram.shape[0]-1:#行数不是在开头也不在结尾
- wave_peaks.append((up_point, i+1))
- else:
- wave_peaks.append((up_point, i))
- up_point = i
-
- # if is_peak and up_point != -1 and i - up_point > 4:
- # wave_peaks.append((up_point, i))
- if not is_peak and x >= threshold:#虽然数据已经结束,但是没有出现小于阈值的情况
- wave_peaks.append((up_point, i))
-
- return wave_peaks
-
- def cut_line3_1(rgb_img, kernel_size = 3, y_len = 5, row_threshold=255 * 1, col_thresh = 255*1):
- '''
- 切割出每一行,只保留高度满足条件的一行内容,然后切除掉每一行的前端后尾端的空白
- '''
- rgb_img = method_9(rgb_img) #高斯滤波
- # 使用sauvola进行二值化
- h, w = rgb_img.shape[:2]
- sau_bin = sauvola_bin(rgb_img) #sauvola二值化
- # cv2.imwrite('./../temp/sauvola_bin.jpg', sau_bin)
- # sau_bin = get_charcter_region(rgb_img) # 局部区域算阈值二值化
- # cv2.imwrite('./../temp/sau_bin1.jpg', sau_bin)
- sau_bin_inv = 255 - sau_bin
- # cv2.imwrite('./../temp/sau_bin_inv1.jpg', sau_bin_inv)
- if kernel_size != 0:
- sau_bin_inv = cv2.medianBlur(sau_bin_inv, kernel_size)
- # cv2.imwrite('./../temp/sau_bin_inv_dinose1.jpg', sau_bin_inv)
-
- col_histogram = np.sum(sau_bin_inv, axis=1)
- wave_peaks = find_waves_row(col_thresh, col_histogram)
- result = []
-
- #找出高度最大的区域,只保留一行内容
- max_y = 0
- result_y = []
- if not len(wave_peaks):
- return [], sau_bin_inv
-
- for i, wave_peak in enumerate(wave_peaks):
- y1 = wave_peak[0]
- y2 = wave_peak[1]
-
- if y2 - y1 < y_len: #20之前是这个阈值 ,将高度不满足>=5的字符区域去掉
- continue
- if max_y < y2 - y1:
- max_y = y2 - y1
- result_y = [y1, y2]
-
- if len(result_y): #有时候裁剪的图片可能是没有字符,这种情况多出现在证件类别错误的情况
- y1 = result_y[0]
- y2 = result_y[1]
- else:
- return [], sau_bin_inv
-
- line_img = sau_bin_inv[y1:y2, :]
- # line_img_bgr = rgb_img[wave_peak[0]:wave_peak[1], :]
- # save_other = os.path.join(save_path, file + '_'+str(i)+'.jpg')
- # cv2.imwrite(save_other, line_img)
-
- row_histogram = np.sum(line_img, axis=0) # 数组的每一列求和
- # row_max = np.max(row_histogram)
- # row_threshold = row_max - 255*1
-
- wave_peaks_line = find_waves_col(row_threshold, row_histogram)
- # cv2.imwrite('./../temp/line_img.jpg', line_img)
-
- x1 = 0
- x2 = w
- result_ = []
- for wave_ in wave_peaks_line:
- len_x = wave_[1] - wave_[0]
- if len_x > 5:
- result_.append(wave_)
-
- if len(result_): # 有时候朝水平投影内容消失了,就用【0,w】代替
- x1 = result_[0][0]
- x2 = result_[-1][1]
-
- return [x1, y1, x2, y2], sau_bin_inv