【问题标题】:How to extract photos from JPG with white background?如何从JPG中提取白色背景的照片?
【发布时间】:2018-09-15 21:49:32
【问题描述】:

我有一个 JPG 文件,其中包含多张白色背景的照片。

我正在寻找一个 CLI 工具,它可以从源 JPG(不提供坐标)中提取照片到单独的 JPG 文件中,以保持质量和照片分辨率。

根据一些研究,我怀疑 ImageMagick 可以实现这一点,尽管不确定 CLI 命令是否正确。

如果有用,我在 OSX 10.13.2 上并安装了 ImageMagick 7.0.7-28。

【问题讨论】:

  • 我有两个使用 Imagemagick、multicrop 或 multicrop2 的 bash unix shell 脚本,可以做到这一点。前者在网格中搜索图像。后者为图像的每个连续区域。两者都应该工作。见fmwconcepts.com/imagemagick/index.php。它们只能在 Windows 10 内置 Unix 或 Cygwin 等 Unix 环境下运行在 Windows 上。它们也可以通过 PHP exec() 运行。您也可以通过将所有非白色转换为黑色,然后使用 Imagemagick 的 -connected-components 命令找到黑色区域,然后在这些边界框处裁剪您的原件。
  • 续:您的 Imagemagick 版本和平台是什么?
  • @fmw42 更新了操作系统和 Imagemagick 版本的问题

标签: image image-processing imagemagick command-line-interface


【解决方案1】:

这里有两种使用 Imagemagick 在 Unix 中执行此操作的方法。我刚刚从您的图表中裁剪出您的基本图像,因为我不确定它是否是您图像的一部分。如果它是图像的一部分,那么您必须先使用 -trim 将其修剪掉。

输入:

第一个是我的脚本,multicrop2:
(-f 10 是提取背景的模糊因子)
(-u 3 表示不尝试取消旋转结果)

multicrop2 -f 10 -u 3 image.jpg resulta.jpg

Processing Image 0
Initial Crop Box: 113x84+81+89

Processing Image 1
Initial Crop Box: 113x67+144+10

Processing Image 2
Initial Crop Box: 113x66+10+11

第二个是使用 Imagemagick -connected-componets(这是我在脚本中使用的)

这是做什么的:

1) fuzzy flood fill the background to transparent (since jpg is loss and does not preserve a uniform background.
2) change the color under the transparent to white and remove the transparency
3) change anything not white to black
4) apply -connected-components to throw out areas smaller than 400 pixel area and extract each bounding box and color
5) if the color is gray(0), i.e. black, then crop the original image to the bounding box and save to disk


OLDIFS=$IFS
IFS=$'\n'
arr=(`convert image.jpg -fuzz 10% -fill none -draw "matte 0,0 floodfill" \
-background white -alpha background -alpha off \
-fill black +opaque white -type bilevel \
-define connected-components:verbose=true \
-define connected-components:mean-color=true \
-define connected-components:area-threshold=400 \
-connected-components 4 null: | tail -n +2 | sed 's/^[ ]*//'`)
IFS=$OLDIFS
num=${#arr[*]}
j=0
for ((i=0; i<num; i++)); do
bbox=`echo "${arr[$i]}" | cut -d\  -f2`
color=`echo "${arr[$i]}" | cut -d\  -f5`
if [ "$color" = "gray(0)" ]; then
convert image.jpg -crop $bbox +repage resultb_$j.jpg
j=$((j+1))
fi
done


编辑:添加实际图像的处理

输入:

首先要注意的是,您的实际两张图像就在右侧,但那里有一个黑边。还有一个在上面。该黑色边缘连接了两个图像,因此 multicrop2 脚本不能轻易地将它们分开。因此,您需要将右侧剃掉足够多的像素才能去除该边缘。顶部还有边缘,如果需要,您可以将其剃掉。如果你这样做,你可以减少 -d​​ 参数。 -d 参数需要小于您要提取的最小图像的区域,并且大于任何其他次要噪声或区域顶部的条纹。所以我从右侧剪掉 20 个像素,然后使用 -d 值非常大的 multicrop2。我为 -f 选择了一个值为 8 的值,由于非恒定背景,这似乎在一个相当窄的范围内。您可以添加 -m save 来查看脚本创建的掩码,以查看两个图像之间的良好分离。我在 -c 20,20 处播种处理以避免图像顶部的黑色边框,以便脚本可以很好地测量洪水填充步骤的背景颜色。

convert test.jpeg -gravity east -chop 20x0 tmp.png
multicrop2 -c 20,20 -f 8 -d 100000 tmp.png result.jpg

Processing Image 0
Initial Crop Box: 2319x1627+968+2153

Processing Image 1
Initial Crop Box: 2293x1611+994+436

【讨论】:

  • 感谢@fmw42,不幸的是,我对现实生活中的案例不太幸运。一直在调整命令参数,但进展不快。例如。试图提取以下照片 - dropbox.com/s/9qh1vg7mw2m197p/test.jpeg?dl=0
  • 为了将来参考,最好添加实际示例而不是“类似”。当您保存为 jpg 时,文件分辨率会发生变化。如果您的原始图像的格式比 jpg 更好,则损失会更少。您可能会遇到问题,因为您的两个边缘有黑色边框。我假设您无法重新扫描照片?
  • 我已经修改了我的答案,以展示一个将 multicrop2 与您新提供的实际输入图像一起使用的示例。
猜你喜欢
  • 2013-04-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-29
  • 2018-10-04
  • 2019-10-30
相关资源
最近更新 更多