简体   繁体   中英

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

在此处输入图片说明

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 (eg 45) and not both?

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM