本程序会根据原文字图片,自动扣字并生成黑字、红字2个透明的png图片,原图片黑字或白字均可。运行的话需要先安装好 ImageMagick-7.1.1-37
用法与生成效果举例:
a.jpg 白字 转 黑、红扣字png:
b.jpg 黑字 转 黑、红扣字png:
分享脚本如下:
windows版:(花好几个小时写好的)
:: # 先安装好 ImageMagick-7.1.1-37@echo off
setlocal EnableDelayedExpansion:: 检查输入参数
if "%~1"=="" (echo 请输入输入文件名echo 用法: %0 input.jpg outputexit /b 1
)if "%~2"=="" (echo 请输入输出文件名前缀echo 用法: %0 input.jpg outputexit /b 1
):: 定义输入和输出文件
set "input=%~1"
set "output_prefix=%~2"
set "tmp_jpg=%output_prefix%_binary.jpg"
set "black_output=%output_prefix%_b.png"
set "red_output=%output_prefix%_r.png":: 亮度与对比度调整
magick "%input%" -brightness-contrast 0x80 "%tmp_jpg%"
magick "%tmp_jpg%" -brightness-contrast 0x80 "%tmp_jpg%":: 转为灰度
:: magick "%tmp_jpg%" -colorspace Gray "%tmp_jpg%":: 去噪音操作
magick "%tmp_jpg%" -morphology Erode Octagon:1 -morphology Dilate Octagon:1 "%tmp_jpg%":: 二值化处理
magick "%tmp_jpg%" -threshold 50%% "%tmp_jpg%":: 获取图像的宽度和高度
for /f "tokens=1,2 delims=x" %%a in ('magick identify -format "%%wx%%h" "%tmp_jpg%"') do (set "width=%%a"set "height=%%b"
)if "%width%"=="" (echo 无法获取图像的宽度和高度exit /b 1
)echo Width = %width%, Height = %height%:: 计算总像素数量
set /a total_pixels=%width% * %height%
if %total_pixels% LEQ 0 (echo 无效的像素总数exit /b 1
):: 计算白色像素数量
for /F "tokens=*" %%i in ('magick "%tmp_jpg%" -format "%%[fx:mean]" info:') do (set "mean_color=%%i"
):: 提取整数部分和小数部分
for /F "tokens=1,2 delims=." %%a in ("%mean_color%") do (set "int_part=%%a"set "dec_part=%%b"
):: 默认小数部分为0
if not defined dec_part set "dec_part=00":: 判断小数部分是否大于 50(即 0.50)
set "is_greater=0"
if "%int_part%" GEQ "1" (set "is_greater=1"
) else (if "%int_part%" EQU "0" (if "%dec_part:~0,2%" GEQ "50" (set "is_greater=1"))
):: 输出结果
if %is_greater% EQU 1 (echo 白色占比 %mean_color% > 0.5,判断原图为黑字
) else (magick "%tmp_jpg%" -negate "%tmp_jpg%"echo 白色占比 %mean_color% ≤ 0.5,判断原图为白字,已作反转
):: 存黑字png
magick "%tmp_jpg%" -fuzz 5%% -fill none -opaque white "%black_output%":: 转回成rgb
magick "%tmp_jpg%" -type TrueColor "%tmp_jpg%":: 黑字转红色
magick "%tmp_jpg%" -fuzz 35%% -fill red -opaque black "%tmp_jpg%":: 存红字png
magick "%tmp_jpg%" -fuzz 5%% -fill none -opaque white "%red_output%":: 删除临时文件
del /q "%tmp_jpg%"echo 处理完成,生成文件: %black_output% 和 %red_output%endlocal
转linux版:(暂未测试)
#!/bin/bash# 先安装好 ImageMagick-7.1.1-37# 检查输入参数
if [ -z "$1" ] || [ -z "$2" ]; thenecho "用法: $0 input.jpg output_prefix"exit 1
fiinput="$1"
output_prefix="$2"
tmp_jpg="${output_prefix}_binary.jpg"
black_output="${output_prefix}_b.png"
red_output="${output_prefix}_r.png"# 亮度与对比度调整
magick "$input" -brightness-contrast 0x80 "$tmp_jpg"
magick "$tmp_jpg" -brightness-contrast 0x80 "$tmp_jpg"# 去噪音操作
magick "$tmp_jpg" -morphology Erode Octagon:1 -morphology Dilate Octagon:1 "$tmp_jpg"# 二值化处理
magick "$tmp_jpg" -threshold 50% "$tmp_jpg"# 获取图像的宽度和高度
dimensions=$(magick identify -format "%wx%h" "$tmp_jpg")
width=$(echo "$dimensions" | cut -d'x' -f1)
height=$(echo "$dimensions" | cut -d'x' -f2)if [ -z "$width" ] || [ -z "$height" ]; thenecho "无法获取图像的宽度和高度"exit 1
fiecho "Width = $width, Height = $height"# 计算总像素数量
total_pixels=$((width * height))
if [ "$total_pixels" -le 0 ]; thenecho "无效的像素总数"exit 1
fi# 计算白色像素数量
mean_color=$(magick "$tmp_jpg" -format "%[fx:mean]" info:)
mean_color_int=${mean_color%.*}
mean_color_dec=${mean_color#*.}
mean_color_dec=${mean_color_dec:0:2}# 判断小数部分是否大于 50(即 0.50)
if [ "$mean_color_int" -ge 1 ] || { [ "$mean_color_int" -eq 0 ] && [ "$mean_color_dec" -ge 50 ]; }; thenecho "白色占比 $mean_color > 0.5, 判断原图为黑字"
elsemagick "$tmp_jpg" -negate "$tmp_jpg"echo "白色占比 $mean_color ≤ 0.5, 判断原图为白字,已作反转"
fi# 存黑字png
magick "$tmp_jpg" -fuzz 5% -fill none -opaque white "$black_output"# 转回成rgb
magick "$tmp_jpg" -type TrueColor "$tmp_jpg"# 黑字转红色
magick "$tmp_jpg" -fuzz 35% -fill red -opaque black "$tmp_jpg"# 存红字png
magick "$tmp_jpg" -fuzz 5% -fill none -opaque white "$red_output"# 删除临时文件
rm -f "$tmp_jpg"echo "处理完成,生成文件: $black_output 和 $red_output"
转PHP版
(先转一下编码,还有一些问题,貌似是我安装的Imagick
版本的问题,有的方法不支持)
在 PHP 后端实现类似的图像处理功能,可以使用Imagick
扩展来操作图像。Imagick
是 PHP 的一个扩展,用于处理图像,支持许多图像处理操作,如调整亮度、对比度、二值化等。
<?php// 检查输入参数
if ($argc < 3) {echo "用法: php script.php input.jpg output_prefix\n";exit(1);
}$input = $argv[1];
$outputPrefix = $argv[2];
$tmpJpg = $outputPrefix . '_binary.jpg';
$blackOutput = $outputPrefix . '_b.png';
$redOutput = $outputPrefix . '_r.png';try {// 创建 Imagick 对象$image = new Imagick($input);// 亮度与对比度调整$image->modulateImage(100, 100, 160); // 模拟亮度与对比度调整// 去噪音操作$image->morphologyImage(Imagick::MORPHOLOGY_ERODE, Imagick::MORPHOLOGY_OCTAGON, 1);$image->morphologyImage(Imagick::MORPHOLOGY_DILATE, Imagick::MORPHOLOGY_OCTAGON, 1);// 二值化处理$image->thresholdImage(0.5 * Imagick::getQuantum());// 获取图像的宽度和高度$width = $image->getImageWidth();$height = $image->getImageHeight();if ($width === false || $height === false) {echo "无法获取图像的宽度和高度\n";exit(1);}echo "Width = $width, Height = $height\n";// 计算图像的平均颜色值$image->normalizeImage();$meanColor = $image->getImageHistogram();$totalPixels = $width * $height;if ($totalPixels <= 0) {echo "无效的像素总数\n";exit(1);}// 获取平均颜色$meanColor = array_reduce($meanColor, function($carry, $pixel) {$carry['r'] += $pixel->getColorValue(Imagick::COLOR_RED);$carry['g'] += $pixel->getColorValue(Imagick::COLOR_GREEN);$carry['b'] += $pixel->getColorValue(Imagick::COLOR_BLUE);return $carry;}, ['r' => 0, 'g' => 0, 'b' => 0]);$meanColor['r'] /= count($meanColor);$meanColor['g'] /= count($meanColor);$meanColor['b'] /= count($meanColor);$meanValue = ($meanColor['r'] + $meanColor['g'] + $meanColor['b']) / 3;if ($meanValue > 0.5) {echo "平均颜色值大于0.5, 原图为白底黑字\n";} else {$image->negateImage();echo "平均颜色值小于或等于0.5, 原图为黑底白字, 已反转\n";}// 存黑字PNG$image->writeImage($blackOutput);// 转回成RGB$image->setImageType(Imagick::IMGTYPE_TRUECOLORMATTE);// 黑字转红色$image->colorizeImage(new ImagickPixel('red'), 1);$image->writeImage($redOutput);// 删除临时文件(如果有的话)echo "处理完成,生成文件: $blackOutput 和 $redOutput\n";} catch (ImagickException $e) {echo 'Imagick 错误: ' . $e->getMessage() . "\n";exit(1);
}?>
PHP中调用bat或sh
前面一直尝试用Imagick
扩展来操作图像,但可能是Imagick
版本变化的关系,一直没有成功。改用调用bat或sh的方式实现。
<?php
// 检查输入参数
if ($argc < 3) {echo "用法: php toPng.php input.jpg output_prefix\n";exit(1);
}// 验证输入文件路径
$inputFile = escapeshellarg($argv[1]);
$outputPrefix = escapeshellarg($argv[2]);
$blackOutput = escapeshellarg($outputPrefix . '_b.png');
$redOutput = escapeshellarg($outputPrefix . '_r.png');// 批处理文件的路径,确保这是正确的路径
$batFile = './toPng.bat'; // 如果在当前目录
// $batFile = 'C:/path/to/your/toPng.bat'; // 如果不在当前目录,使用绝对路径// 不需要再次使用 escapeshellarg,因为我们已经验证了输入
$command = sprintf('"%s" "%s" "%s"', $batFile, $inputFile, $outputPrefix);$descriptorspec = array(0 => array("pipe", "r"), // stdin1 => array("pipe", "w"), // stdout2 => array("pipe", "w") // stderr
);$process = proc_open($command, $descriptorspec, $pipes);if (is_resource($process)) {// 关闭 stdinfclose($pipes[0]);// 读取 stdout$output = stream_get_contents($pipes[1]);fclose($pipes[1]);// 读取 stderr$error = stream_get_contents($pipes[2]);fclose($pipes[2]);// 关闭进程$returnVar = proc_close($process);// 检查执行结果if ($returnVar === 0) {echo "图像处理成功,生成文件: {$blackOutput} 和 {$redOutput}\n";} else {echo "图像处理失败,返回码: $returnVar\n";echo "错误输出:\n" . $error;}
} else {echo "无法打开进程\n";
}?>
<?php
// 检查输入参数
if ($argc < 3) {echo "用法: php script.php input_file output_prefix\n";exit(1);
}// 验证输入文件路径
$inputFile = escapeshellarg($argv[1]);
$outputPrefix = escapeshellarg($argv[2]);
$blackOutput = escapeshellarg($outputPrefix . '_b.png');
$redOutput = escapeshellarg($outputPrefix . '_r.png');// shell 脚本的路径
$shFile = escapeshellarg('./toPng.sh'); // 确保这是正确的路径// 构造命令
$command = sprintf('sh %s %s %s', $shFile, $inputFile, $outputPrefix);$descriptorspec = array(0 => array("pipe", "r"), // stdin1 => array("pipe", "w"), // stdout2 => array("pipe", "w") // stderr
);$process = proc_open($command, $descriptorspec, $pipes);if (is_resource($process)) {// 关闭 stdinfclose($pipes[0]);// 读取 stdout$output = stream_get_contents($pipes[1]);fclose($pipes[1]);// 读取 stderr$error = stream_get_contents($pipes[2]);fclose($pipes[2]);// 关闭进程$returnVar = proc_close($process);// 检查执行结果if ($returnVar === 0) {echo "图像处理成功,生成文件: {$blackOutput} 和 {$redOutput}\n";} else {echo "图像处理失败,返回码: $returnVar\n";echo "错误输出:\n" . $error;}
} else {echo "无法打开进程\n";
}?>