How to create picture effects in MATLAB?

25 views (last 30 days)
Hello! I was wondering if one could create picture effects (i.e warmer, cooler, grunge) in MATLAB other than the built in functions (rgb2gray etc.)? So far, I have seen sepia effect. Is there a color chart or RGB value for each effects or any conveninet way to create such effects?
Thanks in advance!

Accepted Answer

Ameer Hamza
Ameer Hamza on 14 May 2020
What type of effects are you looking for? For example, see colormap() for very simple effects based on mapping grayscale value to a list of colors. Also, see the following links for discussion on more advanced image effects in MATLAB
  2 Comments
John Doe
John Doe on 14 May 2020
Edited: John Doe on 14 May 2020
Hello Hamza! Thanks for the prompt reply!
I am looking for ways to create popular effects such as the grunge, warm, cool, tint etc.
The links look useful! Thanks for sharing!

Sign in to comment.

More Answers (1)

DGM
DGM on 30 May 2022
Steve's blog has some ideas for thinking outside the box with basic MATLAB/IPT tools, but for the most part there aren't first-party tools specifically intended for aesthetic effects.
I have a habit of writing long reference answers to old questions when I'm bored. I also have a habit of writing them around the tools from MIMT -- often because I'm just lazy and find them convenient. In this case though, MIMT probably is apropos. Unlike most other tools in IPT and on the FEX, a large part of MIMT is tailored to non-technical image manipulation.
As I assume that OP is no longer the one who will use this answer, I'm going to choose to use a broader interpretation of "image effects". The aesthetic filters that OP describes are often little more than tone presets and some minor composition (adding grain, scratches, bloom, or vignetting). I leave it to the reader to find some sort of Photoshop tutorial on the subject and then apply that concept using the adjustment and composition tools available in MIMT.
Following is a haphazard set of selected demos. There isn't time, space, or patience to make any of these examples comprehensive, so some imagination may be required to envision the possibilities. To speak metaphorically, take this as evidence that the knife is sharp enough to cut. It is up to you to visualize and carve the desired form.
The images are scaled down. Right-click to view the full images.
If we were to start with very simple operations, brightness and contrast adjustment would be a good place. MIMT offers simplified tools like imbcg(), all the way to arbitrary nonlinear tools like imcurves().
%% basic brightness/contrast tools
inpict = imread('peppers.png');
B = imbcg(inpict,'b',0.2,'c',0.2,'gimpmode'); % simple brightness/contrast/gamma tool
C = imlnc(inpict,'independent','in',[0.1 0.9],'out',[0 1]); % basic endpoint adjustment like imadjust()
D = imlnc(inpict,'independent','g',0.9,'k',1.5); % nonlinear gamma and contrast parameter
E = imlnc(inpict,'chroma','g',2,'k',1.5); % nonlinear chroma distribution manipulation
F = imcurves(inpict,[0 0.25 0.5 0.75 1],[0 0.15 0.5 0.85 1],'color'); % arbitrary curve in RGB
G = imcurves(inpict,[0 0.25 0.5 0.75 1],[0 0.15 0.5 0.85 1],'lchuv'); % arbitrary curve in L*
outpict = [B C; D E; F G];
Among the basic processes would also be color adjustments. MIMT has a number of tools that can be used for color adjustment. You might notice I'm not really being subtle with these adjustments.
%% basic color adjustment tools
inpict = imread('peppers.png');
B = imtweak(inpict,'lchab',[1 1.1 -0.1]); % adjust color in any model
C = ghlstool(inpict,[-20 0 -20]); % GIMP tool for simple adjustment in HSL only
D = colorbalance(inpict,[-0.5 0 0.5; 0 0 0; 0.5 0 -0.5]); % GIMP color balance
E = mixchannels(inpict,[0.5 0.3 0.2; 0 0.2 0.8; 0.4 0 0.6]); % GIMP channel mixer
outpict = [B C; D E];
The colorbalance() tool is a basic RGB tone control. There are more complex tone controls available.
%% Iain Fergusson's GMIC tone controls
inpict = imread('peppers.png');
% trade some green for red in relatively saturated regions
Tr = [00,00,00; 10,25,50; 00,00,00]/255;
Tg = [00,00,00; -10,-25,-50; 00,00,00]/255;
Tb = [00,00,00; 00,00,00; 00,00,00]/255;
Tsat = [0,0,128,255,255]/255;
B = tonergb(inpict,Tr,Tg,Tb,Tsat,'preserve');
% modern film preset
Tc = [00,20,00; 00,08,00; 00,00,00; 00,-23,00]/255;
Tm = [00,-13,00; 00,17,00; 00,00,00; -1,29,00]/255;
Ty = [00,00,00; 00,00,-12; 00,00,00; 19,68,18]/255;
Tk = [00,00,00; 00,00,00; 00,00,00; -5,55,-15 ]/255;
Tsat = [128,255,255,255,255]/255;
C = tonecmyk(inpict,Tc,Tm,Ty,Tk,Tsat,'preserve');
outpict = [B C];
... and there are a few presets available for them as well.
%% GMIC tonepreset demo
inpict = imread('peppers.png');
B = tonepreset(inpict,'warmvintage');
C = tonepreset(inpict,'expired69');
D = tonepreset(inpict,'fadedprint');
outpict = [B; C; D];
Maybe if we're doing enough handwaving to pretend that we can emulate color film processes, maybe we can pretend to model black & white film as well.
%% black & white film emulation
inpict = imread('peppers.png');
B = bwfilmemu(inpict,'Agfa 200X');
C = bwfilmemu(inpict,'Kodak Tmax 400');
D = bwfilmemu(inpict,'Generic BW');
outpict = [B;C;D];
While similar can be done in multiple other ways, there is a simple tool for doing uniform image colorization.
%% basic HSL colorization
inpict = imread('peppers.png');
B = gcolorize(inpict,[300 40 0]);
C = gcolorize(inpict,[0 80 0]);
outpict = [B C];
Excepting a few purple peppers, things have been fairly tame so far. It doesn't take complex tools or processes to start betraying the object content.
%% invert, value-only invert, and color-only invert
inpict = imread('peppers.png');
ivt = iminv(inpict); % same as imcomplement()
voi = imtweak(inpict,'hsl',[0 1 -1]); % don't change hue
coi = imtweak(inpict,'hsl',[0.5 1 1]); % don't change brightness
outpict = [ivt; voi; coi];
Getting more complicated, maybe you can emulate physical images other than film.
%% lcd display viewing angle emulation
inpict = imread('peppers.png');
% second parameter is the viewing angle [vertical horizontal]
% negative vertical angles denote looking downward from above
% positive vertical angles denote looking upward from below
B = lcdemu(inpict,[-5 -10]);
C = lcdemu(inpict,[-10 -20]);
D = lcdemu(inpict,[5 10]);
E = lcdemu(inpict,[10 20]);
outpict = [B C; D E];
Or maybe you can give in to crafting old clich- I mean classics.
%% rotoscope/painting filters
inpict = imread('peppers.png');
% DGM's awful rotoscope filter
m = nhfilter(inpict,'median',10);
e2 = imadjust(255-edgemap(mono(m,'y')));
e2 = imadjust(e2,[0.5 0.9]);
B = imblend(e2,m,1,'multiply');
% Mark Lowry's "Landscape Painter" filter for GIMP's FXF circa 2006
darkenlayer = imgaussfilt(inpict,5);
C = imblend(darkenlayer,inpict,1,'darkenrgb');
outpict = [B C];
... though I suppose some stand the test of time better than others.
%% solarize
inpict = imread('peppers.png');
B = solarize(inpict); % a more realistic nonlinear curve
C = solarize(inpict,'vee'); % naive hard vee curve
outpict = [B C];
It should be no surprise that the desired tasks might involve image blending and compositing. MIMT imblend() offers flexible support for any blend mode you need -- and many you probably don't need.
%% image blending with imblend
inpict = imread('peppers.png');
fk = fkgen('glow2',50); % sum of gaussians filter
blurpict = imfilterFB(inpict,fk);
B = imblend(blurpict,inpict,1,'meanglow'); % add a soft diffusion effect
gradpict = lingrad(imsize(inpict,3),[0 0; 1 1],[128 0 255; 255 0 128]);
C = imblend(gradpict,inpict,1,'starglow'); % do some sort of flat colored overlay
tf = cat(3,[0.78333 0.93826 0.26285;0.73413 0.043409 0.8336;0.31582 0.080085 0.7164;1 0.34188 0.77826;0.67715 0.007206 0],...
[0.15239 0 0.86842;0.1603 0.16907 0.12786;0.41987 0.97911 0.37884;0.55796 1 0.074092;0.58109 0.262 0.83837],...
[0.74722 2.534e-06 0.07651;0.35848 0.12603 0.71524;0.34756 0.25402 0.96749;0.50298 0.50375 0.80452;0.23024 0.3898 1]);
D = imblend(gradpict,inpict,1,'mesh',tf); % do something bold and arbitrary
E = imblend(blurpict,inpict,1,'permute y>h',1.5); % scalable mapped H/HS adjustment
outpict = [B C; D E];
You can make it a bit more complicated if you want.
%% blurmap with heavy vignetting
inpict = imread('peppers.png');
% create a depth map by some means
map = radgrad(imsize(inpict,2),[0.5 0.5],0.5,[0; 255],'cosine');
blurpict = pseudoblurmap(map,inpict,'kstyle','ring','blursize',20);
outpict = imblend(iminv(map),blurpict,1,'linearburn',0.15);
I suppose at this point I'm just playing. Perhaps someone will actually take this as inspiration.
I will likely come back to this in time, perhaps to add a demo file. Maybe I'll think of another goofy "effect" or two. We'll see. I want to at least make sure this much will upload.
  1 Comment
