%% === 修正版小学算式OCR数据集生成器 ===
function generateMathProblems()
% 初始化设置
outputDir = 'math_problems';
if ~exist(outputDir, 'dir')
mkdir(outputDir);
end
numImages = 100;
dataTable = table('Size', [numImages, 5], ...
'VariableTypes', {'string', 'string', 'string', 'string', 'string'}, ...
'VariableNames', {'Filename', 'Problem', 'CorrectResult', 'Operator', 'CorrectFlag'});
% 图像生成参数
fontSize = 80;
horizontalPadding = 50;
verticalPadding = 80;
bgColor = [1, 1, 1]; % 白色背景
textColor = [0, 0, 0]; % 黑色文字
availableFonts = {'Arial', 'Times New Roman', 'Courier New', 'Comic Sans MS'};
% 创建隐藏图像窗口
fig = figure('Visible', 'off', 'Color', bgColor, ...
'Position', [100, 100, 800, 600], ...
'InvertHardcopy', 'off');
ax = axes('Parent', fig, 'Position', [0, 0, 1, 1], ...
'XLim', [0, 1], 'YLim', [0, 1], 'Visible', 'off');
hold(ax, 'on');
imgIdx = 1;
maxAttempts = numImages * 3; % 最大尝试次数
existingLabels = containers.Map(); % 标签检测器
% === 关键修改:使用纯算式作为文件夹名称 ===
while imgIdx <= numImages && maxAttempts > 0
maxAttempts = maxAttempts - 1;
% 生成两位数算式
opType = randi(4);
switch opType
case 1 % 加法 (10-99)
a = randi([10, 99]);
b = randi([10, 99]);
result = a + b;
eq = sprintf('%d+%d=', a, b); % 算式部分
operator = 'addition';
case 2 % 减法 (20-99)
a = randi([20, 99]);
b = randi([10, min(a-1, 99)]); % 确保结果为正
result = a - b;
eq = sprintf('%d-%d=', a, b);
operator = 'subtraction';
case 3 % 乘法 (2-20)
a = randi([2, 20]);
b = randi([2, 20]);
result = a * b;
eq = sprintf('%d×%d=', a, b);
operator = 'multiplication';
case 4 % 除法 (整数结果)
divisor = randi([2, 20]);
quotient = randi([2, 20]);
dividend = divisor * quotient;
result = quotient;
eq = sprintf('%d÷%d=', dividend, divisor);
operator = 'division';
end
% 生成合理错误答案
if rand() > 0.5
displayedResult = result;
isCorrect = "1";
else
% 在正确结果附近生成合理错误
errorRange = max(1, round(result*0.2)); % 误差范围
offset = randi([-errorRange, errorRange]);
while offset == 0
offset = randi([-errorRange, errorRange]);
end
displayedResult = result + offset;
isCorrect = "0";
end
% === 关键修改1:使用纯算式作为文件夹名 ===
problemLabel = eq; % 仅算式部分
safeLabel = regexprep(problemLabel, '[<>:"/\\|?*]', '');
% 检查标签是否已存在
if isKey(existingLabels, safeLabel)
continue; % 跳过重复标签
end
existingLabels(safeLabel) = true;
% === 关键修改2:图像显示完整算式+结果 ===
fullEq = sprintf('%s%d', eq, displayedResult); % 算式+结果显示
% 选择随机字体
selectedFont = availableFonts{randi(length(availableFonts))};
% 计算图像尺寸
textWidth = length(fullEq) * fontSize * 0.6;
imgWidth = textWidth + 2*horizontalPadding;
imgHeight = verticalPadding + fontSize + verticalPadding/2;
% 设置图像大小
set(fig, 'Position', [100, 100, imgWidth, imgHeight]);
cla(ax);
% 绘制算式文本
text(ax, 0.5, 0.5, fullEq, ...
'FontSize', fontSize, ...
'FontName', selectedFont, ...
'FontWeight', 'normal', ...
'Color', textColor, ...
'HorizontalAlignment', 'center', ...
'VerticalAlignment', 'middle');
% 捕获图像数据
imgData = getframe(fig).cdata;
% === 关键修改3:按算式标签创建文件夹 ===
labelDir = fullfile(outputDir, safeLabel);
if ~exist(labelDir, 'dir')
mkdir(labelDir);
end
% 保存图像
filename = sprintf('%04d.png', imgIdx);
imwrite(imgData, fullfile(labelDir, filename));
% 更新数据表
dataTable.Filename(imgIdx) = string(filename);
dataTable.Problem(imgIdx) = string(problemLabel); % 存储纯算式
dataTable.CorrectResult(imgIdx) = string(result);
dataTable.Operator(imgIdx) = operator;
dataTable.CorrectFlag(imgIdx) = isCorrect;
imgIdx = imgIdx + 1;
end
% 检查完成度
if imgIdx <= numImages
fprintf('生成不足: %d/%d, 正在补充...\n', imgIdx-1, numImages);
dataTable = dataTable(1:imgIdx-1, :); % 调整表格大小
% 补充生成缺失的图像
for i = imgIdx:numImages
% 生成唯一算式标签
while true
a = randi([10,99]);
b = randi([10,99]);
op = {'+', '-', '×', '÷'};
opChar = op{randi(4)};
problemLabel = sprintf('%d%s%d=', a, opChar, b);
safeLabel = regexprep(problemLabel, '[<>:"/\\|?*]', '');
if ~isKey(existingLabels, safeLabel)
existingLabels(safeLabel) = true;
break;
end
end
% 生成随机结果
displayedResult = randi([10,200]);
fullEq = sprintf('%s%d', problemLabel, displayedResult);
% 生成图像
set(fig, 'Position', [100, 100, 600, 300]); % 固定尺寸
cla(ax);
text(ax, 0.5, 0.5, fullEq, ...
'FontSize', fontSize, ...
'HorizontalAlignment', 'center', ...
'VerticalAlignment', 'middle');
imgData = getframe(fig).cdata;
% 创建文件夹并保存
labelDir = fullfile(outputDir, safeLabel);
if ~exist(labelDir, 'dir')
mkdir(labelDir);
end
filename = sprintf('%04d.png', i);
imwrite(imgData, fullfile(labelDir, filename));
% 更新表格
newRow = {filename, problemLabel, '0', 'addition', '0'}; % 占位数据
dataTable = [dataTable; newRow];
end
end
% 保存元数据
writetable(dataTable, fullfile(outputDir, 'math_problems_metadata.csv'));
% 关闭图像窗口
close(fig);
% 验证生成结果
folders = dir(outputDir);
folderCount = sum([folders.isdir]) - 2; % 排除.和..
fprintf('最终生成文件夹数量: %d\n', folderCount);
if folderCount < numImages
fprintf('警告: 有重复标签未被检测到\n');
end
fprintf('数据集生成完成! 元数据保存为 math_problems_metadata.csv\n');
end
这是原来的数据集图片生成代码,请根据刚才的数据集要求进行修改
最新发布