Federico Gentile
Federico Gentile

Reputation: 5940

How to blur an image in one specific direction in Matlab?

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);

enter image description here

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

Answers (2)

Federico Gentile
Federico Gentile

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

Anger Density
Anger Density

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,[]);

Add image output

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

Related Questions