Código para generar el conjunto de entrenamiento de OCR, jefe: ¿sin datos? tu nuevo

El sol poniente era fuerte, incluso un poco deslumbrante, y atravesaba el cristal e iluminaba el teclado.

Este es un teclado de plástico ordinario. Los huecos están llenos de polvo y caspa. Bajo la iluminación de una luz fuerte, es más claramente visible, al igual que el campo de visión bajo un microscopio.

Después de trabajar durante tantos años, hace mucho tiempo que entendí que el teclado es solo una herramienta, y lo único que afecta el nivel técnico es la exigencia del jefe.

El cursor en el IDE parpadeaba allí, nunca se movió un solo espacio, pero nunca descansó, al igual que mi pensamiento actual.

La escena de la mañana se repetía en mi mente:

El jefe dijo: ¿No dijiste que la tecnología OCR está muy madura ahora? ¡Entonces lo hacemos nosotros mismos!

Dije: el marco es muy maduro. Pero no tenemos los datos...

El jefe preguntó: ¿Qué datos quieres?

Mi respuesta: si desea que una máquina reconozca "1", debe entrenarla con al menos 500 imágenes de "1".

El jefe preguntó: ¿Qué pasa con el entrenamiento "2"?

Mi respuesta: 500 fotos de "2", y no se pueden repetir, y repetido cuenta como 1 foto. ¡Piénselo, hay más de 3,000 caracteres chinos de uso común y no tenemos material! ¿Quieres comprar algunos en línea...

El jefe se sumió en una profunda reflexión, y de repente sus anteojos destellaron: Oye, si dejas salir a un programador, incluso puedes salir con una nueva esposa.

Rápidamente expliqué: ese es el objeto.

Solo quería decir que no hay nadie disponible, solo un interno.

El teléfono del jefe sonó de repente, y él tapó el teléfono y me dijo: me voy de viaje de negocios. En tres días, cuando regrese, debes darle a mi esposa ... no, dale el conjunto de datos a nuevo. !

Foto de WeChat_20220716004140.jpg

Día 1: Dibuja un marco negro e ingresa una palabra

Temprano en la mañana, entré a la oficina con leche de soya.

Mi oficina no es grande, solo hay dos estaciones de trabajo, una para mí y otra para el interno Xiao Wang. Sin embargo, en el cartel de la puerta se lee claramente las palabras "Centro de I+D de Software del Parque Industrial". El jefe dijo que se ampliará a un equipo técnico de 200 personas en el futuro.

Xiao Wang ahora está en su último año y es pasante aquí este año. El puesto es ingeniero de investigación y desarrollo. Xiao Wang trabaja muy en serio. Viene antes que yo todos los días. Debería ser una buena plántula si está bien entrenado.

"Disculpe, ¿este es el departamento de finanzas?", preguntó un tío con la cabeza asomando por la puerta.

"¡no!".

"No, no, ¿por qué haces tanto ruido? Tu habitación es muy similar al departamento de finanzas. Hay dos personas en una cabaña. Tú eres el contador y él es el cajero".

Caminé hacia Xiao Wang, Xiao Wang estaba leyendo el blog de los Nuggets, y había muchos grandes dioses en él: el chico TF, el hermano Chun, Lin Sanxin...

Xiao Wang me llama jefe porque soy la persona a cargo del "Centro de I + D de software de parque industrial". Estoy a cargo de él y él está a cargo de mí.

跟你安排一个任务,很简单,用python先画一个32*32像素的黑色背景,然后在上面写上白色的字,你去写吧。

小王很快就写好了。

from PIL import Image
from PIL import ImageDraw

# 画出一个32*32的黑色框
img = Image.new("RGB", (32, 32), "black") 
# 在黑框里写上字
draw = ImageDraw.Draw(img)
draw.text((0,0), "2", (255, 255, 255))
# 保存画好的图片
img.save("2.png")

小王上午就来找我汇报工作。

我试过了在黑色背景图上写上字母、数字、符号,都是可以的。

sin título-1 copia.png

我连连点头,称赞小王很棒。

小王问,接下来要做什么。我说,明天再告诉你。

第二天:先加载字体,再绘制字符

第二天,小王问我,老大,今天什么任务啊,我昨天等了一下午。

我说,运行你昨天的代码,输出个汉字试试。

小王执行了下面的代码: draw.text((0,0), "汉", (255, 255, 255)),结果报错了:AttributeError: 'ImageFont' object has no attribute 'getmask2'

小王愣在一旁,我却微微一笑:

你没有加载支持汉字的字体,就直接绘制汉字是不行的。今天的任务就是:你百度解决汉字的绘制。

小王直到下午才来找我汇报工作。

han.png

他不但展示了效果,还跟我汇报了代码。

from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont

img = Image.new("RGB", (320, 320), "black") 
draw = ImageDraw.Draw(img)
# 加载一种字体, 320是字体的大小,和黑框一样大
font = ImageFont.truetype("chinese_fonts/fangzheng_heiti.TTF", 320)
# 将字体作为参数传入
draw.text((0,0), "汉", (255, 255, 255),font)
img.save("汉.png")