DGM
DGM on 31 May 2022
Edited: DGM on 31 May 2022
Considering how long that took to upload, I suppose I'll just continue via comments. It's just as well. I think it's time to continue pushing the interpretation of what "image effect" means. I mentioned that MIMT was built with a focus on non-technical image manipulation. That's an understatement. These examples will probably become progressively less directly relevant to sensible readers.
As before, let's start with simple things. As most of the prior examples were based around color/tone adjustment and composition, these examples start to introduce spatial displacement/filtering of the primary image content. Simple "effects" might be spatial downsampling or related blockwise effects. The garish results might not be very interesting themselves, but perhaps they might work well as a component of a more complicated composition.
%% blockify/shuffle/glasstiles
inpict = imread('peppers.png');
B = blockify(inpict,[10 25]);
C = shuffle(inpict,[4 6],'independent');
D = glasstiles(inpict,[20 40],'coherent');
outpict = [B; C; D];
If the goal is to break up referential object content as part of an abstract composition, any number of displacement methods might be interesting. Imrectrotate() and imannrotate() are both answers to the question "how can I arbitrarily rotate an image without changing its geometry?"
%% imrectrotate/imannrotate
inpict = imread('peppers.png');
% multiple random constrained rotations
B = imrectrotate(inpict,5*(2*randi([0 1],[1 10])-1),'center',rand([10 2]));
% a single nonlinearly-graduated annular rotation
C = imannrotate(inpict,45,'keepcenter','gamma',3);
outpict = [B C];
Speaking of rotation, MIMT jellyroll() reorders image pixels by spiral devectorization. This is similar to one of the options in the FEX links provided by @Ameer Hamza in the original answer above.
%% jellyroll (similar to the Tsukuyomi option in FEX #33147)
inpict = imread('peppers.png');
% use default orientation options
B = jellyroll(inpict);
% do something more complicated by filtering before unrolling
fpict = imfilter(inpict,fkgen('ring',10));
a = jellyroll(fpict);
b = jellyroll(fpict,'tailpos','sw');
c = imblend(a,b,1,'softlight');
c = jellyroll(c,'tailpos','ne','reverse');
cblur = imfilterFB(c,fkgen('gaussian',100));
C = imblend(cblur,c,1,'meanglow');
% use a cell array to roll an image blockwise
tiling = [30 30];
s = imsize(inpict,2);
tpict = maketileable(inpict,tiling);
bs = imsize(tpict,2)./tiling;
D = mat2cell(tpict,bs(1)*ones(tiling(1),1),bs(2)*ones(tiling(2),1),size(tpict,3));
D = maketileable(cell2mat(jellyroll(D,'alternate')),tiling,'revertsize',s);
outpict = [B; C; D];
We can't talk about abusing displacement operations unless we bring up polar-cartesian mapping. MIMT imcartpol() is tailored more toward severe image abuse than it is simple technical transformation.
%% polar-rectangular transformations
inpict = imread('peppers.png');
% simple radial inversion
B = imcartpol(inpict,'offset',[0 0],'center','mode','rinvert');
% iteratively do a bunch of random things
C = imcartpol(inpict,'offset',[0; 1],'gamma',[1 1.5],'amount',[1; i],'cycles',3,'mode','rando');
outpict = [B C];
You might have noticed that a lot of these tools support randomized behavior. Imdrag() is no different.
%% imdrag
inpict = imread('peppers.png');
% use a 'lighten' blend
outpict = imdrag(inpict,'direction','south', ...
'nframes',4, 'ndrags',100, ...
'width',[10 30], 'distance',[50 150], ...
'bmode','lightenrgb','opacity',0.9,'amount',1);
In the main answer, I mentioned that some cliches stand the test of time better than others. That applies here as well.
%% picdynamics
inpict = imread('peppers.png');
sluramt = [1 0; 0 0; -1 0]*3;
slurpict = jpegslur(inpict,sluramt,1,10,'original');
dpict = picdynamics(inpict,5,60,'squeeze','rgb');
outpict = imblend(dpict,slurpict,1,'contrast',0.8);
outpict = imblend(mono(meanlines(slurpict,2),'y'),outpict,1,'contrast',0.3);
We're starting to stray into more complex compositions at this point. I mentioned using spatially transformed copies of an image to break up object content in more abstract compositions. Let's go bananas with that.
%% folding/detiling as a stack source
inpict = imread('peppers.png');
% detile the image into a stack of 4 images
sz = imsize(inpict);
fpict = imdetile(inpict,[2 2]);
fpict(:,:,:,1) = imgaussfilt(fpict(:,:,:,1),10); % blur some frames
fpict(:,:,:,3) = imgaussfilt(fpict(:,:,:,3),10);
outpict = mergedown(fpict,1,'negation'); % collapse the stack by blending
outpict = imresize(outpict,sz(1:2)); % rescale to original size
% add some clouds
cloudpict = perlin(sz(1:2));
outpict = imblend(cloudpict,outpict,1,'lightenrgb');
% add some stars
fk = zeros(51,21);
fk(26,:) = fkgen('glow1',21);
fk(:,11) = fk(:,11) + fkgen('glow1',51)';
fk = fk./sum(fk(:));
dotpict = double(rand(sz(1:2))>0.9999);
dotpict = simnorm(imfilter(dotpict,fk));
outpict = imblend(dotpict,outpict,1,'lineardodge');
% use a gradient to emphasize color contrast
gradpict = radgrad(sz(1:3),[0.4 0.75],1,[128 100 128; 255 255 255],'cosine');
outpict = imblend(gradpict,outpict,1,'meanlight',0.8);
Who knew Space Garlic could be so majestic? Eat your heart out, Lisa Frank.
In the "novelties" category of MIMT, there are a few bespoke tools for cranking through certain tedious parts of abstract composition preparation. MIMT imcontfdx(), imcontmip() and fdblend() are a related family of tools used to produce images or image stacks from an image and a 4D array of masks. These tools do (optionally) continuized ROI-constrained subvector displacement/permutation. What's that even mean? Well...
%% imcontmip
inpict = imread('peppers.png');
% create a set of masks by some means
mask = im2double(mono(inpict,'h'));
mask = mlmask(simnorm(mod(mask+0.5,1)),3);
% spatial transformation is naturally discontinuous
% but may be optionally continuized by applying a filter
outpict = imcontmip(inpict,mask,'angle',[-45 120 5], ...
'filter','none','params',[1 0.9 0]);
%% imcontfdx/fdblend
inpict = imread('peppers.png');
% create a set of masks by some means
mask = mlmask(mono(inpict,'y'),4);
% spatial transformation is naturally discontinuous
% but may be optionally continuized by applying a filter
%op = imcontfdx(inpict,mask,'angle',[60 30 -30 -60],'filter','none');
op = imcontfdx(inpict,mask,'angle',[60 30 -30 -60],'filter',fkgen('gaussian',40));
% stack permutation & blending
op = fdblend(op);
% compose an image from the frames in some creative way
outpict = imblend(op(:,:,:,2),op(:,:,:,3),1,'flatglow');
outpict = imblend(edgemap(op(:,:,:,2)),outpict,1,'malekidodge',0.8);
While I'd argue that a familiar viewer could still find traces of the original image, it's getting rather heavily obfuscated. This is what MIMT was built for. Bear that in mind if you expected a library of instagram filters.
I've burned enough site resources on this thread that nobody needs -- well, almost enough. I'll leave you with some garbage obtained by feeding peppers.png to one of the oldest examples from the MIMT webdocs.
Kind of looks familiar, doesn't it?

Sign in to comment.

Community Treasure Hunt

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

Start Hunting!