Чтобы преобразовать только черный цвет в белый в Matlab
Автор вопроса: Léo Léopold Hertz 준영Ответов: 4
Я знаю эту ветку о преобразовании черного цвета. к белому и белому к черному одновременно. Я хочу преобразовать только черный цвет в белый. Я знаю это thread о том, что я прошу, но не понимаю, что пошло не так.
Рисунок
Код
rgbImage = imread('ecg.png');
grayImage = rgb2gray(rgbImage); % for non-indexed images
level = graythresh(grayImage); % threshold for converting image to binary,
binaryImage = im2bw(grayImage, level);
% Extract the individual red, green, and blue color channels.
redChannel = rgbImage(:, :, 1);
greenChannel = rgbImage(:, :, 2);
blueChannel = rgbImage(:, :, 3);
% Make the black parts pure red.
redChannel(~binaryImage) = 255;
greenChannel(~binaryImage) = 0;
blueChannel(~binaryImage) = 0;
% Now recombine to form the output image.
rgbImageOut = cat(3, redChannel, greenChannel, blueChannel);
imshow(rgbImageOut);
Который дает
Где, кажется, что-то не так в канале красного цвета. Черный цвет - это просто (0,0,0) в RGB, поэтому его удаление должно означать превращение каждого (0,0,0) пикселя в белый (255,255,255). Реализуя эту идею с
Вы хотите обнаружить все черные части изображения, но они не совсем черные
Пример:
Ваша идея (или ваш код):
Сначала вы преобразуете изображение в двоичную форму, выбирая пиксели, которые ЯВЛЯЮТСЯ чем-то, по сравнению с пикселями, которые не являются. Короче говоря, вы делаете: if pixel>level; pixel is something
Поэтому у вас есть небольшое заблуждение! когда ты пишешь
% Make the black parts pure red.
это должно читаться
% Make every pixel that is something (not background) pure red.
% Make every pixel that is something (not background) white
% (or what it is the same in this case, delete them).
Таким образом, вы должны получить полностью белое изображение. Изображение не полностью белое, потому что некоторые пиксели были помечены как "не что-то, часть фона" значением level, в случае вашего изображения около 0,6.
Решение, которое можно придумать, - это вручную установить уровень на 0,05 или аналогичный, поэтому только черные пиксели будут выбраны в сером для двоичного удержания. Но это не сработает на 100%, как видите, числа имеют очень "не-черные" значения.
Как бы я попытался решить проблему:
Я бы попытался найти нужный цвет, извлечь именно этот цвет из изображения, а затем удалить выбросы.
Извлеките синий с помощью HSV (я думаю, что где-то еще я ответил вам, как использовать HSV).
Оказавшись здесь, мы хотели бы получить самую большую синюю часть, и это будет нашим сигналом. Поэтому лучшим подходом кажется сначала преобразовать изображение в двоичную форму, используя все синие пиксели.
% Binarize image, getting all the pixels that are "blue"
bw=im2bw(rgb2gray(I2),0.9999);
Затем с помощью bwlabel пометьте все независимые пиксельные "острова".
% Label each "blob"
lbl=bwlabel(~bw);
Наиболее повторяемая метка будет сигналом. Итак, мы находим его и отделяем фон от сигнала с помощью этой метки.
% Find the blob with the highes amount of data. That will be your signal.
r=histc(lbl(:),1:max(lbl(:)));
[~,idxmax]=max(r);
% Profit!
signal=rgbImage;
signal(repmat((lbl~=idxmax),[1 1 3]))=255;
background=rgbImage;
background(repmat((lbl==idxmax),[1 1 3]))=255;
Вот график с сигналом, фоном и разницей (с использованием того же уравнения, что и @rayryang)
Ответ 2 · рейтинг 7 · rayryeng
Если я вас правильно понял, вы хотите извлечь синий график ЭКГ, удалив текст и оси. Лучший способ сделать это - изучить цветовое пространство HSV изображения. Цветовое пространство HSV отлично подходит для различения цветов, как это делают люди. Мы ясно видим, что на изображении есть два разных цвета.
Мы можем преобразовать изображение в HSV, используя rgb2hsv, и мы можем изучить компоненты отдельно. Компонент оттенка представляет доминирующий цвет пикселя, насыщенность обозначает чистоту или количество белого света в пикселе, а значение представляет интенсивность или силу пикселя.
Попробуйте визуализировать, как каждый канал делает:
im = imread('http://i.stack.imgur.com/cFOSp.png'); %// Read in your image
hsv = rgb2hsv(im);
figure;
subplot(1,3,1); imshow(hsv(:,:,1)); title('Hue');
subplot(1,3,2); imshow(hsv(:,:,2)); title('Saturation');
subplot(1,3,3); imshow(hsv(:,:,3)); title('Value');
Хм ... ну, оттенок и насыщенность нам совершенно не помогают. Он говорит нам, что доминирующий цвет и насыщенность одинаковы ... но их отличает значение. Если вы посмотрите на изображение справа, мы сможем отличить их друг от друга по силе самого цвета. Это говорит нам о том, что "черные" пиксели на самом деле синие, но с ними почти не связана сила.
Мы действительно можем использовать это в наших интересах. Любые пиксели, значения которых превышают определенное значение, являются значениями, которые мы хотим сохранить.
Попробуйте установить порог ... что-то вроде 0.75. Динамический диапазон MATLAB значений HSV от [0-1], поэтому:
mask = hsv(:,:,3) > 0.75;
Когда мы устанавливаем пороговое значение для компонента значения, мы получаем следующее:
Очевидно, есть небольшой шум квантования ... особенно вокруг осей и шрифта. Что я собираюсь сделать дальше, так это выполнить морфологическую эрозию, чтобы устранить шум квантования вокруг каждого из чисел и осей. Я собираюсь сделать маску немного больше, чтобы убрать этот шум. Используя панель инструментов обработки изображений:
se = strel('square', 5);
mask_erode = imerode(mask, se);
Получаем вот что:
Отлично, теперь я собираюсь сделать копию вашего исходного изображения, а затем установить любой черный пиксель из полученной мной маски (см. Выше) на белый в окончательном изображении. Все остальные пиксели должны остаться нетронутыми. Таким образом, мы можем удалить любой текст и оси, которые видны на вашем изображении:
Мне нужно воспроизвести маску в третьем измерении, потому что это цветное изображение, и мне нужно установить для каждого канала значение 255 одновременно в тех же пространственных положениях.
Когда я это делаю, то получаю:
Теперь вы заметите, что на графике есть пробелы ... чего и следовало ожидать из-за шума квантования. Мы можем сделать что-то еще, преобразовав это изображение в оттенки серого и установив пороговое значение для изображения, а затем заполнив, соединяя края вместе с помощью морфологического расширения. Это безопасно, потому что мы уже удалили оси и текст. Затем мы можем использовать это как маску для индексации исходного изображения, чтобы получить окончательный график.
Я ограничиваю предыдущее изображение, которое мы получили без текста и осей, после того, как конвертирую его в оттенки серого, а затем выполняю растяжение с помощью элемента структурирования линии, который находится под углом 90 градусов, чтобы соединить те линии, которые изначально были отключен. Это пороговое изображение будет содержать пиксели, которые нам в конечном итоге понадобятся для выборки из исходного изображения, чтобы мы могли получить нужные нам данные графика.
Затем я беру эту маску, реплицирую ее, делаю полностью белое изображение, а затем пробую из исходного изображения и помещаю места, которые мы хотим из исходного изображения, в белое изображение.
Это наше окончательное изображение:
Очень хорошо! Мне пришлось выполнить всю эту обработку изображения, потому что ваше изображение изначально имеет шум квантования, поэтому будет немного сложнее получить график целиком. Андер Бигури в своем ответе более подробно объяснил шум квантования цвета, поэтому обязательно ознакомьтесь с его публикацией для получения более подробной информации.
Однако в качестве качественной меры мы можем вычесть это изображение из исходного изображения и посмотреть, что осталось:
Таким образом, похоже, что оси и текст удалены нормально, но на графике есть некоторые следы, которые мы не захватили с исходного изображения, и это имеет смысл. Все это связано с правильными пороговыми значениями, которые вы хотите выбрать, чтобы получить данные графика. В начале графика есть несколько проблемных участков, вероятно, из-за проведенной мной морфологической обработки. Это изображение, которое вы предоставили, довольно сложно из-за шума квантования, поэтому будет очень сложно получить идеальный результат. Кроме того, к сожалению, все эти пороговые значения являются эвристическими, поэтому поиграйте с порогами, пока не получите что-то, что с вами согласуется.
Удачи!
Ответ 3 · рейтинг 3 · Amro
Вот вариант решения @ rayryeng для извлечения синего сигнала:
%// retrieve picture
imgRGB = imread('http://i.stack.imgur.com/cFOSp.png');
%// detect axis lines and labels
imgHSV = rgb2hsv(imgRGB);
BW = (imgHSV(:,:,3) < 1);
BW = imclose(imclose(BW, strel('line',40,0)), strel('line',10,90));
%// clear those masked pixels by setting them to background white color
imgRGB2 = imgRGB;
imgRGB2(repmat(BW,[1 1 3])) = 255;
%// show extracted signal
imshow(imgRGB2)
Чтобы лучше рассмотреть, вот обнаруженная маска, наложенная поверх исходного изображения (я использую _ 2_ из Файлового обмена):
black - это область, содержащая черные пиксели. Эти пиксели устанавливаются на белый цвет в каждом цветовом канале.
В вашем коде вы используете порог и изображение в градациях серого, поэтому, конечно, у вас есть гораздо большая область пикселей, которая установлена на белый цвет, соответственно. красный цвет. В этом коде только пиксели, которые абсолютно не содержат красного, зеленого и синего цветов, устанавливаются в белый цвет.
Следующий код делает то же самое с порогом для каждого цветового канала: