Why do I write as Ib(1:478,31:565)(~BW) = 255
1 view (last 30 days)
Show older comments
Ib(1:478,31:565)(~BW) = 255
Ib is a gray image. I want to set a fixed black region as blue, but this code is wrong.
Do we have simple method to finish it?
Accepted Answer
DGM
on 26 Feb 2025
Edited: DGM
on 26 Feb 2025
There are various ways, including expanding the mask, or using more purpose-built tools, but if you're trying to apply an undersize mask to a rectangular sub-image, maybe it'd be best to just show it like this, since it demonstrates a number of concepts that can be rearranged and applied as is truly needed.
% this is a single-channel (gray) image in uint8
inpict = imread('cameraman.tif'); % 256x256x1
imshow(inpict)
% say we have some smaller logical mask
% ignore the ==0 here. that's just a consequence of the image i'm repurposing
mask = imread('150mk.png') == 0; % 150x150x1
imshow(mask)
% if we want the output to contain color,
% let's start with expanding the image as needed
if size(inpict,3) == 1
outpict = repmat(inpict,[1 1 3]);
else
outpict = inpict;
end
% we want to apply the mask to some region within the image
% we might choose to just extract that region
offset = [10 10]; % [y x]
sz = size(mask,1:2);
roi = outpict(offset(1):offset(1)+sz(1)-1, ...
offset(1):offset(2)+sz(2)-1,:);
% we can apply the mask to that sub-image
fgcolor = [0 0 1]; % unit-scale float
for c = 1:3
thischannel = roi(:,:,c);
thischannel(mask) = im2uint8(fgcolor(c));
roi(:,:,c) = thischannel;
end
% we can put the roi back into the image if we want
outpict(offset(1):offset(1)+sz(1)-1, ...
offset(1):offset(2)+sz(2)-1,:) = roi;
% show the result
imshow(outpict)
Not sure if that covers all the bases, but maybe it's a start. I know you don't want to assign the subimage to a new variable, but you're going to have to do something, since the image an mask have mismatched geometry, and the input and output have mismatched depth.
EDIT: Like I said, there are other ways. This example uses different approaches to addressing both of the above issues.
% this is a single-channel (gray) image in uint8
inpict = imread('cameraman.tif'); % 256x256x1
% say we have some smaller logical mask
mask = imread('150mk.png')==0; % 150x150x1
% instead of working on the sub-image to fix the geometry mismatch
% just expand the mask to fit the image
offset = [10 10]; % [y x]
sz = size(mask,1:2);
fullmask = false(size(inpict,1:2));
fullmask(offset(1):offset(1)+sz(1)-1, ...
offset(1):offset(2)+sz(2)-1) = mask;
% use simple multiplicative composition to construct the output
% in modern versions, this lets us avoid the problem of mismatched depth
fgcolor = [0 0 1]; % unit-scale float
outpict = im2double(inpict).*(1-fullmask) ... % do the composition
+ permute(fgcolor,[1 3 2]).*fullmask;
outpict = im2uint8(outpict); % assuming the output should be uint8
% show the result
imshow(outpict)
Alternatively, so long as the image/mask geometry matches, the final composition could be done using tools made for the purpose.
% IPT imoverlay() can do solid-color fills, given a logical mask
fgcolor = [0 0 1]; % unit-scale float
outpict = imoverlay(inpict,fullmask,fgcolor);
6 Comments
DGM
on 27 Feb 2025
Edited: DGM
on 27 Feb 2025
Hues are values on a circular continuum -- angles in a polar space. A hue of 0 degrees is the same as 360 degrees.
The output of rgb2hsv() is unit-scale HSV -- specifically meaning that hue data (angles from 0-360 degrees) are normalized to a [0 1] scale.
If we offset hues by addition, we may end up with angles outside of our expected interval (either [0 360] or [0 1]), so we use mod() to wrap these angles back to the expected interval. Since in this case we're using unit-scale, we do mod(H,1) instead of mod(H,360).
Consider the three examples to see what the effect is.
% the amount to offset H
% e.g. 0.25 is a 90 degree rotation
os = -0.3;
% the image
inpict = imread('peppers.png');
% simply apply the offset by addition
% we potentially create values outside the unit interval
% this causes problems on conversion back to RGB
hsvcopy = rgb2hsv(inpict);
hsvcopy(:,:,1) = hsvcopy(:,:,1) + os;
op1 = hsv2rgb(hsvcopy);
% do the same thing, but try to constrain H
% by clamping values to the unit interval
% this creates abrupt gaps in the color distribution
% as colors get compressed near zero (red in HSV)
hsvcopy = rgb2hsv(inpict);
hsvcopy(:,:,1) = min(max(hsvcopy(:,:,1) + os,0),1);
op2 = hsv2rgb(hsvcopy);
% apply the offset by modular addition
% values simply circulate like angles should
hsvcopy = rgb2hsv(inpict);
hsvcopy(:,:,1) = mod(hsvcopy(:,:,1) + os,1);
op3 = hsv2rgb(hsvcopy);
% compare the results
outpict = [op1; op2; op3];
imshow(outpict)
More Answers (1)
Walter Roberson
on 26 Feb 2025
Edited: Walter Roberson
on 26 Feb 2025
temp = Ib(1:478,31:565,:);
temp(~repmat(BW,1,1,ndims(temp))) = 255;
Ib(1:478,31:565,:) = temp;
3 Comments
Walter Roberson
on 27 Feb 2025
Ib = randi([0 255], 500, 600, 3, 'uint8');
temp = Ib(1:478,31:565,:);
BW = rand(size(temp,1), size(temp,2)) > 0.8;
temp(~repmat(BW,1,1,size(temp,3))) = 255;
Ib(1:478,31:565,:) = temp;
See Also
Products
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!