program tip

이미지에서 흰색 배경을 제거하고 투명하게 만들기

radiobox 2020. 10. 5. 07:49
반응형

이미지에서 흰색 배경을 제거하고 투명하게 만들기


Mathematica에서 다음을 수행하려고합니다.
RMagick은 이미지에서 흰색 배경을 제거하고 투명하게 만듭니다.

그러나 실제 사진에서는 (이미지 주위에 후광이있는 것처럼) 형편 없게 보입니다.

지금까지 시도한 내용은 다음과 같습니다.

unground0[img_] := With[{mask = ChanVeseBinarize[img, TargetColor->{1.,1.,1.}]},
  Rasterize[SetAlphaChannel[img, ImageApply[1-#&, mask]], Background->None]]]

다음은 그 기능의 예입니다.

원본 이미지 :

원본 이미지

흰색 배경이 배경없이 대체 된 이미지 (또는 여기에서 데모 목적으로 분홍색 배경) :

투명한 배경이있는 이미지-실제로 여기에는 분홍색 배경이 있습니다.

그 후광을 없애기위한 아이디어가 있습니까? LevelPenalty와 같은 것을 조정하면 이미지의 일부를 잃는 대신 후광을 없앨 수 있습니다.

편집 : 그래서 현상금에 대한 솔루션을 비교할 수 있습니다. 위와 같이 솔루션을 구성하십시오. 즉 이미지를 가져 와서 투명한 배경으로 이미지를 반환하는 unground-something이라는 자체 포함 함수입니다.


아마도 필요한 가장자리 품질에 따라 다음과 같습니다.

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]

여기에 이미지 설명 입력

편집하다

Stealing a bit from @Szabolcs

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}}]

여기에 이미지 설명 입력

클릭하면 확대됩니다

편집 2

이미지 후광 과 배경 결함 의 정도에 대한 아이디어를 얻으려면 :

img = Import@"http://i.stack.imgur.com/k7E1F.png";
Join[{img}, MapThread[Binarize, {ColorSeparate[img, "HSB"], {.01, .01, .99}}]]

여기에 이미지 설명 입력

ColorNegate@ImageAdd[EntropyFilter[img, 1] // ImageAdjust, ColorNegate@img]

여기에 이미지 설명 입력


이 기능은 작지만 눈에 띄는 개선을 위해 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}]
  ]

배경 제거 기능입니다. 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]
  ]

기능 테스트 :

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]

견본

작동 원리에 대한 간략한 설명 :

  1. 비교적 정확한 날카로운 모서리를 생성하는 선호하는 이진화 방법을 선택하십시오.

  2. 확대 된 이미지에 적용한 다음 얻은 이미지 mask를 원래 크기 로 축소합니다 . 이것은 우리에게 안티 앨리어싱을 제공합니다. 대부분의 작업이 완료되었습니다.

  3. 약간 개선하려면 네거티브의 밝기를 알파로 사용하여 이미지를 배경에 혼합 한 다음 얻은 이미지를 가장자리 주변의 얇은 영역 ( edgemask) 에서 원본 위에 혼합하여 가장자리 의 흰색 픽셀의 가시성을 줄입니다. 이러한 연산에 해당하는 알파 채널이 계산됩니다 (다소 비밀스러운 ImageMultiply/Add표현).

  4. 이제 우리는 역 블렌드를 할 수 있도록 알파 채널의 추정치를 얻었습니다.

3 단계와 4 단계는 그다지 개선되지 않지만 차이는 눈에 보입니다.


저는 Mathematica와 관련하여 구체적으로 언급하지 않고 일반적으로 말할 것입니다. 나는 이러한 작업이 어렵거나 사소한 것인지 전혀 모릅니다.

첫 번째 단계는 이미지 가장자리의 픽셀에 대한 알파 (투명도) 수준을 추정하는 것입니다. 지금은 엄격한 임계 값을 사용하고 있으므로 알파는 완전 투명 0 % 또는 완전 불투명 100 %입니다. 배경의 전체 흰색과 이미지의 일부인 색상 사이의 범위를 정의하고 적절한 비율을 설정해야합니다. 색상이 배경에 더 가까우면 알파가 낮고 더 어두운 컷오프에 더 가까우면 적절한 비율을 설정해야합니다. 높은 알파. 그 후에 주변 알파 값을 기준으로 조정할 수 있습니다. 픽셀이 투명도로 둘러싸 일수록 자체적으로 투명해질 가능성이 높습니다.

알파 값이 있으면 적절한 색상을 얻기 위해 역 블렌드를 수행해야합니다. 이미지가 배경 위에 표시 될 때 수식하여 알파 값에 따라 배합 배경색이고 전경 색상이다. 귀하의 경우 배경은 흰색 (255,255,255)이고 전경색은 알 수 없으므로 공식을 반대로 바꿉니다 . 수식 0으로 나누기를 요구하지만, 색상이 문제 어쨌든 그래서 그냥 검은 색 또는 흰색으로 사용하지 않습니다.c = bc*(1-a)+fc*abcfcfc = (c - bc*(1-a))/aa=0


