web-dev-qa-db-ja.com

RGBイメージをグレースケールに変換して、1つの色を維持するにはどうすればよいですか?

私はSin Cityまたは他の映画に似た効果を作成しようとしています。この場合、画像から1色を除くすべての色が削除されます。

グレースケールに変換したいRGB画像がありますが、1つの色を保持したいと思います。

これは私の写真です:

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);
36
Richard Knop
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

19
zellus

結果の画像の品質を大幅に向上させる1つのオプションは、より簡単に色を選択するために別の色空間に変換することです。特に、 HSV色空間 は、ピクセルの色を色相(色)、彩度(色の量)、および値(色の明るさ)で定義します。

たとえば、関数 rgb2hsv を使用してRGB画像をHSV空間に変換し、「非赤」の色として定義したい色にまたがる色相を持つピクセルを見つけることができます(たとえば、 、20度から340度)、それらのピクセルの彩度を0に設定して(グレースケールにする)、関数 hsv2rgb を使用して画像をRGB空間に戻します。

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

ゼルスからの解 と比較して、花の淡いピンクの色調を簡単に維持できることに注目してください。茎と地面の茶色がかった色調も消えていることにも注意してください。

色のプロパティに基づいて画像からオブジェクトを選択するクールな例については、MathWorksのBrett Shoelsonによる1つの「amigo」を抽出するためのソリューションについて説明しているSteve Eddinsのブログ投稿 The Two Amigos をチェックしてください。画像から。


色範囲の選択に関する注意事項...

色の範囲を選択するのに役立つもう1つのことは、HSV画像のピクセルに存在する色相(つまり、上記の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度)は、両端の2つの大きな赤いクラスターの一部ではないほとんどすべてのものを除外するのに適しています。

87
gnovice

Matlabがどのように機能するのか本当にわからないので、コードにコメントを付けることはできませんが、RGBカラーがどのように機能するかを少し説明するのに役立つかもしれません。

RGBカラーを使用する場合、R、G、Bの値がすべて同じであることを確認することにより、グレースケールを作成できます。したがって、基本的には、R、G、Bを同じにするだけでなく、ピクセルが赤かどうかを検出することをお勧めします(基本的な結果には3の平均を使用できます)。

より難しい部分は、ピクセルが実際に赤であるかどうかを検出する方法です。ピクセルがR値が高いかどうかを確認することはできません。別の色になる可能性があるためです。R値が低いと、赤が濃くなるだけです。

あなたはこのようなことをすることができます:(私はMATLABを持っていないので、構文を仮定しています):

赤= cdata(y、x、1); 
緑= cdata(y、x、2); 
青= 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; 
} 

赤を検出して平均的な灰色を得るには、おそらくもっと良い方法がありますが、それは始まりです;)

2
Doggett