Extract Red Line From JPEG
15 views (last 30 days)
I need to extract this red line from the image.
The line was drawn on and the file saved as a JPEG so it may be possible to simply extract this element from the image.
I do not know the exact tone of red so am unable to simply search for pixels in that colour.
Is there a way I can detect the red parts of the image so that I can isolate them to use later as required?
I have tried using getpts to click on the red line however for some reason it always returns a different colour value.
im = imread('Images/Annotated/2x_LN063B1_an.jpg');
im_original = im;
im = imresize(im,[3200,3200]);%resize
[x,y] = getpts;
x = round(x);
y = round(y);
imcolour = im(x,y)
James Li on 18 Feb 2021
First of all, here is some general advice that might help you work on images:
1) To find the RGB value of a pixel, in addition to running getpts command in the prompt, you can also use the "Data Tips" tool from the Figure which might be easier. You can find it in the Menu - Tools - Data Tips.
2) It is typical to see different values for pixels that seem to have the "same color" -- JPEG is a lossy image format, so some values are altered during compression when the image was saved. And there could be other artifacts introduced in various stages of image processing that would lead to this kind of fluctuation in values.
One way to solve your problem is to define a range of the RGB values, i.e., a "standard" value for the red color and experiment with "tolerance", and use them to filter this red line.
However, for your specific example, since your background is on the grey scale, while the only element with color is the red line, you could convert your image to CIELAB (or L*a*b*) space and easily get the result you need. You can read more about CIELAB color space here: https://en.wikipedia.org/wiki/CIELAB_color_space.
I have prepared a script that demonstrates this process:
img = imread('image.jpeg');
subplot(1, 3, 1);
lab = rgb2lab(img); % convert image to CIELAB color space
subplot(1, 3, 2);
imagesc(squeeze(lab(:, :, 2)));
threshold = 2; % arbitrary value
map = squeeze(lab(:, :, 2) > threshold);
subplot(1, 3, 3);
title('a* value after threshold');
indices = find(map);
[rol, col] = ind2sub(size(img, 1), indices);
The general idea is to convert the image to CIELAB color space and look at its a* (or b*, it works similarly) value. Most of the background is near 0, while the area covered by the red line has a non-zero value. Then you can define a threshold and do some filtering to get a map of only 1 and 0 values. You can experiment with that threshold and see how it changes the result. I put some plotting code in the script to help visualize the process and attached the figure to my answer.
You can also then get the indices or these pixels by using find and ind2sub functions, as in the last two lines of the script.
Alternatively, you could convert the image to HSV color space using rgb2hsv and look at the image's H (hue) or S (saturation) channel, and you will get similar results.