dre*_*ves 81 wolfram-mathematica image image-processing masking
我们尝试在Mathematica中执行以下操作:
RMagick从图像中删除白色背景并使其透明
但实际照片看起来很糟糕(就像图像周围有光环).
这是我们到目前为止所尝试的:
unground0[img_] := With[{mask = ChanVeseBinarize[img, TargetColor->{1.,1.,1.}]},
Rasterize[SetAlphaChannel[img, ImageApply[1-#&, mask]], Background->None]]]
Run Code Online (Sandbox Code Playgroud)
这是一个例子.
原始图片:

没有背景的白色背景替换图像(或者,为了演示目的,粉红色背景):

什么想法摆脱光环?调整像LevelPenalty这样的东西,我只能以丢失一些图像为代价来消除光环.
编辑:所以我可以比较赏金的解决方案,请像上面那样构建你的解决方案,即一个名为unground的自包含函数,它可以获取图像并返回具有透明背景的图像.非常感谢大家!
Sza*_*lcs 48
此函数实现了Mark Ransom描述的反向混合,以获得额外的小但可见的改进:
reverseBlend[img_Image, alpha_Image, bgcolor_] :=
With[
{c = ImageData[img],
a = ImageData[alpha] + 0.0001, (* this is to minimize ComplexInfinitys and considerably improve performance *)
bc = bgcolor},
ImageClip@
Image[Quiet[(c - bc (1 - a))/a, {Power::infy,
Infinity::indet}] /. {ComplexInfinity -> 0, Indeterminate -> 0}]
]
Run Code Online (Sandbox Code Playgroud)
这是背景删除功能.该threshold参数用于图像的初始二值化,minSizeCorrection用于调整二值化后要删除的小垃圾组件的大小限制.
removeWhiteBackground[img_, threshold_: 0.05, minSizeCorrection_: 1] :=
Module[
{dim, bigmask, mask, edgemask, alpha},
dim = ImageDimensions[img];
bigmask =
DeleteSmallComponents[
ColorNegate@
MorphologicalBinarize[ColorNegate@ImageResize[img, 4 dim], threshold],
Round[minSizeCorrection Times @@ dim/5]];
mask = ColorNegate@
ImageResize[ColorConvert[bigmask, "GrayScale"], dim];
edgemask =
ImageResize[
ImageAdjust@DistanceTransform@Dilation[EdgeDetect[bigmask, 2], 6],
dim];
alpha =
ImageAdd[
ImageSubtract[
ImageMultiply[ColorNegate@ColorConvert[img, "GrayScale"],
edgemask], ImageMultiply[mask, edgemask]], mask];
SetAlphaChannel[reverseBlend[img, alpha, 1], alpha]
]
Run Code Online (Sandbox Code Playgroud)
测试功能:
img = Import["http://i.stack.imgur.com/k7E1F.png"];
background =
ImageCrop[
Import["http://cdn.zmescience.com/wp-content/uploads/2011/06/\
forest2.jpg"], ImageDimensions[img]];
result = removeWhiteBackground[img]
ImageCompose[background, result]
Rasterize[result, Background -> Red]
Rasterize[result, Background -> Black]
Run Code Online (Sandbox Code Playgroud)
它的工作原理简要说明:
选择您喜欢的binariaztion方法,生成相对精确的锐边
将其应用于放大的图像,然后将获得的缩小mask到原始大小.这给了我们抗锯齿.大部分工作已经完成.
对于一个小的改进,混合图像上使用其负如α的亮度的背景,然后在混合的原始获得的图像中的薄区域周围的边缘(edgemask),以减少白色像素的边缘上的可见度.计算对应于这些操作的alpha通道(有点神秘的ImageMultiply/Add表达).
现在我们估算了alpha通道,这样我们就可以进行反向混合.
步骤3和4没有那么多改善,但差异是显而易见的.
Dr.*_*ius 44
也许,取决于您需要的边缘质量:
img = Import@"http://i.stack.imgur.com/k7E1F.png";
mask = ChanVeseBinarize[img, TargetColor -> {1., 1., 1.}, "LengthPenalty" -> 10]
mask1 = Blur[Erosion[ColorNegate[mask], 2], 5]
Rasterize[SetAlphaChannel[img, mask1], Background -> None]
Run Code Online (Sandbox Code Playgroud)

编辑
img2 = Import@"http://i.stack.imgur.com/k7E1F.png";
(*key point:scale up image to smooth the edges*)
img = ImageResize[img2, 4 ImageDimensions[img2]];
mask = ChanVeseBinarize[img, TargetColor -> {1., 1., 1.}, "LengthPenalty" -> 10];
mask1 = Blur[Erosion[ColorNegate[mask], 8], 10];
f[col_] := Rasterize[SetAlphaChannel[img, mask1], Background -> col,
ImageSize -> ImageDimensions@img2]
GraphicsGrid[{{f@Red, f@Blue, f@Green}}]
Run Code Online (Sandbox Code Playgroud)
编辑2
只是为了了解图像中光晕和背景缺陷的程度:
img = Import@"http://i.stack.imgur.com/k7E1F.png";
Join[{img}, MapThread[Binarize, {ColorSeparate[img, "HSB"], {.01, .01, .99}}]]
Run Code Online (Sandbox Code Playgroud)

ColorNegate@ImageAdd[EntropyFilter[img, 1] // ImageAdjust, ColorNegate@img]
Run Code Online (Sandbox Code Playgroud)

Mar*_*som 22
我将会说一般,而不是特别提到Mathematica.我不知道这些操作是困难还是微不足道.
第一步是估计图像边缘像素的alpha(透明度)级别.现在你正在使用严格的阈值,因此alpha是0%完全透明或100%完全不透明.你应该在背景的总白色和无可争议的图像的一部分颜色之间定义一个范围,并设置一个合适的比例 - 如果它的背景颜色更接近它的低alpha值,如果它更接近更暗的截止点那么它就是高alpha.之后,您可以根据周围的alpha值进行调整 - 像素被透明度包围得越多,就越有可能透明.
获得alpha值后,您需要进行反向混合以获得正确的颜色.当图像在背景上显示时,它将根据alpha值使用公式c = bc*(1-a)+fc*a进行混合,其中bc背景颜色fc为背景颜色,并且是前景色.在你的情况下,背景是白色的(255,255,255),前景色是未知的,所以我们颠倒了公式:fc = (c - bc*(1-a))/a.当a=0公式要求除以零时,但颜色无关紧要,所以只使用黑色或白色.
JxB*_*JxB 11
这是尝试实施Mark Ransom的方法,在belisarius的面具生成的帮助下:
找到对象的边界:
img1 = SetAlphaChannel[img, 1];
erosionamount=2;
mb = ColorNegate@ChanVeseBinarize[img, TargetColor -> {1., 1., 1},
"LengthPenalty" -> 10];
edge = ImageSubtract[Dilation[mb, 2], Erosion[mb, erosionamount]];
ImageApply[{1, 0, 0} &, img, Masking ->edge]
Run Code Online (Sandbox Code Playgroud)

设置alpha值:
edgealpha = ImageMultiply[ImageFilter[(1 - Mean[Flatten[#]]^5) &,
ColorConvert[img, "GrayScale"], 2, Masking -> edge], edge];
imagealpha = ImageAdd[edgealpha, Erosion[mb, erosionamount]];
img2 = SetAlphaChannel[img, imagealpha];
Run Code Online (Sandbox Code Playgroud)
反色混合:
img3 = ImageApply[Module[{c, \[Alpha], bc, fc},
bc = {1, 1, 1};
c = {#[[1]], #[[2]], #[[3]]};
\[Alpha] = #[[4]];
If[\[Alpha] > 0, Flatten[{(c - bc (1 - \[Alpha]))/\[Alpha], \[Alpha]}], {0., 0.,
0., 0}]] &, img2];
Show[img3, Background -> Pink]
Run Code Online (Sandbox Code Playgroud)

注意一些边缘是如何有白色模糊的?将其与第一张图像中的红色轮廓进行比较.我们需要更好的边缘检测器.增加侵蚀量有助于模糊,但是其他侧面变得太透明,因此边缘掩模的宽度存在折衷.不过,考虑到本身没有模糊操作,这是非常好的.
在各种图像上运行算法以测试其稳健性,看看它是多么自动化将是有益的.
cor*_*ion 10
只是作为一个初学者来玩 - 令人惊讶的是有多少工具可用.
b = ColorNegate[
GaussianFilter[MorphologicalBinarize[i, {0.96, 0.999}], 6]];
c = SetAlphaChannel[i, b];
Show[Graphics[Rectangle[], Background -> Orange,
PlotRangePadding -> None], c]
Run Code Online (Sandbox Code Playgroud)

我对图像处理完全陌生,但这是我在使用版本8的新形态图像处理功能后得到的结果:
mask = DeleteSmallComponents[
ColorNegate@
Image[MorphologicalComponents[ColorNegate@img, .062,
Method -> "Convex"], "Bit"], 10000];
Show[Graphics[Rectangle[], Background -> Red,
PlotRangePadding -> None], SetAlphaChannel[img, ColorNegate@mask]]
Run Code Online (Sandbox Code Playgroud)

我建议使用Photoshop进行此操作并保存为PNG.