Extract part from an RGB image based on the obtained pixel locations.
2 views (last 30 days)
Show older comments
I had an RGB image and I converted this to a binary image. Then, I got desired pixel locations from a binary image. I want to extract that part from the same RGB image (from which binary image was developed) which lies in the obtained desired location mentioned above.
Can anyone suggest me some way out?
0 Comments
Accepted Answer
DGM
on 23 Sep 2023
Edited: DGM
on 23 Sep 2023
"Extract" tends to be a word that gets used in ways that make it difficult to know what anyone means when they use it. Here are three different interpretations.
% you have an RGB image
inpict = imread('peppers.png');
% and a logical mask
mask = imread('redpepmask.png')>128;
% you could apply the mask to the image
% this is just cosmetic and typically isn't very useful
% for processing purposes
maskedpict = inpict.*cast(mask,class(inpict));
imshow(maskedpict,'border','tight')
% or you can extract only those pixels as a color table
% bear in mind that this will retain the class and scale of inpict
% and so generally won't be compatible with other tools that handle color tables
% unless rescaled to unit-scale float.
selectedpixels = inpict(repmat(mask,[1 1 size(inpict,3)]));
selectedpixels = reshape(selectedpixels,[],3)
% if you want a picture that contains only the ROI content,
% you can do that, but it's usually not what people think they want.
f = factor2(size(selectedpixels,1),'ordered',false);
onlythepepper = reshape(selectedpixels,[f(end,:) 3]);
imshow(onlythepepper,'border','tight')
7 Comments
DGM
on 24 Sep 2023
Depending on your familiarity with the concepts, perhaps I could have elaborated.
We want to blank part of an array by filling it with zeros. There are two basic approaches: indexing and multiplication.
For indexing, there are multiple ways. Say we start with a logical mask:
% the inputs
Agray = imread('sadberry_gray.png'); % a single-channel uint8 image
mask = imread('sadberry_mask.png'); % a mask selecting the _background_
imshow(Agray,'border','tight')
% you could do this using logical indexing
B1 = Agray;
B1(mask) = 0;
imshow(B1,'border','tight')
% or you could convert the logical mask to linear indices
idx = find(mask);
B2 = Agray;
B2(idx) = 0;
imshow(B2,'border','tight')
% or you could convert the logical mask to subscripts
[y x] = find(mask);
% ... at which point you'd have to either use a set of loops
% or convert the subscripts back to linear indices
idx = sub2ind(size(mask),y,x);
B3 = Agray;
B3(idx) = 0;
imshow(B3,'border','tight')
If we're creating a logical output from some test, it's usually easiest to use the logical array directly. There are some complications in this application though. Because our image is RGB, it doesn't have the same size as the mask. It has the same page geometry, but it has 3 pages instead of 1.
If we were to replicate the above example with logical indexing, we'd need to expand the mask to match, otherwise we'd only select the first page.
% an RGB input
Argb = imread('sadberry.png');
imshow(Argb,'border','tight')
% use logical indexing with an expanded mask
Brgb1 = Argb;
Brgb1(repmat(mask,[1 1 3])) = 0;
imshow(Brgb1,'border','tight')
Alternatively, instead of directly using the mask for indexing, we can implicitly use it as a numeric array and multiply it with the image. In modern versions of MATLAB with implicit array expansion, this obviates the need to expand the mask, but it does present the problem of mixed-class arithmetic. In order to avoid that issue, we can explicitly cast the mask to an appropriate numeric class.
% image composition via multiplication
% this works for both gray or RGB
B4 = Agray.*cast(~mask,class(Agray));
imshow(B4,'border','tight')
Brgb2 = Argb.*cast(~mask,class(Argb));
imshow(Brgb2,'border','tight')
Alternatively, if the image is always float class, the explicit casting of the mask isn't strictly necessary.
More Answers (0)
See Also
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!