跟昨天的相比,区别就是调用 ImageFont.truetype("字体文件路径", 字体大小)加载了字体文件,然后调用draw.text(……,font)的时候,把字体font传入,这样字体大小也可以控制了。

我连连点头,称赞小王很棒。并继续说,汉字的可以了,你再试试数字和符号。

小王又调用draw.text(",")、raw.text("2")draw了个“,”和“2”。

2.png

“什么感觉?看完这些图片,你什么感觉?”,我问小王,声音有些严厉。

“没什么感觉啊,这……这不挺好的!”,小王回答道。

我提高了音量,敲着屏幕:“不居中啊,大哥,逗号那么明显,你看不出来吗?”。

刚刚还沉浸在骄傲中的小王有些疑惑,但是他依然很镇定:这个好弄,draw.text((x,y),……)我改下x和y坐标就行了。

“今天能改完吗?”,我问他。

“肯定能改完!调个坐标就完事了”,小王很自信的样子。

“好”,我告诉小王:“你要记得一件事,不要针对某一个字符调坐标,多调几个,不管是出1,2,3,4,还是甲乙丙丁,都要居中,记住了吗?”。

下午,我回家时,小王说要加个班。

凌晨2点,我在家上厕所时,远程查看了一下公司的网络流量数据,不断有关于“python”、“字体居中”的搜索。

第三天:字体居中,添加椒盐

第三天一早,我在家吃过饭,又从楼下买了包子和豆浆。

一进办公室,我发现小王趴在办公桌上不动了。

我心里就是一惊,别再是怎么着了吧。昨天的任务对他来说可真是够难的,我连忙晃动他:小王,醒醒,醒醒,小王!

小王慢慢地睁开眼,打了个哈欠,伸了个懒腰:天亮了吗?

小王发现我在旁边,才反应过来:哦,这是在公司啊,我的“居中”功能还没有实现呢!

老大,为什么我怎么调都有问题,x=20,y=30,对这个字符可以,换别字符的就不行了呢?如何才能写出通用的代码啊?那得加多少ifelse if判断啊?

我说,你先把早饭吃了,完了我告诉你个知识点,你马上就能完成任务了。

integración.png

其实,字体制作时,有很多规则。图中红框表示的区域,代表这是字体的范围,就算内部是空白也是人家的领地。里面,还有一个字符区域,是具体显示的内容,比如逗号,就靠下,为了便于标记,字符在字体内有一个偏移量offset属性,表示它相对于字体区域的偏移情况。

所以,你要让一个字在背景里居中,他的坐标绝不是你肉眼看到的,而且是千变万化的,需要你结合字体的宽高以及偏移量来计算。 integración 2.png

小王很兴奋,有规则就好办了。

很快,他就写好了代码。

from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont

width,height = 32,32 # 因为宽高多处使用,定义成变量
font_size = 32
char = "好" # 要绘制的字符

img = Image.new("RGB", (width, height), "black") 
draw = ImageDraw.Draw(img)
# 加载一种字体, 32是字体的大小,和黑框一样大
font = ImageFont.truetype("chinese_fonts/fangzheng_fangsong.ttf", font_size)
# 获取字体的宽高
font_width, font_height = draw.textsize(char, font)
offset_x, offset_y = font.getoffset(char)

# 计算字体绘制的x,y坐标,主要是让文字画在图标中心
x = (width - font_width - offset_x) // 2
y = (height - font_height - offset_y) // 2
# 将字体作为参数传入
draw.text((x,y), char, (255,255, 255),font)
img.save("好.png")

小王试了试,不管是数字、字母、符号还是汉字,确实都可以居中了。 2022-07-15_235428.png

其实,关键点就是通过draw.textsize(char, font)获取了字体的宽高,通过font.getoffset(char)获取了偏移量的信息。如果要将字体在一个背景中居中,其实就是背景的长度减去字体长度再减去偏移量长度,这是字符和背景的缝隙,缝隙除以2,那就是把缝隙分到两边了,它就居中了。

今天,小王虽然没有睡觉,但是他却很开心,我告诉他帮公司解决了一个大难题,让他早早地回去休息了。

今天晚上,老板应该出差回来了。

我拿出3天前就写好的代码,跑了起来。

from __future__ import print_function
from PIL import Image
from PIL import ImageFont
from PIL import ImageDraw
import os
import shutil
import time
import cv2

# 要生成的文本
label_dict = {0: '你', 1: '好', 2: '掘', 3: '金', 4: ':', 5: '1', 6: '+', 7: '2', 8: ',', 9: 'g', 10: 'o', 11: '!'}

# 文本对应的文件夹,给每一个分类建一个文件
for value,char in label_dict.items():
    train_images_dir = "dataset"+"/"+str(value)
    if os.path.isdir(train_images_dir):
        shutil.rmtree(train_images_dir)
    os.makedirs(train_images_dir)

