Reputation: 5940
I have an image and I would like to blur it in one specific direction and distance using Matlab.
I found out there is a filter called fspecial('motion',len,theta)
.
Here there is an example:
I = imread('cameraman.tif');
imshow(I);
H = fspecial('motion',20,45);
MotionBlur = imfilter(I,H,'replicate');
imshow(MotionBlur);
However the blurred picture is blurred in 2 directions! In this case 225 and 45 degrees. What should it do in order to blur it just in a specific direction (e.g. 45) and not both?
Upvotes: 2
Views: 2439
Reputation: 5940
Based on Anger Density's answer I wrote this code that solves my problem completely:
L = 10; % kernel width
sx=0.1;
sy=100;
THETA = ([0,45,90,135,180,225,270,320,360])*pi/180;
for i=1:length(THETA)
theta=(THETA(i)+pi)*-1;
I = imread('cameraman.tif');
x = -L:1.0:L;
[X,Y] = meshgrid(x,x);
rX = X.*cos(theta)-Y.*sin(theta);
rY = X.*sin(theta)+Y.*cos(theta);
H1 = exp(-((rX./sx).^2)-((rY./sy).^2));
Hflag = double((0.*rX+rY)>0);
H1 = H1.*Hflag;
comet_kernel = H1/sum((H1(:)));
smearedImage = conv2(double(I),comet_kernel,'same');
% Fix edges
smearedImage(:,[1:L, end-L:end]) = I(:,[1:L, end-L:end]); % Left/Right edge
smearedImage([1:L, end-L:end], :) = I([1:L, end-L:end], :); % Top/bottom edge
% Keep only inner blur
smearedImage(L:end-L,L:end-L) = min(smearedImage(L:end-L,L:end-L),double(I(L:end-L,L:end-L)));
figure
imshow(smearedImage,[]);
title(num2str(THETA(i)*180/pi))
set(gcf, 'Units', 'Normalized', 'OuterPosition', [0 0 1 1]);
end
Upvotes: 0
Reputation: 332
I think you want what's called a "comet" kernel. I'm not sure what kernel is used for the "motion" blur, but I'd guess that it's symmetrical based on the image you provided.
Here is some code to play with that applies the comet kernel in one direction. You'll have to change things around if you want an arbitrary angle. You can see from the output that it's smearing in one direction, since there is a black band on only one side (due to the lack of pixels there).
L = 5; % kernel width
sigma=0.2; % kernel smoothness
I = imread('cameraman.tif');
x = -L:1.0:L;
[X,Y] = meshgrid(x,x);
H1 = exp((-sigma.*X.^2)+(-sigma.*Y.^2));
kernel = H1/sum((H1(:)));
Hflag = double((X>0));
comet_kernel = Hflag.*H1;
comet_kernel=comet_kernel/sum(comet_kernel(:));
smearedImage = conv2(double(I),comet_kernel,'same');
imshow(smearedImage,[]);
Updated code: This will apply an arbitrary rotation to the comet kernel. Note also the difference between sigma
in the previous example and sx
and sy
here, which control the length and width parameters of the kernel, as suggested by Andras in the comments.
L = 5; % kernel width
sx=3;
sy=10;
theta=0;
I = imread('cameraman.tif');
x = -L:1.0:L;
[X,Y] = meshgrid(x,x);
rX = X.*cos(theta)-Y.*sin(theta);
rY = X.*sin(theta)+Y.*cos(theta);
H1 = exp(-((rX./sx).^2)-((rY./sy).^2));
Hflag = double((0.*rX+rY)>0);
H1 = H1.*Hflag;
comet_kernel = H1/sum((H1(:)))
smearedImage = conv2(double(I),comet_kernel,'same');
imshow(smearedImage,[]);
Upvotes: 3