是否可以使用 ImageMagick 等现有工具自动从漫画中提取图块,或者我应该自己编写一个工具?
我已经使用 ImageMagick 看到了答案(使用 imagemagick 如何将图像分割成多个单独的图像?,https://superuser.com/questions/1308928/how-to-automatically-crop-and-cut- an-image-into-several-images-using-imagemagick/1308953#1308953)但在我的情况下,图块可以具有不同的尺寸(高度可以改变)。
彼此下方始终有 1 个图块(仅 1 列),并且每个图块都由相同颜色的一些空间分隔(可以在图像中使用黑色、灰色或白色的水平颜色渐变来间隔图块),因此应该通过查看具有相同像素颜色的水平线,可以检测何时有新图块并提取它们。
理想情况下,如果漫画有 2 个或更多列,其中的图块高度不同(这可能会更复杂一些,因为不一定有具有相同像素颜色的完整水平线),也应该可以提取图块。
更新:您可以根据要求找到我在下面制作的快速示例。有些漫画有一些字符和文本气泡从图块中出来,这使得无法比较水平线上的像素,所以我特意在示例中添加了它。我还添加了另一列和具有不同宽度或高度的图块,以便获得一个示例,其中包含漫画中可以找到的内容的摘要。
以下是如何在 ImageMagick 中执行此操作。但我注意到你的图可能不具有代表性。首先,我期待的是垂直堆叠的框架,而不是随机排列。其次,部分图形在 X 或 Y 上重叠,以便边界框重叠。我使用连接组件来提取边界框。然后我只需循环边界框并裁剪图像。
输入:
Unix 语法:
bboxArr=(`convert -quiet boxes.png +repage -threshold 50% \
-morphology open square:3 -type bilevel \
-define connected-components:exclude-header=true \
-define connected-components:verbose=true \
-define connected-components:area-threshold=1500 \
-define connected-components:mean-color=true \
-connected-components 4 null: | grep "gray(0)" | awk '{print $2}'`)
num=${#bboxArr[*]}
for ((i=0; i<num; i++)); do
bbox="${bboxArr[$i]}"
echo "$bbox;"
convert -quiet boxes.png +repage -crop "$bbox" +repage boxes_$i.png
done
这是一个更好的例子:
bboxArr=(`convert -quiet DoomPatrol1.jpg +repage -negate -threshold 25% -type bilevel \
-define connected-components:exclude-header=true \
-define connected-components:verbose=true \
-define connected-components:area-threshold=20000 \
-define connected-components:mean-color=true \
-connected-components 8 null: | grep "gray(255)" | awk '{print $2}'`)
num=${#bboxArr}
for ((i=0; i<num; i++)); do
bbox="${bboxArr[$i]}"
echo "$bbox;"
convert -quiet DoomPatrol1.jpg +repage -crop "$bbox" +repage boxes_$i.png
done
这里有一些 powershell 魔法可以使长网络漫画变短(使用 ure idea):
# Function to process a single file
function ProcessFile {
param (
[string]$originalFilePath,
[string]$outputDir
)
# Get bounding boxes and store in $bboxArr
$originalFileNameWithoutExtension = [System.IO.Path]::GetFileNameWithoutExtension($originalFilePath)
$originalFileDirectory = [System.IO.Path]::GetDirectoryName($originalFilePath)
$output = magick convert -quiet $originalFilePath +repage -negate -threshold 15% `
-morphology Dilate Rectangle:1x30+0+0 `
-type bilevel `
-define connected-components:exclude-header=true `
-define connected-components:verbose=true `
-define connected-components:area-threshold=20000 `
-define connected-components:mean-color=true `
-connected-components 8 null:
$bboxArr = @()
$output -split "`n" | Select-String -Pattern "gray\(255\)" | ForEach-Object {
if ($_ -match "(\d+x\d+\+\d+\+\d+)") {
$bboxArr += $matches[1]
}
}
# Initialize empty array to store final bounding boxes
$finalBboxArr = @()
# Filter out smaller boxes likely to be text
foreach ($bbox in $bboxArr) {
$splitBbox = $bbox -split "[x\+]"
$width = [int]$splitBbox[0]
$height = [int]$splitBbox[1]
if ($width -gt 350 -and $height -gt 350) {
$finalBboxArr += $bbox
}
}
# Initialize an array to hold groups of bounding boxes
$bboxGroups = @()
# Sort bounding boxes by their y coordinates
$sortedBboxArr = $finalBboxArr | Sort-Object {
$split = $_ -split "[x\+]"
[int]$split[3]
}
# Group bounding boxes while keeping the total height <= 1440
$currentGroup = @()
$currentGroupHeight = 0
foreach ($bbox in $sortedBboxArr) {
$split = $bbox -split "[x\+]"
$currentY = [int]$split[3]
$height = [int]$split[1]
if (($currentGroupHeight + $height) -le 1440) {
$currentGroup += $bbox
$currentGroupHeight += $height
} else {
if ($currentGroup.Length -gt 0) {
$bboxGroups += ,@($currentGroup)
}
$currentGroup = @($bbox)
$currentGroupHeight = $height
}
}
# Add the last group if it's not empty
if ($currentGroup.Length -gt 0) {
$bboxGroups += ,@($currentGroup)
}
# Crop and concatenate images based on groups of bounding boxes
for ($i = 0; $i -lt $bboxGroups.Length; $i++) {
$currentGroup = $bboxGroups[$i]
$tmpFiles = @()
for ($j = 0; $j -lt $currentGroup.Length; $j++) {
$bbox = $currentGroup[$j]
$tmpFileName = "${originalFileDirectory}\${originalFileNameWithoutExtension}_tmp_${i}_${j}.png"
magick convert -quiet $originalFilePath +repage -crop $bbox +repage $tmpFileName
$tmpFiles += $tmpFileName
}
$newFileName = "${outputDir}\${originalFileNameWithoutExtension}_${i}.png"
magick convert -append $tmpFiles $newFileName
Remove-Item $tmpFiles # Delete temporary files
}
}
# Main part of the script
$inputDir = "C:\my_folder_with_images_in_webp_format"
$outputDir = "${inputDir}-cropped"
# Create output directory if it doesn't exist
if (-not (Test-Path $outputDir)) {
New-Item -ItemType Directory -Force -Path $outputDir
}
# Loop through each .webp file in the input directory
Get-ChildItem -Path $inputDir -Filter *.webp | ForEach-Object {
$originalFilePath = $_.FullName
# Call the function to process each file
ProcessFile -originalFilePath $originalFilePath -outputDir $outputDir
}