栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

png图片自动转ttf字体(使用python实现)

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

png图片自动转ttf字体(使用python实现)

这里写目录标题
  • 一、任务概述
  • 二、实现
    • 2.1 ocr识别
      • 2.1.1 安装环境
      • 2.1.2 实现脚本
    • 2.2 图形文字精确提取
    • 2.3 png转svg
    • 2.4 svg转ttf

一、任务概述


任务要求:需要将上述生僻字png图片批量自动转成ttf字体文件,该字体对应的unicode码为图中下半部分对应的16进制值。

整个任务分成几个部分实现:

  • OCR识别:识别出图片下半部分对应的16进制数值;
  • 图形文字精确提取:提取出图片上半部分精确的文字图形区域;
  • png图片转svg: 通过图像处理算法提取上半部分图片的字形轮廓,将其转成svg文件;
  • svg转ttf:通过FontForge提供的Python工具实现批量转换;
二、实现 2.1 ocr识别

综合考虑识别精度和CPU推理速度要求,本文使用PaddleOCR实现。

2.1.1 安装环境
python -m pip install paddlepaddle==2.3.0 -i https://mirror.baidu.com/pypi/simple
pip install paddlehub -i https://pypi.tuna.tsinghua.edu.cn/simple 
pip install shapely -i https://pypi.tuna.tsinghua.edu.cn/simple
2.1.2 实现脚本
# 导入系统库
import cv2
import os

# 导入字体识别库
import paddlehub as hub

# 导入自定义识别库
from tools import sim_code 

def main(): 
    '''
    主函数
    '''
    # 定义参数
    img_list = list()
    img_dir = './screenshot/25A2C_2625F'  
    target_width, target_height = 363, 269

    # 获取文件列表
    for file in os.listdir(img_dir):
            if os.path.splitext(file)[1].lower() in '.png|.jpg':
                img_list.append(file)
    print('当前总图片数量: %d' % len(img_list))
    
    # 创建识别器
    ocr = hub.Module(name="chinese_ocr_db_crnn_server")
    
    # 循环处理图片
    index = 0
    error_index = 0
    for img_path in img_list:
        img = cv2.imread(os.path.join(img_dir,img_path),cv2.IMREAD_COLOR)
        # 图像标准化
        h, w, _=img.shape
        if h != target_height or w != target_width:
            img = cv2.resize(img, dsize=(target_width, target_height))
            
        # 提取ocr区域
        ocrimg = img[170:259,40:310,:]    
        h,w,_= ocrimg.shape
        ocrimg = cv2.copyMakeBorder(ocrimg,2*h,2*h,2*w,2*w, cv2.BORDER_CONSTANT,value=[255,255,255])    
        result = ocr.recognize_text([ocrimg])
        
        code = result[0]['data']
        if len(code)==0:
            error_index+=1
            cv2.imwrite('error/%d.png' % error_index, img)
            continue
        
        code = code[0]["text"].strip()
        code = sim_code(code)
        if len(code)!=5:
            error_index+=1
            cv2.imwrite('error/%d.png' % error_index, img)
            continue
        try:
            a = int(code,16)
        except Exception as e:
            error_index+=1
            cv2.imwrite('error/%d.png' % error_index, img)
            continue
        
        index += 1 
        print(img_path+'   识读结果:'+code)
        
        # 检查是否有同名文件
        save_path = 'ocr/%s.png' % code
        if os.path.exists(save_path):
            error_index+=1
            cv2.imwrite('error/%d_repeat.png' % error_index, img)
            continue
            
        textimg = img   
        cv2.imwrite(save_path, textimg)


if __name__ == "__main__":
    '''
    程序入口
    '''
    main()

识读结果如下图所示:

2.2 图形文字精确提取

完整代码如下:

# 导入系统库
import cv2
import os
import numpy as np


def main(): 
    '''
    主函数
    '''
    # 定义参数
    img_list = list()
    img_dir = './ocr' 
    target_width, target_height = 363, 269

    # 获取文件列表
    for file in os.listdir(img_dir):
            if os.path.splitext(file)[1].lower() in '.png|.jpg':
                img_list.append(file)
    print('当前总图片数量: %d' % len(img_list))
    
    # 循环处理图片
    index = 0
    error_index = 0
    for img_path in img_list:
        img = cv2.imread(os.path.join(img_dir,img_path),cv2.IMREAD_COLOR)
        # 图像标准化
        h, w, _=img.shape
        if h != target_height or w != target_width:
            img = cv2.resize(img, dsize=(target_width, target_height))
        
        # 去掉上下左右边界线
        image_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        edges = cv2.Canny(image_gray, 170, 220, apertureSize=3)
        lines = cv2.HoughLines(edges, 1, np.pi / 180, 250)
        for line in lines:
            # 获取rho和theta
            rho, theta = line[0]
            a = np.cos(theta)
            b = np.sin(theta)
            x0 = a * rho
            y0 = b * rho
            x1 = int(x0 + 1000 * (-b))
            y1 = int(y0 + 1000 * (a))
            x2 = int(x0 - 1000 * (-b))
            y2 = int(y0 - 1000 * (a))
            cv2.line(img, (x1, y1), (x2, y2), (255, 255, 255), thickness=20)
        
        # 提取图形区域
        img = img[5:175,100:270,:]
        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        
        # 精确裁剪
        ret, thresh = cv2.threshold(gray,127,255,cv2.THRESH_BINARY_INV)
        coords = np.column_stack(np.where(thresh > 0))
        coords = np.array(coords, dtype=np.float32)
        #min_rect = cv2.minAreaRect(coords)
        
        rect = cv2.boundingRect(coords)
        [y, x, h, w] = rect
        img = img[y:y+h,x:x+w,:]
        
        # 调整为正方形
        h,w,_ = img.shape
        if h>w:
            pad = int((h-w)/2.0)
            img = cv2.copyMakeBorder(img,0,0,pad,pad, cv2.BORDER_CONSTANT,value=[255,255,255])
        elif w>h:
            pad = int((w-h)/2.0)
            img = cv2.copyMakeBorder(img,pad,pad,0,0, cv2.BORDER_CONSTANT,value=[255,255,255])
                    
        # 统一缩放
        img = cv2.resize(img, dsize=(128, 128))

        # 边缘补白
        img = cv2.copyMakeBorder(img,10,10,10,10, cv2.BORDER_CONSTANT,value=[255,255,255])   
        
        # 保存
        code = os.path.splitext(img_path)[0]
        save_path = 'crop/%s.png' % code  
        cv2.imwrite(save_path, img)
        index += 1
        print(img_path)   
        