다음은 belisarius의 마스크 생성의 도움을 받아 Mark Ransom의 접근 방식을 구현하는 시도입니다.

개체의 경계를 찾습니다.

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]

그림 가장자리

알파 값을 설정합니다.

edgealpha = ImageMultiply[ImageFilter[(1 - Mean[Flatten[#]]^5) &, 
   ColorConvert[img, "GrayScale"], 2, Masking -> edge], edge];
imagealpha = ImageAdd[edgealpha, Erosion[mb, erosionamount]];
img2 = SetAlphaChannel[img, imagealpha];

반전 색상 혼합 :

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]

분홍색 배경

일부 가장자리에 흰색 보풀이있는 것을 알 수 있습니까? 첫 번째 이미지의 빨간색 윤곽선과 비교하십시오. 더 나은 에지 감지기가 필요합니다. 침 식량을 늘리면 보풀이 생기는 데 도움이되지만 다른면이 너무 투명 해 지므로 가장자리 마스크의 너비에 상충 관계가 있습니다. 하지만 블러 작업 자체가 없다는 점을 감안하면 꽤 좋습니다.

다양한 이미지에서 알고리즘을 실행하여 견고성을 테스트하고 얼마나 자동인지 확인하는 것이 좋습니다.


초보자로서 놀기만하면됩니다. 얼마나 많은 도구를 사용할 수 있는지 놀랍습니다.

b = ColorNegate[
    GaussianFilter[MorphologicalBinarize[i, {0.96, 0.999}], 6]];
c = SetAlphaChannel[i, b];
Show[Graphics[Rectangle[], Background -> Orange, 
     PlotRangePadding -> None], c]


저는 이미지 처리에 완전히 익숙하지 않지만 여기에 버전 8의 새로운 형태 학적 이미지 처리 기능을 사용하여 얻은 결과가 있습니다.

mask = DeleteSmallComponents[
   ColorNegate@
    Image[MorphologicalComponents[ColorNegate@img, .062, 
      Method -> "Convex"], "Bit"], 10000];
Show[Graphics[Rectangle[], Background -> Red, 
  PlotRangePadding -> None], SetAlphaChannel[img, ColorNegate@mask]]

영상


이를 위해 Photoshop을 사용하고 PNG로 저장하는 것이 좋습니다.


취할 수있는 조치 :

  • 마스크를 확장
  • 흐리게
  • using the mask, set transparency by distance from white
  • using the mask, adjust saturation such that the previously more-white colors are more saturated.

Just replace any pixel that is "almost close to white" with a pixel of the same RGB color and a Sigmoid gradient on the transparency channel. You can apply linear transition from solid to transparent, but Sinusoid or Sigmoid or Tanh look more natural, depending on the sharpness of edge you are looking for, they rapidly move away from the medium to either solid or transparent, but not in stepwise/binary manner, which is what you have now.

Think of it this way:

Let's say R,G,B are each 0.0-1.0, then let's represent white as a single number as R+G+B=1.0*3=3.0.

Taking a little bit of each color out makes it a little "off-white", but taking a little of all 3 is taking it a lot more off than a little off any one. Let's say that you allow a 10% reduction on any one channel: 1.0*.10 = .1, Now spread this loss across all three and bind it between 0 and 1 for alpha channel, if it's less than .1, such that (loss=0.9)=>0 and (loss=1.0)=>1:

threshold=.10;
maxLoss=1.0*threshold;
loss=3.0-(R+G+B);
alpha=If[loss>maxLoss,0,loss/maxLoss];
(* linear scaling is used above *)
(* or use 1/(1 + Exp[-10(loss - 0.5maxLoss)/maxLoss]) to set sigmoid alpha *)
(* Log decay: Log[maxLoss]/Log[loss]
      (for loss and maxLoss <1, when using RGB 0-255, divide by 255 to use this one *)

setNewPixel[R,G,B,alpha];

For reference:

maxLoss = .1;
Plot[{ 1/(1 + Exp[-10(loss - 0.5maxLoss)/maxLoss]),
       Log[maxLoss]/Log[loss],
       loss/maxLoss
     }, {loss, 0, maxLoss}]

The only danger (or benefit?) you have in this, is that this does not care about whites which actually ARE part of the photo. It removes all whites. So that if you have a picture of white car, it'll end up having transparent patches in it. But from your example, that seems to be a desired effect.

참고URL : https://stackoverflow.com/questions/8041703/remove-white-background-from-an-image-and-make-it-transparent

반응형