56 views (last 30 days)
Sara Macchiavello on 11 Aug 2020
Edited: DGM on 21 May 2022
Good evening,
I had to darken half of a RGB image in order to recreate an emianopsy. Here is the code I used:
%Loss of left visus
[x,y,z]=size(A); %dimensions' estraction RGB image
Y=y/2; % halving y axis
HSV = rgb2hsv(A); %conversion to hsv space
%Process the HSV image. This example decrease the brightness of half image by multiplying the V channel by a scale factor.
[h,s,v] = imsplit(HSV); %split hue, saturation and value channels
vFactor = 0.2; %define the scale factor for brightness
% for cicle darken pixels of the left part of the image
for i=1:x
for j=1:Y
v(i,j) = v(i,j)*vFactor;
end
end
HSV_v = cat(3,h,s,v); %reconstrucion of HSV image
%Convert the processed HSV image back to the RGB color space.
Av = hsv2rgb(HSV_v);
figure
imshow(Av)
title('Left emianopsy');
Here is the resulting image:
The separation between the 2 parts of the image is too sharp and marked, so I'd like to obtain a more faded transition between the dark and the coloured side (like a gradient?). How can I obtain a realistic result? like for example the image below:
hosein Javan on 11 Aug 2020
the reason why your image is not a garadient, is that you are multiplying one single value factor to the whole half left part of the image rather than multiplying a series of factors that change smoothly according to pixel position.

hosein Javan on 11 Aug 2020
figure(1);imshow(A) % show the original image in figure1
dim = linspace(0,1,512); % create a linear dimming factor across horizontal dimension of the image
dim = repmat(dim,[512 1 3]); % repeat dimming factor for all rows
Adim = uint8(dim.*single(A)); % multiply the dimming factor to the original image and store it in "Adim"
figure(2);imshow(Adim) % show the dim image in figure2
Sara Macchiavello on 2 Sep 2020
Goodmorning, I'm sorry to bother you but you were very helpful and kind so I'd like to ask you another question regarding the further developments of my project.
I'd like to create some irregular regions in a RGB image with an effect similar to contour plots. I have to work on these regions for example modifying contrast, saturation or luminance into every region created. As a consequence I think that the drawfreehand and roipoly commands are not suited for my purpose because I saw that they create a mask on which I can't apply transformations named above. Do you know if is there the possibility to obtain this effect?
Thank you

DGM on 21 May 2022
Edited: DGM on 21 May 2022
A 'multiply' blend is one of the simple and fundamental kinds of image blending. If you have appropriate images to begin with and you pay attention to your image class and data scaling, you should be fine.
I've posted plenty of other reference answers about doing similar things with standard tools, but I don't feel like it tonight. MATLAB does not have any practical tools for image blending or composition, so I think it's kind of unreasonable to reinvent a missing wheel every single time. For these examples, I'm going to use tools from MIMT, which is available on the File Exchange.
As in any image manipulation environment, MIMT imblend() can simply blend (and composite) two images. You don't have to be stuck with ultra-simple things like 'multiply' and 'addition' blends, and you don't have to guess at the behavior of closed-source software which no longer exists or debug potentially erroneous formulae found on an abandoned blog somewhere. I already did that.
% background image (RGB, uint8)
% create foreground image (grayscale, uint8)
easew = 0.5; % normalized WRT image width
s = imsize(BG);
FG = lingrad(s(1:2),[0.2 0.5-easew/2; 0.8 0.5+easew/2],[0; 255],'cosine');
% show the images
montage({FG,BG})
% blend the images
%outpict = imblend(FG,BG,1,'multiply');
%outpict = imblend(FG,BG,1,'colorburn',0.5);
%outpict = imblend(FG,BG,1,'linearburn',0.5);
outpict = imblend(FG,BG,1,'suauburn');
While imblend() is compared to Photoshop or GIMP in that it supports image blending, it's dissimilar in that it supports more options than any image manipulation suite does. Most of the modes are adjustable in ways which are convenient for their typical use. In the above example, the lineardodge and colordodge blends are done with a parameter of 0.5, resulting in subtle and rich results unobtainable through scalar opacity adjustment.
Admittedly, my goal here isn't to create anything that really looks good. Slapping a black gradient on lena is just a tangent on the replication of OP's example. Anyone who is familiar with blending images in Photoshop, etc should be able to plan the composition they desire. Having a better hammer doesn't help if you don't know where to put the nails.
So let's try another. MIMT also has tools for creating simple two-point and multipoint gradients. Instead of a linear grayscale gradient, let's use a colored radial gradient. We'll use the same sort of NRL-leveraged blending with darkening modes to do a sort of goofy mood vignetting.
% background image (RGB, uint8)
% create foreground image (RGB, uint8)
easew = 0.5; % normalized WRT image width
s = imsize(BG);
% show the images
montage({FG,BG})
% blend the images
%outpict = imblend(FG,BG,1,'multiply');
%outpict = imblend(FG,BG,1,'colorburn',0.8);
%outpict = imblend(FG,BG,1,'linearburn',0.8);
outpict = imblend(FG,BG,1,'suauburn');
I suppose that's a bit better than black. Again, these blends are adjustable. It takes more than a handful of pictures to explain what the difference is between 'multiply' and the other modes. If all you need to do is to something like this, the details probably don't matter much. The synopsis for imblend() has extensive description of the behaviors, and most modes have their technical properties documented here.
As for the last questions about blurring an image region -- this is a simple task of linear image composition. You could combine images using a logical mask, but the transition will always have ugly jagged edges. You want to do linear composition.
Again, much like the black gradient overlay, you can't get a smooth transition if you don't start with a smooth mask. Whether it's a circle or a polygon, you'll need to come up with a way to make it smooth. If you start with a logical image and try to blur it, make sure to cast it as something other than logical before you blur it.
Don't use roifilt() if appearances are important. Internally, roifilt() is very simple in concept. Much like the code below, it filters a copy of the image and then composes the two copies of that image. Instead of doing that to the whole image, it does it on the rectangular region which circumscribes the mask ROI. It doesn't do any sort of fancy mask-aware weighting or window traversal to process the actual nonrectangular mask region. It's useful for its efficiency when the filtered region is very small in comparison to the overall image, but it uses logical composition internally, so the results will always have jagged edges, even if the mask is smooth.
In this example, a soft circular mask is simply generated by applying a nonlinear contrast curve to a radial gradient with a linear ease curve. While imblend() can be used for both blending and compositing, replacepixels() is often more convenient when all that's needed is compositing (and when the mask is unattached). It's definitely more convenient than doing all the class handling and multiplication the long way every time.
% background image (RGB, uint8)
% create foreground image (RGB, uint8)
FG = imgaussfilt(BG,20);
% show the images and mask
% compose the images in linear RGB
While something like this is easily handled by composition in practice, be aware that transitioning a blur by composition isn't the same thing as using a variable-kernel blurring operation. See this answer:
Consider also the following answers to similar questions regarding basic image composition: