2010-10-31 15 views
33

मैं सिन सिटी या अन्य फिल्मों के समान प्रभाव बनाने की कोशिश कर रहा हूं जहां वे एक छवि से एक को छोड़कर सभी रंगों को हटाते हैं।मैं एक आरजीबी छवि को ग्रेस्केल में कैसे परिवर्तित कर सकता हूं लेकिन एक रंग रख सकता हूं?

मेरे पास एक आरजीबी छवि है जिसे मैं ग्रेस्केल में कनवर्ट करना चाहता हूं लेकिन मैं एक रंग रखना चाहता हूं।

alt text

मैं लाल रंग रखना चाहते हैं:

यह मेरी तस्वीर है। बाकी ग्रेस्केल होना चाहिए।

alt text

यहाँ मेरी कोड है:

यह वही मेरी कोड अब तक आउटपुट (आपको लगता है कि क्षेत्रों सही हैं देख सकते हैं, मैं क्यों वे लाल के बजाय सफेद होते हैं, हालांकि पता नहीं है) है अब तक:

filename = 'roses.jpg'; 

[cdata,map] = imread(filename); 
% convert to RGB if it is indexed image 
if ~isempty(map) 
    cdata = idx2rgb(cdata, map); 
end 

%imtool('roses.jpg'); 

imWidth = 685; 
imHeight = 428; 

% RGB ranges of a color we want to keep 
redRange = [140 255]; 
greenRange = [0 40]; 
blueRange = [0 40]; 

% RGB values we don't want to convert to grayscale 
redToKeep = zeros(imHeight, imWidth); 
greenToKeep = zeros(imHeight, imWidth); 
blueToKeep = zeros(imHeight, imWidth); 

for x=1:imWidth 

    for y=1:imHeight 

     red = cdata(y, x, 1); 
     green = cdata(y, x, 2); 
     blue = cdata(y, x, 3); 

     if (red >= redRange(1) && red <= redRange(2) && green >= greenRange(1) && green <= greenRange(2) && blue >= blueRange(1) && blue <= blueRange(2)) 
      redToKeep(y, x) = red; 
      greenToKeep(y, x) = green; 
      blueToKeep(y, x) = blue; 
     else 
      redToKeep(y, x) = 999; 
      greenToKeep(y, x) = 999; 
      blueToKeep(y, x) = 999; 
     end 

    end 

end 

im = rgb2gray(cdata); 
[X, map] = gray2ind(im); 
im = ind2rgb(X, map); 

for x=1:imWidth 

    for y=1:imHeight 

     if (redToKeep(y, x) < 999) 
      im(y, x, 1) = 240; 
     end 
     if (greenToKeep(y, x) < 999) 
      im(y, x, 2) = greenToKeep(y, x); 
     end 
     if (blueToKeep(y, x) < 999) 
      im(y, x, 3) = blueToKeep(y, x); 
     end 

    end 

end 

imshow(im); 
+0

यह मैटलैब एक समाधान प्रदान कर रहा है, लेकिन यह इस बात का एक कोड गोल्फ ... – gary

उत्तर

18
figure 
pic = imread('EcyOd.jpg'); 

for mm = 1:size(pic,1) 
    for nn = 1:size(pic,2) 
     if pic(mm,nn,1) < 80 || pic(mm,nn,2) > 80 || pic(mm,nn,3) > 100 
      gsc = 0.3*pic(mm,nn,1) + 0.59*pic(mm,nn,2) + 0.11*pic(mm,nn,3); 
      pic(mm,nn,:) = [gsc gsc gsc]; 
     end 
    end 
end 
imshow(pic) 

alt text

+0

धन्यवाद, यह करने के लिए यह एक बहुत आसान तरीका है। आपने उन गुणांक (0.3, 0.5 9, 0.11) को कैसे प्राप्त किया? मुझे यह समझ में नहीं आता है। –

+3

