书法图片自动扣字的批处理
本程序会根据原文字图片,自动扣字并生成黑字、红字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 output
exit /b 1
)
if "%~2"=="" (
echo 请输入输出文件名前缀
echo 用法: %0 input.jpg output
exit /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" ]; then
echo "用法: $0 input.jpg output_prefix"
exit 1
fi
input="$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" ]; then
echo "无法获取图像的宽度和高度"
exit 1
fi
echo "Width = $width, Height = $height"
# 计算总像素数量
total_pixels=$((width * height))
if [ "$total_pixels" -le 0 ]; then
echo "无效的像素总数"
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 ]; }; then
echo "白色占比 $mean_color > 0.5, 判断原图为黑字"
else
magick "$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"), // stdin
1 => array("pipe", "w"), // stdout
2 => array("pipe", "w") // stderr
);
$process = proc_open($command, $descriptorspec, $pipes);
if (is_resource($process)) {
// 关闭 stdin
fclose($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"), // stdin
1 => array("pipe", "w"), // stdout
2 => array("pipe", "w") // stderr
);
$process = proc_open($command, $descriptorspec, $pipes);
if (is_resource($process)) {
// 关闭 stdin
fclose($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";
}
?>