image - एक छवि से सफेद पृष्ठभूमि निकालें और इसे पारदर्शी बनाओ




image-processing wolfram-mathematica (6)

हम गणित में निम्नलिखित करने की कोशिश कर रहे हैं:
RMagick छवि से सफेद पृष्ठभूमि को हटा दें और इसे पारदर्शी बनाएं

लेकिन वास्तविक तस्वीरों के साथ यह लुसी दिख रहा है (छवि के चारों ओर एक हेलो होने की तरह)।

यहां हमने अभी तक कोशिश की है:

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

यहां एक उदाहरण दिया गया है जो करता है।

मूल छवि:

सफेद पृष्ठभूमि के साथ छवि पृष्ठभूमि के साथ प्रतिस्थापित (या, यहां प्रदर्शन उद्देश्यों के लिए, एक गुलाबी पृष्ठभूमि):

उस हेलो से छुटकारा पाने के लिए कोई विचार? लेवलपेनल्टी जैसी चीजें ट्विकिंग, मैं केवल कुछ छवि खोने के खर्च पर जाने के लिए हेलो प्राप्त कर सकता हूं।

संपादित करें: तो मैं बक्षीस के लिए समाधान की तुलना कर सकता हूं, कृपया उपरोक्त की तरह अपने समाधान की संरचना करें, अर्थात् एक स्व-निहित फ़ंक्शन जो अनगिनत है- कुछ ऐसा जो छवि लेता है और पारदर्शी पृष्ठभूमि के साथ एक छवि देता है। बहुत बहुत धन्यवाद, हर कोई!


बस किसी भी पिक्सेल को प्रतिस्थापित करें जो "लगभग करीब सफेद" है, उसी आरजीबी रंग के पिक्सेल और पारदर्शिता चैनल पर सिग्मोइड ढाल के साथ। आप ठोस से पारदर्शी से रैखिक संक्रमण लागू कर सकते हैं, लेकिन साइनसॉइड या सिग्मोइड या तन अधिक प्राकृतिक दिखते हैं, जो किनारे की तेजता के आधार पर आप तेजी से माध्यम से या तो ठोस या पारदर्शी हो जाते हैं, लेकिन चरणबद्ध / बाइनरी में नहीं तरीके, जो अब आपके पास है।

इस पर इस तरीके से विचार करें:

मान लीजिए आर, जी, बी प्रत्येक 0.0-1.0 हैं, तो चलिए सफेद को एक ही संख्या के रूप में आर + जी + बी = 1.0 * 3 = 3.0 के रूप में दर्शाते हैं।

प्रत्येक रंग के बाहर थोड़ा सा लेना इसे थोड़ा "ऑफ-व्हाइट" बनाता है, लेकिन 3 में से कुछ लेना इसे किसी भी से थोड़ा अधिक दूर ले जा रहा है। आइए मान लें कि आप किसी एक चैनल पर 10% की कमी की अनुमति देते हैं: 1.0 * .10 = .1, अब इस नुकसान को तीनों में फैलाएं और इसे 0 से 1 के बीच अल्फा चैनल के लिए बाध्य करें, यदि यह 1 से कम है, जैसे कि ( नुकसान = 0.9) => 0 और (हानि = 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];

सन्दर्भ के लिए:

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

आपके पास एकमात्र खतरा (या लाभ?) है, यह है कि यह उन सफेदों की परवाह नहीं करता जो वास्तव में तस्वीर का हिस्सा हैं। यह सभी सफेद हटा देता है। ताकि अगर आपके पास सफेद कार की तस्वीर है, तो इसमें पारदर्शी पैच होने लगेंगे। लेकिन आपके उदाहरण से, यह एक वांछित प्रभाव प्रतीत होता है।


बेलारियस के मास्क पीढ़ी से कुछ मदद के साथ, मार्क रान्ससम के दृष्टिकोण को लागू करने का प्रयास यहां दिया गया है:

वस्तु की सीमा का पता लगाएं:

img1 = SetAlphaChannel[img, 1];
erosionamount=2;
mb = [email protected][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]

