Why do I write as Ib(1:478,31:565)(~BW) = 255

1 view (last 30 days)
xie
xie on 26 Feb 2025
Commented: xie on 28 Feb 2025
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?
  1 Comment
xie
xie on 26 Feb 2025
I don't want to assign Ib(1:478,31:565) to new variable to meet request.

Sign in to comment.

Accepted Answer

DGM
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
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)
xie
xie on 28 Feb 2025
Understood completely. a circle
so I can try to change every color by myself. thank you DGM。

Sign in to comment.

More Answers (1)

Walter Roberson
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
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;
xie
xie on 27 Feb 2025
Thank you Walter!
My BW size is the size of full picture. so I should crop it to setting,
temp = Ib(1:478,31:565);
BW = Ib(1:478,31:565);
temp(~BW) = 255;
Ib(1:478,31:565,:) = temp;
I think that my definition of location is not good idear.

Sign in to comment.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!