简体   繁体   中英

How to apply gaussian filter on single pixel of an image in matlab?

I have a white/black image. I want to apply Gaussian filter to the white pixels on this image. However, I want to apply it pixel by pixel as I want to give different Gaussian bandwidth parameters to different pixels.

For example, there are only 2 pixels on an image are white, others are black. I want to apply different Gaussian filter to these 2 pixels. Let's say X[2] and Y[2] are coordinates of the 2 pixels.

Gaussian bandwidth for X[0] and Y[0] is [10, 10], standard deviation is 1.
Gaussian bandwidth for X[1] and Y[1] is [20, 20], standard deviation is 3.

I know roifilt2 would work on ROI, but it seems that it only applies to an area of the image not a single pixel. I have coded by my understanding after I checked ROI processing, but the code below gives me error:

Error using imwrite (line 422)
Image data can not be empty.

Error in guassianFilter (line 73)
    imwrite(out,[outdir,imname,'.png'],'png');

It seems the filtered output image is empty. But I am new to matlab, I don't know why this is happening and how to fix it. :(

Is there any matlab functions that I can directly call to do the job?

Code:

    while ischar(tline)
        line = regexp(tline,' ','split');
        if(strcmp(line{1},'touch') == 1)
            c = floor(str2double(line{1,3})); % same as X[0] as I mentioned above 
            r = floor(str2double(line{1,4})); % same as Y[0] as I mentioned above 
            BW = roipoly(im,c,r); 
            G = fspecial('gaussian',[10 10],1);
            out = roifilt2(G,im,BW);
        end
        if(strcmp(line{1},'dT') == 1)
            c = floor(str2double(line{1,3})); % same as X[1] as I mentioned above 
            r = floor(str2double(line{1,4})); % same as X[1] as I mentioned above 
            BW = roipoly(im,c,r);
            G = fspecial('gaussian',[20 20], 3);
            out = roifilt2(G,im,BW);
        end
        tline = fgets(fid);
    end
    fclose(fid);

    imname=strtok(imList(cnt).name,'.');
    imwrite(out,[outdir,imname,'.png'],'png'); 

Before outlining an idea that should work, let me observe one problem with the code you posted. Looking at your calls to roifilt2 you see that out is overwritten with the result of each single-pixel instruction that you read from file. Even if you spotted some other bug that results in an empty result image, the result would never be the composite.

How about this. You could first read all the pixel positions and corresponding bandwidths from file, and then reconstruct the filtered image in two strokes from these coordinates alone. Reading the pixel list could look like this

fid = fopen('points.txt');
pxl = struct('x', {}, 'y', {}, 'sig', {});
n_pxl = 0;
tline = fgets(fid);
while ischar(tline)
    line = regexp(tline,' ','split');
    n_pxl = n_pxl + 1;
    pxl(n_pxl).x = floor(str2double(line{1,3}));
    pxl(n_pxl).y = floor(str2double(line{1,4}));
    if strcmp(line{1},'touch') == 1
        pxl(n_pxl).sig = 1;
    elseif strcmp(line{1},'dT') == 1
        pxl(n_pxl).sig = 3;
    else
        pxl(n_pxl).sig = nan;
    end
    tline = fgets(fid);
end
fclose(fid);

where x and y are the positions and sig is the bandwidth. Assuming that WIDTH and HEIGHT are the dimensions of your image, you could initialize the composite result image to flat out = zeros(HEIGHT, WIDTH); . A lookup vector for your filter sizes could be flt_size = [10, 15, 20]; . In some for -loop over sig = [1, 3] , we create each "slide" of the overlay, after collecting all the pixels corresponding to a particular sigma

im_raw = zeros(HEIGHT, WIDTH);
for k = find([pxl.sig] == sig)
    im_raw(pxl(k).y, pxl(k).x) = 1;
end

and increment the composite with the result of the filter operation

fsz = flt_size(sig);
out = out + conv2(im_raw, fspecial('gaussian', [fsz, fsz], sig), 'same');

Taken together, the loop would could like this:

out = zeros(HEIGHT, WIDTH);
flt_size = [10, 15, 20];
for sig = [1, 3]
    im_raw = zeros(HEIGHT, WIDTH);
    for k = find([pxl.sig] == sig)
        im_raw(pxl(k).y, pxl(k).x) = 1;
    end
    fsz = flt_size(sig); 
    out = out + conv2(im_raw, fspecial('gaussian', [fsz, fsz], sig), 'same');
end

Using slightly larger bandwidth for illustration, here an example, for two points in each category. The left and middle image show each "slide", and the right image shows the composite. Each image is shown scaled by imagesc .

例

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