if __name__ == "__main__":
    '''
    程序入口
    '''
    main()

效果如下图所示:

2.3 png转svg

这里主要通过opencv的形态学操作提取图像轮廓实现转换。

# 导入系统库
import cv2
import os


def main():
    '''
    主函数
    '''
    # 定义参数
    img_list = list()
    img_dir = './crop' 

    # 获取文件列表
    for file in os.listdir(img_dir):
            if os.path.splitext(file)[1].lower() in '.png|.jpg':
                img_list.append(file)
    print('当前总图片数量: %d' % len(img_list))
    
    # 循环处理图片
    index = 0
    for img_path in img_list:
        textimg = cv2.imread(os.path.join(img_dir,img_path),cv2.IMREAD_COLOR)
        
        # 提取图形区域
        textimg = cv2.resize(textimg, dsize=(640, 640))
        blur = cv2.GaussianBlur(textimg, (3, 3), 0)
        gray = cv2.cvtColor(blur, cv2.COLOR_BGR2GRAY)
        ret, thresh = cv2.threshold(gray, 10, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)        
        contours,hierarchy = cv2.findContours(thresh, mode=cv2.RETR_TREE, method=cv2.CHAIN_APPROX_SIMPLE)
        
        epsilon = 3
        h, w, _ = textimg.shape
        code = os.path.splitext(img_path)[0]
        svg_path = 'svg/'+code+'.svg'
        with open(svg_path, "w+") as f:
            f.write(f'")
        index +=1
        print('当前处理完 %d 张图片' % index)
    print('全部处理结束')


if __name__ == "__main__":
    '''
    程序入口
    '''
    main()

部分样例转换结果如下图所示:

2.4 svg转ttf

ttf是专门的字体库文件,目前能够支持ttf编辑的软件并不多。这里推荐使用FontForge,该软件提供了python处理接口,可以使用python脚本批量转换svg到ttf。

首先从官网下载windows版的FontForge并安装,本文将其安装到D盘的toolplace的文件夹中。要使用FontForge提供的python接口,我们必须要使用FontForge的python执行器,这个执行器位于FontForge安装目录的bin文件夹中,完整路径如下图所示:

D:toolplaceFontForgeBuildsbin

在这个目录下面有个名为ffpython.exe的可执行文件,这个就是FontForge提供的python执行器。为了能够正常使用这个执行器,我们需要将我们的可执行目录切换到bin文件夹下面,然后创建一个转换脚本main_ttf.py,内容如下:

# 导入系统库
from time import sleep
import fontforge, os,psMat


def main():
    '''
    主函数
    '''
    # 定义参数
    img_list = list()
    img_dir = './svg' 

    # 获取文件列表
    for file in os.listdir(img_dir):
            if os.path.splitext(file)[1].lower() in '.svg':
                img_list.append(file)
    print('当前总图片数量: %d' % len(img_list))
    
    # 循环处理图片
    index = 0
    
    for img_path in img_list:  
        print('当前处理 '+img_path)
        
        # 获取unicode
        codestr = os.path.splitext(img_path)[0]
        code = int(codestr,16)
        
         # 创建字体
        font = fontforge.font()
        font.encoding = 'UnicodeFull'
        font.version = '1.0'
        font.weight = 'Regular'
        font.fontname = 'uni'+codestr
        font.familyname = 'uni'+codestr
        font.fullname = 'uni'+codestr       
        
        # 创建字符
        glyph = font.createChar(code, "uni"+codestr)
        glyph.importOutlines(os.path.join(img_dir,img_path))
        
        # 位移调整
        base_matrix = psMat.translate(0,0)
        glyph.transform(base_matrix)
        
        # 写入ttf
        font.generate('./ttf/'+codestr+'.ttf')      
        index +=1
        # if index>1:
        #     break
        print('当前处理完 %d 张图片' % index)
        
        # 删除文件
        os.remove(os.path.join(img_dir,img_path))
        
    
    print('全部处理结束')


if __name__ == "__main__":
    '''
    程序入口
    '''
    main()

然后使用下面的命令执行该脚本:

./ffpython.exe main_ttf.py

最后在当前目录下会生成一个个的ttf文件。

我们可以使用FontForge的客户端查看我们这个生成的字体文件,打开后在菜单栏上选择Encoding-Compact,如下图所示:

可以看到我们已经成功的将png图片批量转换成了ttf文件。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/997393.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号