def makeImage(label_dict, font_path, width=32, height=32, rotate = 0, salt = 22):

    # 从字典中取出键值对
    for value,char in label_dict.items():
        # 创建一个黑色背景的图片
        img = Image.new("RGB", (width, height), "black") 
        draw = ImageDraw.Draw(img)
        # 加载一种字体,字体大小是图片宽度的90%
        font = ImageFont.truetype(font_path, int(width*0.9))
        # 获取字体的宽高
        font_width, font_height = draw.textsize(char, font)
        offset_x, offset_y = font.getoffset(char)
        # 计算字体绘制的x,y坐标,主要是让文字画在图标中心
        x = (width - font_width - offset_x) // 2
        y = (height - font_height - offset_y) // 2
        # 绘制图片,在那里画,画啥,什么颜色,什么字体
        draw.text((x,y), char, (255, 255, 255), font)
        # 设置图片倾斜角度
        if rotate != 0:
            img = img.rotate(rotate)
        
        # 将数据转为np格式
        np_img = np.asarray(img.getdata(), dtype='uint8')
        # 降维,3通道转为1通道,并组成矩阵
        np_img = np_img[:, 0].reshape((height, width))
        for i in range(salt): #添加噪声
            temp_x = np.random.randint(0,np_img.shape[0])
            temp_y = np.random.randint(0,np_img.shape[1])
            np_img[temp_x][temp_y] = 255

        # 命名文件保存,命名规则:dataset/编号/img-编号_r-选择角度_时间戳.png
        time_value = int(round(time.time() * 1000))
        img_path = "dataset/{}/{}_{}.png".format(value, time_value, rotate)
        cv2.imwrite(img_path, np_img)
        
# 存放字体的路径
font_dir = "./chinese_fonts"
for font_name in os.listdir(font_dir):
    # 把每种字体都取出来,每种字体都生成一批图片
    path_font_file = os.path.join(font_dir, font_name)
    # 倾斜角度从-5到5度,每个角度都生成一批图片
    for k in range(-5, 5, 1):	
        # 每个字符都生成图片
        makeImage(label_dict, path_font_file, rotate = k, salt = 5-k)

Este código no solo genera texto, sino que también agrega elementos de interferencia, como rotar moderadamente la imagen, como agregar ruido aleatorio a la imagen, lo llamamos sal y pimienta (la pimienta es negra, la sal es blanca, lo que significa ruido blanco y negro ) . Porque, cuando se entreguen los documentos que identificamos, habrá situaciones poco claras, por lo que tenemos que entrenar de acuerdo con la interferencia, para que el efecto sea más cercano a la situación real.

2022-07-16_001029.png

En realidad, el código para generar el conjunto de caracteres es muy simple y lo escribí la tarde que discutí con mi jefe.

Lo que me mantiene luchando es dejar que Xiao Wang escriba esta vez. Deje que Xiao Wang escriba, necesito gastar varias veces más energía, porque puedo terminar de escribir el trabajo que le dije. Recordé que Xiao Wang ya era el décimo pasante de la empresa, y los primeros habían aprendido un poco y se fueron.

Al final, elegí cultivar a Xiao Wang. Haz lo mejor que puedas, escucha al destino.

Ahora parece que, aunque solo son 3 días, Xiao Wang ha hecho un gran progreso.

Día 4: Cruce

Le entregué el conjunto de personajes al jefe y le dije que fue desarrollado por Xiao Wang. El jefe estaba muy contento y dijo que le daría a Xiao Wang un aumento de salario de 200 yuanes.

Estaba dudando si decirle a Xiao Wang. Xiao Wang me encontró, estaba un poco avergonzado.

De hecho, yo también lo pensé.

Xiao Wang dijo: Jefe, encontré un nuevo trabajo, y la otra parte reconoció mucho mi habilidad, especialmente por mi habilidad para generar conjuntos de caracteres automáticamente, también lo necesitaban mucho, y el salario se duplicó para mí... Entonces. ..

"Está bien, ¡bendito seas! ¿Cuándo te vas a ir?", No tenía la menor ola en mi corazón.

Xiao Wang dijo con urgencia: Esta tarde... ¿está bien?

¡Pueden!

Mirando la estación donde se fue Xiao Wang, saqué un plan del cajón, que era el guión para entrenar a Xiao Wang para completar todo el proyecto de reconocimiento OCR.

Casualmente pasé una página, y el punto de conocimiento de esta página es: ¿Por qué los conjuntos de datos de entrenamiento de imágenes usan principalmente fondos negros y fuentes blancas?

Sonreí: eso es porque el valor del color del negro es 0 y el valor del color del blanco es 255. La computadora ignora el 0 y presta más atención al 255 del blanco. Si es negro sobre blanco, entonces requerir que la computadora se concentre en 0 lo convierte en un dolor.

También hay cómo entrenar, cómo ajustar, cómo implementar, etc.

De todos modos, él tiene un buen lugar a donde ir, y yo puedo ser considerado un hombre de negocios.

Cruzado, todo cruzado yo mismo.

微信图片_20220716004134.jpg

Estoy participando en el reclutamiento del programa de firma de creadores de la Comunidad Tecnológica de Nuggets, haga clic en el enlace para registrarse y enviar .

Supongo que te gusta

Origin juejin.im/post/7120640342298198024
Recomendado
Clasificación