如何将 RGB 图像转换为灰度图像但保留一种颜色?
我正在尝试创建一种类似于罪恶之城或其他电影的效果,它们会删除图像中除一种颜色之外的所有颜色。
我有一个 RGB 图像,我想将其转换为灰度图像,但我想保留一种颜色。
这是我的图片:
我想保留红色。其余的应该是灰度的。
这是我的代码到目前为止输出的内容(您可以看到这些区域是正确的,但我不知道为什么它们是白色而不是红色):
这是到目前为止我的代码:
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);
I am trying to create an effect similar to Sin City or other movies where they remove all colors except one from an image.
I have an RGB image which I want to convert to grayscale but I want to keep one color.
This is my picture:
I want to keep the red color. The rest should be grayscale.
This is what my code outputs so far (you can see that the areas are correct, I don't know why they are white instead of red though):
Here is my code so far:
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);
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
极大提高生成图像质量的一种选择是转换为不同的色彩空间,以便更轻松地选择颜色。特别是,HSV 颜色空间 根据色调(颜色)、饱和度定义像素颜色(颜色的量)和值(颜色的亮度)。
例如,您可以使用函数
rgb2hsv 将 RGB 图像转换为 HSV 空间
,找到色调跨越您想要定义为“非红色”颜色的像素(例如,20 度到 340 度),将这些像素的饱和度设置为 0(这样它们是灰度),然后使用函数hsv2rgb 将图像转换回 RGB 空间
:这是生成的图像:
请注意,与 来自zellus的解决方案,您可以轻松保持花朵上的浅粉色色调。还请注意,茎和地面上的棕色色调也消失了。
有关根据颜色属性从图像中选择对象的一个很酷的示例,您可以查看 Steve Eddins 博客文章 The Two Amigos 描述了 MathWorks 的 Brett Shoelson 提出的一种解决方案,用于从图像中提取一个“amigo”。
关于选择颜色范围的说明...
您可以做的另一件事可以帮助您选择颜色范围,那就是查看色调的直方图(即
hPlane
上面)存在于 HSV 图像的像素中。以下是使用函数histc
的示例(或推荐的histcounts
,如果有的话) 和bar
:这是结果像素颜色直方图:
请注意原始图像主要包含红色、绿色和黄色像素(还有一些橙色像素)的)。几乎没有青色、蓝色、靛蓝色或洋红色像素。另请注意,我在上面选择的范围(20 到 340 度)很好地排除了不属于两端两个大红色簇的大部分内容。
One option which greatly improves the quality of the resulting image is to convert to a different color space in order to more easily select your colors. In particular, the HSV color space defines pixel colors in terms of their hue (the color), saturation (the amount of color), and value (the brightness of the color).
For example, you can convert your RGB image to HSV space using the function
rgb2hsv
, find pixels with hues that span what you want to define as "non-red" colors (like, say, 20 degrees to 340 degrees), set the saturation for those pixels to 0 (so they are grayscale), then convert the image back to RGB space using the functionhsv2rgb
:And here is the resulting image:
Notice how, compared to the solution from zellus, you can easily maintain the light pink tones on the flowers. Notice also that brownish tones on the stem and ground are gone as well.
For a cool example of selecting objects from an image based on their color properties, you can check out Steve Eddins blog post The Two Amigos which describes a solution from Brett Shoelson at the MathWorks for extracting one "amigo" from an image.
A note on selecting color ranges...
One additional thing you can do which can help you select ranges of colors is to look at a histogram of the hues (i.e.
hPlane
from above) present in the pixels of your HSV image. Here's an example that uses the functionshistc
(or the recommendedhistcounts
, if available) andbar
:And here's the resulting pixel color histogram:
Notice how the original image contains mostly red, green, and yellow colored pixels (with a few orange ones). There are almost no cyan, blue, indigo, or magenta colored pixels. Notice also that the ranges I selected above (20 to 340 degrees) do a good job of excluding most everything that isn't a part of the two large red clusters at either end.
我真的不知道 matlab 是如何工作的,所以我不能真正评论代码,但这也许有助于解释 RGB 颜色的工作原理。
使用 RGB 颜色时,可以通过确保 R、G 和 B 的值全部相同来生成灰度。所以基本上你想要做的是检测一个像素是否是红色的,而不仅仅是让 R、G 和 B 相同(你可以使用 3 的平均值来获得基本结果)。
更难的部分是如何检测像素是否实际上是红色,您不能只检查像素的 R 值是否较高,因为它仍然可以是另一种颜色,而较低的 R 值可能意味着较深的红色。
所以你可以做这样的事情:(我没有matlab,所以假设语法):
可能有更好的方法来检测红色并获得平均灰色,但这是一个开始;)
I don't really know how matlab works so I can't really comment on the code, but maybe this will help explain a bit how RGB colors work.
When using RGB colors a gray scale can be made by making sure the values for R,G and B are all the same. So basically what you want to do is detect if a pixel is red, when not just make R,G and B the same (you can use an average of the 3 for a rudimentary result).
Harder part is how to detect if a pixel is actually red, you can't just check if a pixel is high in the R value since it can still be another color, and a low R value can just mean a darker red.
so you could do something like this: (I don't have matlab, so assuming syntax):
There are probably better ways to detect red and to get an average gray, but it's a start ;)