I have a noisy image that I am trying to clean using a lowpass filter (code below, modified from here). The image I get as a result is essentially identical to the one I gave as an input.
I'm not an expert, but my conclusion would be that the input image is so noisy that no patterns are found. Do you agree? Do you have any suggestion on how to interpret the result?
Result from the code:
Input image:
Code:
clear; close all;
frame = 20;
size_y = 512; % This is actually size_x
size_x = 256; % This is actually size_y
roi=5;thresh=100000;
AA = imread('image.png');
A = zeros(size_x, size_y);
A = AA(1:size_x, 1:size_y);
A(isnan(A)) = 0 ;
B = fftshift(fft2(A));
fabs = abs(B);
figure; imshow(B);
local_extr = ordfilt2(fabs, roi^2, ones(roi)); % find local maximum within 3*3 range
result = (fabs == local_extr) & (fabs > thresh);
[r, c] = find(result);
for i=1:length(r)
if (r(i)-128)^2+(c(i)-128)^2>thresh % periodic noise locates in the position outside the 20-pixel-radius circle
B(r(i)-2:r(i)+2,c(i)-2:c(i)+2)=0; % zero the frequency components
end
end
Inew=ifft2(fftshift(B));
figure;
subplot(2,1,1); imagesc(A), colormap(gray); title('Original image');
subplot(2,1,2);imagesc(real(Inew)),colormap(gray); title('Filtered image');
For filtering this kind of signal, you can try to use the median filter. It might be more appropriated than a means or Gaussian filter. The median filter is very effective on "salt and paper" noise when the mean just blur the noise.
As the signal seems very noisy, you need to try to find the good size of kernel for the filter. You can also try to increase the contrast of the image (after filtering) in order to see more the difference between the gray levels.
Related
I've taken the following image:
PandaNoise.bmp and tried to remove the periodic noise by focusing on its Fourier spectrum. Commented lines are the ones I'm not sure about. I can't get it back to the image plane. What am I doing wrong here?
panda = imread('PandaNoise.bmp');
fpanda = fft2(panda); % 2d fast fourier transform
fpanda = fftshift(fpanda); % center FFT
fpanda = abs(fpanda); % get magnitude
fpanda = log(1 + fpanda); % use log to expand range of dark pixels into bright region
fpanda = mat2gray(fpanda); % scale image from 0 to 1
figure; imshow(fpanda,[]); % show the picture
zpanda = fpanda;
zpanda(fpanda<0.5)=0;
zpanda(fpanda>0.5)=1;
%img = ifft2(zpanda);
%img = ifftshift(img);
%img = exp(1-img);
%img = abs(img);
Here is an example of how to work with the complex Fourier transform. We can take the log modulus for display, but don't change the original Fourier transform matrix, since the phase information that we throw away with abs is very important.
% Load data
panda = imread('https://i.stack.imgur.com/9SlW5.png');
panda = im2double(panda);
% Forward transform
fpanda = fft2(panda);
% Prepare FT for display -- don't change fpanda!
fd = fftshift(fpanda);
fd = log(1 + abs(fd));
figure; imshow(fd,[]); % show the picture
% From here we learn that we should keep the central 1/5th along both axes
% Low-pass filter
sz = size(fpanda);
center = floor(sz/2)+1;
half_width = ceil(sz/10)-1;
filter = zeros(sz);
filter(center(1)+(-half_width(1):half_width(1)),...
center(2)+(-half_width(2):half_width(2))) = 1;
filter = ifftshift(filter); % The origin should be on the top-left, like that of fpanda.
fpanda = fpanda .* filter;
% Inverse transform
newpanda = ifft2(fpanda);
figure; imshow(newpanda);
After computing the ifft2, newpanda is supposed to be purely real-valued if we designed the filter correctly (i.e. perfectly symmetric around the origin). Any imaginary component still present should be purely numerical innacuracy. MATLAB will detect that the input to ifft2 is conjugate symmetric, and return a purely real result. Octave will not, and you would have to do newpanda=real(newpanda) to avoid warnings from imshow.
Here is the input image 5.png:
Here is my code:
clear all; close all; clc;
%Input Image
A = imread('C:\Users\efu\Desktop\5.png');
% figure, imshow(A);
C=medfilt2(A,[3 5]);
% figure,imshow(C);
D=imfill(C);
% figure,imshow(D);
%Image obtained using MATLAB function 'edge'
E=edge(D,'canny',[0.01 .02],3);
figure, imshow(E); title('Image obtained using MATLAB function');
image=E;
img=im2bw(image);
% imshow(img)
se = strel('line',3,0);
zz = imerode(img,se);
figure, imshow(zz);
Output after canny edge detection:
After Eroding:
Here the problem is that after eroding all horizontal edges are broken, but I don't want that. I want to extract all horizontal lines without breaking, besides want to remove all vertical and diagonal lines.
Please someone modify the code.
It's a hack but it works. A short note, I would advise against using clear all. It has some negative effects such as clearing references to your mex functions. I'm not really sure what that means but there seems to be no real use for it unless you want to clear global variables.
Basically what I did here was threefold. I added a gaussian filter to give a bit more tolerance, increased the erosion rate of strel, and searched across angles to give a bit of angle tolerance. In the end, you have a bit more than you started with on the horizontal part but it does clear the image up a lot better. If you wanted you could just add up the zz matrices and threshold it to get a new binary image which could be a bit closer to your original. Really enjoyed the question by the way and made me look forward to image processing in the fall.
clear; close all;
%Input Image
A = imread('5.png');
% figure, imshow(A);
C=medfilt2(A,[3 5]);
% figure,imshow(C);
D=imfill(C);
% figure,imshow(D);
%Image obtained using MATLAB function 'edge'
E=edge(D,'canny',[0.01 .02],4);
figure, imshow(E); title('Image obtained using MATLAB function');
image=E;
img=double(image);
img = imgaussfilt(img,.5);
% imshow(img)
zz_out = zeros(size(img));
% se = strel('line',3,-90);
% zz = imerode(img,se);
% se2 = strel('line',3,0);
% zz2 = imerode(img,se2);
for ii = -5:.1:5
se = strel('line',20,ii);
zz = imerode(img,se);
zz_out = or(zz,zz_out);
end
% zz_out = img-zz;
figure, imshow(zz_out);
I separated the High Frequency (HF) component and low-frequency (LF) component from an image. After this step, I applied some denoising technique to the HF and LF. Afterwards I want to combine them together. How can I do that this?
I used the below code for decomposition
%// Load an image
Orig = double(rgb2gray(imread('lena.jpg')));
O=ROFdenoise(Orig, 12);
O=uint8(O);
figure, imshow(O)
%// Transform
Orig_T = dct2(Orig);
%// Split between high - and low-frequency in the spectrum (*)
cutoff = round(0.5 * 226);
High_T = fliplr(tril(fliplr(Orig_T), cutoff));
Low_T = Orig_T - High_T;
%// Transform back
High = idct2(High_T);
Low = idct2(Low_T);
I've commented out ROFdenoise because I don't know what it does. If you've split your image in the frequency domain, you want to combine it back together in frequency too. Also; I've added some plotting to make it easier to see what's happening.
%// Load an image
Orig = double(rgb2gray(imread('Lenna.png')));
%O=ROFdenoise(Orig, 12);
O=Orig; % No denoising before DCT
O=uint8(O);
figure(1), subplot(2,2,1), imshow(O), title('Before')
%// Discrete Cosine Transform
T = dct2(Orig);
%// Split between high - and low-frequency in the spectrum (*)
cutoff = round(0.5 * 226);
highT = fliplr(tril(fliplr(T), cutoff));
lowT = T - highT;
%//Do some denoising
highT = 0*highT;
subplot(2,2,2), imshow(highT), title('High T')
subplot(2,2,4), imshow(lowT), title('Low T')
%// Combine back
denoiseT = highT + lowT;
%// Transform back
denoiseO = uint8(idct2(denoiseT));
subplot(2,2,3), imshow(denoiseO), title('After')
Also; here is Lenna
what i want to do is a histogram for quantized DCT coefficient for an image, to detect Double Quantization effect. when i use hist(x) it will categorize it in to 10s and if i changed it to hist(x,20) or 30 it does not really show the DQ effect. so is there any better way for this??
here is the code: on matlab
im = jpeg_read('image');
% Pull image information - Lum, Cb, Cr
lum = im.coef_arrays{im.comp_info(1).component_id};
cb = im.coef_arrays{im.comp_info(2).component_id};
cr = im.coef_arrays{im.comp_info(3).component_id};
% Pull quantization arrays
lqtable = im.quant_tables{im.comp_info(1).quant_tbl_no};
cqtable = im.quant_tables{im.comp_info(2).quant_tbl_no};
% Quantize above two sets of information
qcof = quantize(lum,lqtable);
bqcof = quantize(cb,cqtable);
rqcof = quantize(cr,cqtable);
hist(qcof,30); %lum quantized dct coefficient histogram
First, no need to quantize the coefficients. Secondly, the effect can be observed by plotting histograms of certain frequencies. You need to go through various positions in the blocks and look for the pattern. Plotting FFT of the histogram helps.
Here is the matlab code:
imJPG2 = jpeg_read('foto2.jpg');
lum = imJPG2.coef_arrays{imJPG2.comp_info(1).component_id};
for i = 1:8
for j = 1:8
r = lum( i:8:end, j:8:end );
histogram(r(:), 'binmethod','integers');
pause();
end
end
More details and background can be found in this paper: http://www.sciencedirect.com/science/article/pii/S0031320309001198
I am using fft2 to compute the Fourier Transform of a grayscale image in MATLAB.
What is the common way to plot the magnitude of the result?
Assuming that I is your input image and F is its Fourier Transform (i.e. F = fft2(I))
You can use this code:
F = fftshift(F); % Center FFT
F = abs(F); % Get the magnitude
F = log(F+1); % Use log, for perceptual scaling, and +1 since log(0) is undefined
F = mat2gray(F); % Use mat2gray to scale the image between 0 and 1
imshow(F,[]); % Display the result
Here is an example from my HOW TO Matlab page:
close all; clear all;
img = imread('lena.tif','tif');
imagesc(img)
img = fftshift(img(:,:,2));
F = fft2(img);
figure;
imagesc(100*log(1+abs(fftshift(F)))); colormap(gray);
title('magnitude spectrum');
figure;
imagesc(angle(F)); colormap(gray);
title('phase spectrum');
This gives the magnitude spectrum and phase spectrum of the image. I used a color image, but you can easily adjust it to use gray image as well.
ps. I just noticed that on Matlab 2012a the above image is no longer included. So, just replace the first line above with say
img = imread('ngc6543a.jpg');
and it will work. I used an older version of Matlab to make the above example and just copied it here.
On the scaling factor
When we plot the 2D Fourier transform magnitude, we need to scale the pixel values using log transform to expand the range of the dark pixels into the bright region so we can better see the transform. We use a c value in the equation
s = c log(1+r)
There is no known way to pre detrmine this scale that I know. Just need to
try different values to get on you like. I used 100 in the above example.