本文目前使用的方法是基于SVM的,后续可能会改进成别的,不够不管是哪一种,都需要创造训练集。

先说第一种,mnist,不推荐,毕竟是手写训练集,打印出来的还是能好一些。

所以,这里采用生成数字的方式

首先在python里面导入必须要的库,我用的是pycharm,设置里能直接加。

生成数字的代码如下,这里对图片进行了很多修改,如让其旋转一定角度,或者是更改其对比度,可以让训练的结果更好

不过又两个地方需要注意,一个是图片数量那里,他这个数量是图片总数,也就是一共生成多少图片。这里给2000是第一次尝试时候用的2000,对于部分数字已经够用,但是对于6,8,9等比较模糊的数字还是不太够,需要根据实际需要修改数量

第二,他这里生成的数字是64x64的,后续SVM时候,以及数字识别的时候,大小都要写64x64.

第三,字体路径,点开C:/Windows/Fonts/后,你就可以看到电脑的各种字体,我选的是黑体。

import os
import random
from PIL import Image, ImageDraw, ImageFont, ImageEnhance
import numpy as np

# 设置文件保存路径
output_dir = 'generated_images'
os.makedirs(output_dir, exist_ok=True)

# 设置字体路径
font_path = "C:/Windows/Fonts/simhei.ttf"

# 设置生成图片的数量
num_images = 2000

# 图像数据增强:旋转、平移、亮度调整
def augment_image(image):
    # 随机旋转
    angle = random.randint(-15, 15)
    image = image.rotate(angle, resample=Image.BICUBIC, expand=False)

    # 随机平移
    max_translation = 5
    translation = (random.randint(-max_translation, max_translation),
                   random.randint(-max_translation, max_translation))
    image = image.transform(
        image.size, Image.AFFINE,
        (1, 0, translation[0], 0, 1, translation[1]),
        resample=Image.BICUBIC
    )

    # 随机缩放 + 裁剪或填充回原始尺寸
    scale_factor = random.uniform(0.8, 1.2)
    new_size = (int(image.size[0] * scale_factor), int(image.size[1] * scale_factor))
    image = image.resize(new_size, resample=Image.BICUBIC)

    # 保持输出尺寸为 64x64
    if scale_factor < 1.0:
        # 缩小后,放到中央,填充白色背景
        background = Image.new('RGB', (64, 64), 'white')
        offset = ((64 - new_size[0]) // 2, (64 - new_size[1]) // 2)
        background.paste(image, offset)
        image = background
    else:
        # 放大后,居中裁剪
        left = (new_size[0] - 64) // 2
        top = (new_size[1] - 64) // 2
        image = image.crop((left, top, left + 64, top + 64))

    # 随机亮度调整
    enhancer = ImageEnhance.Brightness(image)
    image = enhancer.enhance(random.uniform(0.8, 1.2))

    return image

# 生成并保存图像
def generate_images():
    for i in range(num_images):
        # 随机选择数字
        digit = str(random.randint(0, 9))

        # 创建白色背景
        img = Image.new('RGB', (64, 64), color='white')
        draw = ImageDraw.Draw(img)

        # 随机字体大小
        font_size = random.randint(30, 50)
        font = ImageFont.truetype(font_path, font_size)

        # 获取文本边界框(替代 textsize)
        bbox = draw.textbbox((0, 0), digit, font=font)
        text_width = bbox[2] - bbox[0]
        text_height = bbox[3] - bbox[1]

        # 计算文本位置(居中)
        x = (img.width - text_width) // 2
        y = (img.height - text_height) // 2

        # 绘制文本
        draw.text((x, y), digit, font=font, fill='black')

        # 增强图像
        img = augment_image(img)

        # 保存图片
        img.save(os.path.join(output_dir, f"{i}_{digit}.png"))

if __name__ == '__main__':
    generate_images()

生成完之后就可以在python的文件夹找到图片集了。

下面还有一个没有黑边纯数字的数字生成集,而且数字放大了一些:

import os
import random
from PIL import Image, ImageDraw, ImageFont, ImageEnhance

output_dir = 'generated_images'
os.makedirs(output_dir, exist_ok=True)

font_path = "C:/Windows/Fonts/simhei.ttf"
image_size = (64, 64)

digit_counts = {
    '0': 500,
    '1': 500,
    '2': 500,
    '3': 500,
    '4': 500,
    '5': 500,
    '6': 500,
    '7': 500,
    '8': 500,
    '9': 500,
}


def augment_image(image):
    # 增加图像背景,使旋转时不产生黑边
    angle = random.randint(-15, 15)
    new_size = (image.size[0] * 2, image.size[1] * 2)  # 扩大背景
    expanded_image = Image.new('RGB', new_size, color='white')

    # 计算中心位置
    x_offset = (new_size[0] - image.size[0]) // 2
    y_offset = (new_size[1] - image.size[1]) // 2
    expanded_image.paste(image, (x_offset, y_offset))

    # 旋转图像
    rotated_image = expanded_image.rotate(angle, expand=True, fillcolor='white')  # 保证旋转时无黑边

    # 缩放时确保最小比例为 0.9,避免数字太小
    scale = random.uniform(0.9, 1.2)  # 防止缩放过小
    new_size = (int(rotated_image.size[0] * scale), int(rotated_image.size[1] * scale))
    rotated_image = rotated_image.resize(new_size, Image.Resampling.LANCZOS)

    # 裁剪并调整至 64x64,确保数字居中
    left = (rotated_image.size[0] - 64) // 2
    top = (rotated_image.size[1] - 64) // 2
    right = (rotated_image.size[0] + 64) // 2
    bottom = (rotated_image.size[1] + 64) // 2
    rotated_image = rotated_image.crop((left, top, right, bottom))

    rotated_image = rotated_image.resize((64, 64), Image.Resampling.LANCZOS)  # 确保图像大小为64x64

    # 提高对比度,确保数字更清晰
    enhancer = ImageEnhance.Contrast(rotated_image)
    rotated_image = enhancer.enhance(random.uniform(1.2, 2.0))

    return rotated_image


def generate_images():
    count = 0
    for digit, num in digit_counts.items():
        for _ in range(num):
            img = Image.new('RGB', image_size, color='white')  # 白色背景
            draw = ImageDraw.Draw(img)
            font_size = random.randint(30, 50)
            font = ImageFont.truetype(font_path, font_size)

            # 获取文本边界框,计算宽度和高度
            bbox = draw.textbbox((0, 0), digit, font=font)
            w, h = bbox[2] - bbox[0], bbox[3] - bbox[1]  # 计算宽度和高度
            x = (image_size[0] - w) // 2
            y = (image_size[1] - h) // 2
            draw.text((x, y), digit, font=font, fill='black')  # 黑色字体

            img = augment_image(img)  # 增强图像(旋转、缩放等)
            img.save(os.path.join(output_dir, f"{count}_{digit}.png"))
            count += 1


generate_images()

剩下的见中篇和下篇。

Logo

火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。

更多推荐