如何使用Ruby编程从图像中删除背景并使其透明?

5
我有一堆产品图片,想要用Ruby编程自动去掉每个图片的背景。这里是我在imgur上放置的示例图像
我将在此处放一个示例让您看到,但我不想发布大量图像。这是最简单的图像。它只有一个白色背景,但有些产品具有更复杂的背景。 我知道在该图像上做这样的事情可能行不通,因此我希望找出问题并以某种方式优雅地失败,而不是真正删除背景并通知我。
我正在使用Ruby on Rails 3和CarrierWave作为我的上传处理程序。
这是否可能,或者我只能去除白色背景?

如果这个问题的预期结果是关于启发式颜色分析的学术讨论,我建议查看下面的答案。如果你想知道如何完成这项工作,请查看SaaS提供商Imagga(http://imagga.com/api/docs/smart-cropping-collage-slicing.html),他们提供这个精确的功能。 - Jason Malcolm
Google还有一个名为“Background Burner”的工具,它提供了一个JSON API来去除图像背景。 - wbharding
4个回答

6

以下是使用imagemagick的bash脚本来从图像中去除白色背景:

#!/bin/bash

# pass the image path, image name and threshold(used as a fuzz factor) to the bash script
IMGPATH=$1
IMGNAME=$2
THRESHOLD=$3

# start real
convert ${IMGPATH}${IMGNAME} \( +clone -fx 'p{0,0}' \)  -compose Difference  -composite   -modulate 100,0  +matte  ${IMGPATH}${IMGNAME}_difference.png

# remove the black, replace with transparency
convert ${IMGPATH}${IMGNAME}_difference.png -bordercolor white -border 1x1 -matte -fill none -fuzz 7% -draw 'matte 1,1 floodfill' -shave 1x1 ${IMGPATH}${IMGNAME}_removed_black.png
composite  -compose Dst_Over -tile pattern:checkerboard ${IMGPATH}${IMGNAME}_removed_black.png ${IMGPATH}${IMGNAME}_removed_black_check.png

# create the matte 
convert ${IMGPATH}${IMGNAME}_removed_black.png -channel matte -separate  +matte ${IMGPATH}${IMGNAME}_matte.png

# negate the colors
convert ${IMGPATH}${IMGNAME}_matte.png -negate -blur 0x1 ${IMGPATH}${IMGNAME}_matte-negated.png

# eroding matte(to remove remaining white border pixels from clipped foreground)
convert ${IMGPATH}${IMGNAME}_matte.png -morphology Erode Diamond ${IMGPATH}${IMGNAME}_erode_matte.png

# you are going for: white interior, black exterior
composite -compose CopyOpacity ${IMGPATH}${IMGNAME}_erode_matte.png ${IMGPATH}${IMGNAME} ${IMGPATH}${IMGNAME}_finished.png

#remove white border pixels
convert ${IMGPATH}${IMGNAME}_finished.png -bordercolor white -border 1x1 -matte -fill none -fuzz  ${THRESHOLD}% -draw 'matte 1,1 floodfill' -shave 1x1 ${IMGPATH}${IMGNAME}_final.png

#deleting extra files
rm ${IMGPATH}${IMGNAME}_difference.png
rm ${IMGPATH}${IMGNAME}_removed_black.png
rm ${IMGPATH}${IMGNAME}_removed_black_check.png
rm ${IMGPATH}${IMGNAME}_matte.png
rm ${IMGPATH}${IMGNAME}_matte-negated.png
rm ${IMGPATH}${IMGNAME}_finished.png

我遇到一个问题,就是无法将图像中的白色边框像素去除。通过腐蚀二进制掩模并刮去剩余像素可以解决这个问题。

来源:将白色转换为透明


这看起来非常有前途,可以解决我遇到的问题。然而,当我尝试使用这个脚本时,遇到了以下问题:'non-conforming drawing primitive definition `matte' @ error/draw.c/DrawImage/3269'。你有什么想法是什么原因导致的吗?我正在使用Mac和ImageMagick 7.0.5-0 Q16 x86_64。 - Viktor Nilsson
尝试仔细检查您的单/双引号。 看看这个答案是否有帮助:http://stackoverflow.com/a/8701126/2175224 - jahackbeth
2
谢谢您的评论!我尝试了那个方法,但是没有起作用,也不是问题所在。然而,我在某个地方读到这个脚本的语法相当老旧,而且似乎被alpha(?)所取代。因此,当我将'matte 1,1 floodfill'更改为'alpha 1,1 floodfill'时,它就起作用了!非常感谢您提供的脚本,在一些调整后完美地适用于我的用例! - Viktor Nilsson

3
请看http://www.imagemagick.org/Usage/masking/#bg_remove
对于纯色背景,您可能能够得到不错的效果,但是非纯色背景(例如您提供的图像中的背景)较为困难,我怀疑您无法找到一种适用于所有图像的单一方法。

1

ImageMagick是最可能的解决方案(也许与Rails的mini-magick gem一起使用),但正如您所建议的那样,在某些情况下,您不太可能得到良好的结果。简单地将所有白色像素变为透明很可能会留下锯齿状的边缘,在非白色背景上会非常明显。但是有许多令人惊讶的选项可以给您提供类似于PhotoShop或其他软件中可能具有的控制,您可以创建一个掩模,找到在色调、颜色或类似物的某个容差范围内的形状轮廓,然后将所有匹配的像素更改为透明。我认为您还必须更改为PNG格式,因为我不认为JPEG支持alpha-transparency。

CarrierWave是这种处理的正确工具--您可以使用其“versions”功能存储原始文件,并尝试使用不同参数进行几次自动化尝试(这将保存不同的文件而不触及原始文件)。

http://www.imagemagick.org/Usage/masking/#two_background 可能会给您一个开始。


检测一张图片是否可行怎么样?这是我的另一个担忧。我不想在一张注定会失败的图片上进行操作。 - hadees
如果没有已知的图像集(即所有图像都有白色背景),那么解决这个问题虽然可能是可行的,但不值得花费这样的努力——一个人可以在一瞬间选择最佳选项。因此,考虑使用亚马逊机械土耳其(Amazon Mechanical Turk),该平台具有API,可以向实际人员呈现图像版本,让他们选择最佳选项。看看MTurk——它非常适合这种问题。 - Tom Harrison

-1
假设你的意思是批处理一堆不相关的文件。据我理解,由于移除背景(通过拉出遮罩)是一个严重的非约束问题,必须需要用户输入。像蓝色或绿色屏幕这样的恒定背景颜色将使您能够使用免费程序(如gimp)来完成相当不错的工作,但除非您想阅读最前沿的科学期刊,否则没有什么可以做得很好。
泊松抠图

http://research.microsoft.com/apps/pubs/default.aspx?id=69117

OR

自然图像抠图的闭式解决方案

www.wisdom.weizmann.ac.il/~levina/papers/Matting-Levin-Lischinski-Weiss-CVPR06.pdf

后者提供了Matlab代码,供学术用途。但是这些都是严肃的数字计算器,可以在更大的文件上使用您的所有系统资源,正如从http://PixelFeather.com/download的试用版本pullmatt应用程序中可以确定的那样。顺便说一句,它比任何专有软件(包括Photoshop)都更好地解决了自然图像问题。


1
虽然这是一个关于哪些程序适合完成工作的好答案,但问题要求如何以编程方式完成;不幸的是,你的答案没有提供这方面的信息。 - Jesse
是的,公正的评论。当我阅读原帖时,我认为hadees并不一定打算批量处理一系列无关的图像,事实上他最后询问是否可以仅使用白色背景图像完成。即具有相同白色背景的相关图像。此外,批量处理显然是我的假设,甚至没有提到。我暗示对于无关的图像,批量处理将非常非常困难(几乎不可能)。 - user2337920

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接