ध्यान दें कि किनारों में से कुछ में सफेद फ़ज़ है? पहली छवि में लाल रूपरेखा के साथ इसकी तुलना करें। हमें एक बेहतर किनारे डिटेक्टर की जरूरत है। क्षरण राशि को बढ़ाने से फज़ के साथ मदद मिलती है, लेकिन फिर अन्य पक्ष बहुत पारदर्शी हो जाते हैं, इसलिए एज मास्क की चौड़ाई पर एक ट्रेडऑफ होता है। हालांकि, यह बहुत अच्छा है, पर विचार नहीं है कि कोई धुंधला ऑपरेशन नहीं है, प्रति से।

यह स्वचालित रूप से यह देखने के लिए, इसकी मजबूती का परीक्षण करने के लिए विभिन्न छवियों पर एल्गोरिदम चलाने के लिए निर्देशक होगा।


मैं छवि प्रसंस्करण के लिए पूरी तरह से नया हूं लेकिन संस्करण 8 के नए रूपरेखा छवि प्रसंस्करण कार्यों के साथ कुछ खेलने के बाद मुझे यह मिलता है:

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


मैं सामान्य रूप से गणित के संदर्भ में, विशेष रूप से बात करने जा रहा हूं। मुझे नहीं पता कि ये ऑपरेशन मुश्किल या तुच्छ हैं।

पहला कदम छवि के किनारे पर पिक्सेल के लिए अल्फा (पारदर्शिता) स्तर का अनुमान लगाने के लिए है। अभी आप सख्त दहलीज का उपयोग कर रहे हैं, इसलिए अल्फा या तो 0% पूरी तरह से पारदर्शी या 100% पूरी तरह से अपारदर्शी है। आपको पृष्ठभूमि के कुल सफेद और रंगों के बीच एक सीमा को परिभाषित करना चाहिए जो छवि के निर्विवाद रूप से भाग हैं, और उचित अनुपात निर्धारित करें - यदि यह पृष्ठभूमि के रंग में करीब है तो यह अल्फा है, और यदि यह गहरे कटऑफ के करीब है तो यह है एक उच्च अल्फा। इसके बाद आप आस-पास के अल्फा मानों के आधार पर समायोजन कर सकते हैं - जितना अधिक पिक्सेल पारदर्शिता से घिरा हुआ है, उतना अधिक संभावना है कि यह पारदर्शी हो।

एक बार आपके पास अल्फा मान हो जाने के बाद आपको उचित रंग प्राप्त करने के लिए एक रिवर्स मिश्रण करने की आवश्यकता है। जब पृष्ठभूमि पर एक छवि प्रदर्शित होती है तो इसे सूत्र c = bc*(1-a)+fc*a का उपयोग करके अल्फा मान के अनुसार मिश्रित किया जाता c = bc*(1-a)+fc*a जहां bc पृष्ठभूमि रंग होता है और fc अग्रभूमि रंग होता है। आपके मामले में पृष्ठभूमि सफेद है (255,255,255) और अग्रभूमि रंग अज्ञात है, इसलिए हम सूत्र को उलट देते हैं: fc = (c - bc*(1-a))/a । जब a=0 सूत्र शून्य से विभाजित करने के लिए कहता है, लेकिन रंग किसी भी तरह से कोई फर्क नहीं पड़ता है तो बस काले या सफेद का उपयोग करें।


शायद, किनारे की गुणवत्ता के आधार पर आपको आवश्यकता है:

img = [email protected]"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 = [email protected]"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 -> [email protected]]
GraphicsGrid[{{[email protected], [email protected], [email protected]}}]

बड़ा करने के लिए क्लिक करें

2 संपादित करें

छवि में हेलो और पृष्ठभूमि की खामियों की सीमा का एक अनुमान प्राप्त करने के लिए:

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

[email protected][EntropyFilter[img, 1] // ImageAdjust, [email protected]]


शुरुआत के रूप में बस खेलना - यह आश्चर्यजनक है कि कितने टूल्स उपलब्ध हैं।

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





masking