Как преобразовать изображение RGB в оттенки серого, но сохранить один цвет?

Я пытаюсь создать эффект, похожий на Sin City или другие фильмы, где они удаляют все цвета, кроме одного из изображения.

У меня есть изображение RGB, которое я хочу преобразовать в оттенки серого, но я хочу сохранить один цвет.

Это моя картина:

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 = greenRange(1) && green = 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); 

3 Solutions collect form web for “Как преобразовать изображение RGB в оттенки серого, но сохранить один цвет?”

 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

Одним из вариантов, который значительно улучшает качество получаемого изображения, является преобразование в другое цветовое пространство, чтобы легче выбирать цвета. В частности, цветовое пространство HSV определяет цвета пикселей с точки зрения их оттенка (цвета), насыщенности (количества цвета) и значения (яркости цвета).

Например, вы можете преобразовать ваше изображение RGB в пространство HSV с помощью функции rgb2hsv , найти пиксели с оттенками, которые охватывают то, что вы хотите определить как « rgb2hsv » цвета (например, от 20 до 340 gradleусов), установите насыщенность для этих пикселей до 0 (так что они имеют оттенки серого), затем преобразуйте изображение обратно в пространство RGB с помощью функции 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

Обратите внимание, что по сравнению с решением от zellus вы можете легко поддерживать светло-розовые тона на цветках. Обратите также внимание на то, что коричневатые тона на стебле и почве также исчезли.

Для прохладного примера выбора объектов из изображения, основанного на их цветовых свойствах, вы можете проверить сообщение блога Стив Эддинов The Two Amigos, в котором описывается решение от Brett Shoelson в MathWorks для извлечения одного «амиго» из изображения.

Заметка о выборе цветовых диапазонов ...

Еще одна вещь, которую вы можете сделать, которая может помочь вам выбрать диапазоны цветов, - это посмотреть на гистограмму оттенков (т.е. hPlane сверху), присутствующих в пикселях вашего изображения HSV. Вот пример, который использует функции 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 ay label 

И вот итоговая гистограмма цвета пикселей:

alt text

Обратите внимание, что исходное изображение содержит в основном красные, зеленые и желтые пиксели (с несколькими оранжевыми). Почти нет голубых, синих, индиго или пурпурных цветных пикселей. Обратите внимание также, что диапазоны, выбранные мной выше (от 20 до 340 gradleусов), делают хорошую работу по исключению всего всего, что не является частью двух больших красных кластеров с обоих концов.

Я не знаю, как работает Matlab, поэтому я не могу прокомментировать код, но, возможно, это поможет немного объяснить, как работают цвета RGB.

При использовании цветов RGB можно сделать шкалу серого, убедившись, что значения для R, G и B одинаковы. Таким образом, в основном то, что вы хотите сделать, – это определить, является ли пиксель красным, а не просто сделать R, G и B тем же самым (вы можете использовать среднее значение 3 для элементарного результата).

Сложнее всего определить, действительно ли пиксель на самом деле красный, вы не можете просто проверить, высок ли пиксель в значении R, поскольку он может быть еще одним цветом, а низкое значение R может означать только более темный красный цвет.

так что вы могли бы сделать что-то вроде этого: (У меня нет MATLAB, поэтому предполагаю синтаксис):

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

 if (красный < (синий * 1.4) || красный <(зеленый * 1.4))
 {
     avg = (красный + зеленый + синий) / 3;
     cdata (y, x, 1) = avg;
     cdata (y, x, 2) = avg;
     cdata (y, x, 3) = avg;
 }

Есть, вероятно, лучшие способы обнаружить красный цвет и получить средний серый цвет, но это начало;)

Interesting Posts

Сообщение Firebase, где можно получить ключ сервера?

HashMap get / put сложность

Как проверить, что исключение не выбрасывается?

Как я могу создать компонент ProgressBar в JavaFX

Ruby on Rails will_paginate массив

Как получить значение свойства на основе имени

Как создать общую учетную запись рабочей группы для учетной записи Windows 8 Online?

Есть ли способ вызвать скрипт, когда Ubuntu просыпается из режима ожидания или спящего режима?

Портирование приложения Java, использующего AWT и Swing для рисования фильмов на стороне сервера

Как реализовать ListView без ListActivity? (используйте только действие)

Найдите отсутствующие и повторяющиеся элементы в массиве в линейном времени и постоянном пространстве

Понимание процесса / обновления PrimeFaces и JSF f: атрибуты ajax execute / render

Команда Windows для отображения всех IP-адресов

Как я могу решить проблемы Windows PPTP VPN?

Существуют ли какие-либо темы Firefox, которые работают, когда Ubuntu имеет темную тему?

Давайте будем гением компьютера.