@ रिचर्ड नूप: यह प्रपत्र है जो [आरजीबी 2GRAY] (http://www.mathworks.com/help/toolbox/images/ref/rgb2gray.html) द्वारा प्रलेखन में सूचीबद्ध है। – gnovice

+0

@ रिचर्ड नूप: http://www.mathworks.com/help/toolbox/images/ref/rgb2gray.html जब तक आप पैराग्राफ * 'एल्गोरिदम' * तक नहीं पहुंच जाते, तब तक थोड़ा सा स्क्रॉल करें। लेकिन वेब पर भी अन्य लोग हैं। – zellus

2

मैं सच में पता नहीं कैसे matlab काम करता है तो मैं वास्तव में कोड पर टिप्पणी नहीं कर सकता, लेकिन शायद यह मदद मिलेगी एक सा कैसे आरजीबी रंग काम समझाने।

आरजीबी रंगों का उपयोग करते समय आर, जी और बी के मान समान हैं, यह सुनिश्चित करके एक ग्रे स्केल किया जा सकता है। तो मूल रूप से आप जो करना चाहते हैं वह पता लगाता है कि एक पिक्सेल लाल है, जब न केवल आर, जी और बी बनाते हैं (आप प्राथमिक परिणाम के लिए 3 का औसत उपयोग कर सकते हैं)।

कठिन हिस्सा यह पता लगाने के लिए है कि एक पिक्सेल वास्तव में लाल है या नहीं, तो आप यह जांच नहीं सकते कि आर मान में पिक्सेल उच्च है या नहीं, क्योंकि यह अभी भी एक और रंग हो सकता है, और कम आर मान का मतलब केवल एक गहरा हो सकता है लाल।

ताकि आप कुछ इस तरह कर सकता है: (मैं matlab की जरूरत नहीं है, इसलिए वाक्य रचना मानते हुए):

 
red = cdata(y, x, 1); 
green = cdata(y, x, 2); 
blue = cdata(y, x, 3); 

if (red < (blue * 1.4) || red < (green * 1.4)) 
{ 
    avg = (red + green + blue)/3; 
    cdata(y, x, 1) = avg; 
    cdata(y, x, 2) = avg; 
    cdata(y, x, 3) = avg; 
} 

लाल पता लगाने के लिए और एक औसत ग्रे पाने के लिए शायद बेहतर तरीके हैं, लेकिन यह एक है शुरू करें;)

+0

धन्यवाद देखने के लिए दिलचस्प हो जाएगा लगता है। मैंने अपना कोड थोड़ा सा बदल दिया है और मुझे पहले से ही कुछ आउटपुट मिल गया है लेकिन लाल रंग वाले क्षेत्र इसके बजाय सफेद हैं। मेरा अद्यतन प्रश्न देखें। –

+0

आपके रंग सफेद हैं क्योंकि आपने उन पिक्सल के लिए मूल मानों को हरे और नीले रंग के लिए हटा दिया है जिन्हें आप रखना चाहते हैं। यही कारण है कि उदाहरण में यह केवल पिक्सल के लिए मैट्रिक्स को संशोधित करता है जिसे आप ग्रे बनाना चाहते हैं और केवल बाकी को छोड़ दें। – Doggett

+0

आपकी पोस्ट को ध्यान में रखे बिना आपके एल्गोरिदम को लागू करने की तरह। मुझे आशा है कि आपको बुरा लगेगा। – zellus

82

एक विकल्प जो परिणामी छवि की गुणवत्ता में काफी सुधार करता है, वह आपके रंगों को अधिक आसानी से चुनने के लिए एक अलग रंग स्थान में परिवर्तित करना है। विशेष रूप से, HSV color space उनके रंग (रंग), संतृप्ति (रंग की मात्रा), और मूल्य (रंग की चमक) के संदर्भ में पिक्सेल रंग परिभाषित करता है।

उदाहरण के लिए, यदि आप अपने आरजीबी छवि एचएसवी अंतरिक्ष के लिए समारोह rgb2hsv का उपयोग कर परिवर्तित कर सकते हैं, अवधि है कि क्या आप के रूप में "गैर लाल" रंग (जैसे कि, की तरह, 340 डिग्री तक 20 डिग्री) को परिभाषित करना चाहते रंग के साथ पिक्सल लगता है , 0 करने के लिए उन पिक्सल के लिए संतृप्ति सेट (ताकि वे ग्रेस्केल हैं), तो समारोह hsv2rgb का उपयोग कर आरजीबी अंतरिक्ष में वापस छवि परिवर्तित:

