Чтобы преобразовать только черный цвет в белый в Matlab
Я знаю нить о преобразовании черного цвета в белый и белый в черный одновременно. Я хотел бы преобразовать только черное в белое. Я знаю это нить об этом я спрашиваю, но я не понимаю что идет не так.
картинка
код
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). Делать эту идею с
redChannel(~binaryImage) = 255;
greenChannel(~binaryImage) = 255;
blueChannel(~binaryImage) = 255;
дает
поэтому я, должно быть, неправильно понял что-то в Matlab. Синий цвет не должен иметь черного. Так что последнее изображение странное.
как вы можете превратить только черный цвет в белый? Я хочу сохранить голубой цвет ЭКГ.
4 ответов
в чем проблема?
вы хотите обнаружить все черные части изображения, но они на самом деле не черный
пример:
ваша идея (или код):
вы первый бинаризация изображения, выбора пикселей, которые что-то против пикселей, которые не являются. Короче говоря, вы делаете:if pixel>level; pixel is something
поэтому у вас есть небольшое заблуждение! когда ты пишешь
% Make the black parts pure red.
следует читать
% Make every pixel that is something (not background) pure red.
поэтому, когда вы делаете
redChannel(~binaryImage) = 255;
greenChannel(~binaryImage) = 255;
blueChannel(~binaryImage) = 255;
Вы делаете
% 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).
rgbImage = imread('ecg.png');
hsvImage=rgb2hsv(rgbImage);
I=rgbImage;
R=I(:,:,1);
G=I(:,:,2);
B=I(:,:,3);
th=0.1;
R((hsvImage(:,:,1)>(280/360))|(hsvImage(:,:,1)<(200/360)))=255;
G((hsvImage(:,:,1)>(280/360))|(hsvImage(:,:,1)<(200/360)))=255;
B((hsvImage(:,:,1)>(280/360))|(hsvImage(:,:,1)<(200/360)))=255;
I2= cat(3, R, G, B);
imshow(I2)
здесь мы хотели бы получить самую большую синюю часть, и это было бы нашим сигналом. Поэтому самый лучший подход, кажется, первый бинаризация изображения, принимать все синие пикселы
% 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)
если я правильно вас понимаю, вы хотите извлечь синий график ЭКГ при удалении текста и осей. Лучший способ сделать это - изучить цветовое пространство 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);
мы получаем это:
отлично, так что я собираюсь сделать сейчас, это сделать копию исходного изображения, а затем установить любой пиксель, который черный от маски, которую я получил (выше) до белого цвета на конечном изображении. Все остальные пиксели должны оставаться нетронутыми. Таким образом, мы можем удалить любой текст и топоры виден на изображении:
im_final = im;
mask_final = repmat(mask_erode, [1 1 3]);
im_final(~mask_final) = 255;
мне нужно скопировать маску в третье измерение, потому что это цветное изображение, и мне нужно установить каждый канал на 255 одновременно в тех же пространственных местоположениях.
когда я это делаю, вот что я получаю:
теперь вы заметите, что есть пробелы в графике.... что следует ожидать из-за шума квантования. Мы можем сделать что-то еще, преобразовав это изображение в оттенки серого и удерживая изображение, а затем заполнив соединение краев морфологическим расширение. Это безопасно, потому что мы уже устранили аксиомы и текст. Затем мы можем использовать это как маску для индексации в исходное изображение для получения нашего окончательного графика.
что-то вроде этого:
im2 = rgb2gray(im_final);
thresh = im2 < 200;
se = strel('line', 10, 90);
im_dilate = imdilate(thresh, se);
mask2 = repmat(im_dilate, [1 1 3]);
im_final_final = 255*ones(size(im), class(im));
im_final_final(mask2) = im(mask2);
Я пороговое предыдущее изображение, которое мы получили без текста и осей после преобразования его в оттенки серого, а затем я выполняю расширение с строка структурирующий элемент, который составляет 90 градусов, чтобы соединить те линии, которые были первоначально разъединенный. Это пороговое изображение будет содержать пиксели, которые мы в конечном счете должны отобрать из исходного изображения, чтобы мы могли получить необходимые данные графика.
затем я беру эту маску, повторить ее, сделать полностью белое изображение, а затем образец из исходного изображения и место расположения мы хотим от исходного изображения в белые изображения.
это наше окончательное изображение:
очень приятно! Я должен был сделать весь этот образ обработка, потому что ваше изображение в основном имеет шум квантования, поэтому будет немного сложнее получить график полностью. Андер Бигури в своем ответе объяснил более подробно о шуме цветового квантования, поэтому, безусловно, ознакомьтесь с его сообщением для получения более подробной информации.
однако, как качественная мера, мы можем вычесть это изображение из исходного изображения и посмотреть, что осталось:
imshow(rgb2gray(abs(double(im) - double(im_final_final))));
получаем:
Так выглядит например, оси и текст удаляются нормально, но на графике есть некоторые следы, которые мы не захватили из исходного изображения, и это имеет смысл. Все это связано с правильными порогами, которые вы хотите выбрать, чтобы получить данные графика. Есть некоторые проблемные места в начале графика, и это, вероятно, связано с морфологической обработкой, которую я сделал. Это изображение, которое вы предоставили, довольно сложно с шумом квантования, поэтому будет очень сложно получить идеальный результат. Кроме того, эти пороги, к сожалению, все эвристические, поэтому играйте с порогами, пока не получите что-то, что согласуется с вами.
удачи!
вот вариация на решение@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)
чтобы получить лучший вид, вот обнаруженная маска, наложенная поверх исходного изображения (я использую imoverlay
функция из обмена файлами):
figure
imshow(imoverlay(imgRGB, BW, uint8([255,0,0])))
вот код для этого:
rgbImage = imread('ecg.png');
redChannel = rgbImage(:, :, 1);
greenChannel = rgbImage(:, :, 2);
blueChannel = rgbImage(:, :, 3);
black = ~redChannel&~greenChannel&~blueChannel;
redChannel(black) = 255;
greenChannel(black) = 255;
blueChannel(black) = 255;
rgbImageOut = cat(3, redChannel, greenChannel, blueChannel);
imshow(rgbImageOut);
black
область, содержащая черные пиксели. Эти пиксели имеют значение белого цвета в каждом цветовом канале.
в вашем коде вы используете порог и изображение в оттенках серого, поэтому, конечно, у вас есть гораздо большая площадь пикселей, которая установлена на белый resp. красный цвет. В этом коде только пиксель, который не содержит абсолютно никакого красного, зеленого и синего, установлен на белый.
следующий код делает то же самое с порогом для каждого цвета канал:
rgbImage = imread('ecg.png');
redChannel = rgbImage(:, :, 1);
greenChannel = rgbImage(:, :, 2);
blueChannel = rgbImage(:, :, 3);
black = (redChannel<150)&(greenChannel<150)&(blueChannel<150);
redChannel(black) = 255;
greenChannel(black) = 255;
blueChannel(black) = 255;
rgbImageOut = cat(3, redChannel, greenChannel, blueChannel);
imshow(rgbImageOut);