cdata = imread('EcyOd.jpg');  % Load image 
hsvImage = rgb2hsv(cdata);   % Convert the image to HSV space 
hPlane = 360.*hsvImage(:, :, 1); % Get the hue plane scaled from 0 to 360 
sPlane = hsvImage(:, :, 2);  % Get the saturation plane 
nonRedIndex = (hPlane > 20) & ... % Select "non-red" pixels 
       (hPlane < 340); 
sPlane(nonRedIndex) = 0;   % Set the selected pixel saturations to 0 
hsvImage(:, :, 2) = sPlane;  % Update the saturation plane 
rgbImage = hsv2rgb(hsvImage);  % Convert the image back to RGB space 

और यहाँ जिसके परिणामस्वरूप छवि है:

alt text

ध्यान दें कि the solution from zellus की तुलना में, आप आसानी से फूलों पर हल्के गुलाबी टोन बनाए रख सकते हैं। ध्यान दें कि तने और जमीन पर भूरे रंग के स्वर भी चले गए हैं।

उनके रंग गुणों के आधार पर एक छवि से वस्तुओं का चयन करने के लिए एक शांत उदाहरण के लिए, आप स्टीव Eddins ब्लॉग पोस्ट The Two Amigos जो एक छवि से एक निकालने "एमिगो" के लिए MathWorks पर ब्रेट Shoelson से एक समाधान का वर्णन करता है की जाँच कर सकते हैं।


का चयन रंग पर्वतमाला पर एक नोट ...

एक अतिरिक्त बात आप जो मदद कर सकते हैं रंग की श्रेणियों का चयन कर सकते हैं (यानी hPlane ऊपर से) रंग का एक हिस्टोग्राम को देखने के लिए है आपकी एचएसवी छवि के पिक्सल में मौजूद है। यहाँ एक उदाहरण कार्यों histc का उपयोग करता है (या सिफारिश की histcounts, यदि उपलब्ध हो) और bar है:

binEdges = 0:360; % Edges of histogram bins 
hFigure = figure(); % New figure 

% Bin pixel hues and plot histogram: 
if verLessThan('matlab', '8.4') 
    N = histc(hPlane(:), binEdges); % Use histc in older versions 
    hBar = bar(binEdges(1:end-1), N(1:end-1), 'histc'); 
else 
    N = histcounts(hPlane(:), binEdges); 
    hBar = bar(binEdges(1:end-1), N, 'histc'); 
end 

set(hBar, 'CData', 1:360, ...   % Change the color of the bars using 
      'CDataMapping', 'direct', ... % indexed color mapping (360 colors) 
      'EdgeColor', 'none');   % and remove edge coloring 
colormap(hsv(360));      % Change to an HSV color map with 360 points 
axis([0 360 0 max(N)]);     % Change the axes limits 
set(gca, 'Color', 'k');     % Change the axes background color 
set(hFigure, 'Pos', [50 400 560 200]); % Change the figure size 
xlabel('HSV hue (in degrees)');   % Add an x label 
ylabel('Bin counts');     % Add a y label 

और यहाँ जिसके परिणामस्वरूप पिक्सेल रंग हिस्टोग्राम है:

alt text

सूचना कैसे मूल छवि शामिल ज्यादातर लाल, हरे, और पीले रंग के पिक्सल (कुछ नारंगी वाले लोगों के साथ)। लगभग कोई सायन, नीला, इंडिगो, या मैजेंटा रंगीन पिक्सल नहीं हैं। ध्यान दें कि मैंने जो श्रेणियां ऊपर चुनी हैं (20 से 340 डिग्री) उन सभी चीजों को छोड़कर एक अच्छा काम करते हैं जो दोनों बड़े लाल क्लस्टरों का हिस्सा किसी भी अंत में नहीं हैं।

+0

धन्यवाद। मैं कोशिश करूँगा। इस बीच, मैंने अपना प्रश्न अपडेट किया है। क्या आप इसे देख सकते हैं? :) –

+3

+1 आपके समाधान की सराहना करने के लिए। परिणाम और कोड में सुपीरियर। – zellus

+0

हिस्टोग्राम एफटीडब्ल्यू। – Spike0xff

संबंधित मुद्दे

 संबंधित मुद्दे