I created a method in Matlab for quantizing an Image.
But I don't seem to get a good quantization of the image.
(For example, when I quantize the image after using DWT and then use IDWT, the image is filled with squares).
what is wrong with the quantization method?
function [imQuant, error] = quantizeImage(imOrig, nQuant, nIter)
[imQuant, error] = quantizeImageHelper(imOrig, nQuant, nIter);
end
function [imQuant, error] = quantizeImageHelper(imOrig, nQuant, nIter)
% Helper function for the quantizeImage function.
imOrig = uint8(round(imOrig*255));
imHist = imhist(imOrig);
% Calculate number of pixels in the image.
height = size(imOrig, 1);
width = size(imOrig, 2);
numOfPixels = height*width;
% Initialize the error vector.
error = zeros(1, nIter);
% Compute the first division of the intensities to segments.
z = computeInitialZ(imHist, numOfPixels, nQuant);
% P(z) - the probability of each intensity in the image.
pz = imHist/numOfPixels;
% Compute q, the vector of the new intensities of the quantized image.
q = qFromZ(z, pz, nQuant);
% Compute the error of the first z and q we calculated.
error(1) = calculateError(z, q, pz, nQuant);
% Compute z,q, and error, and keep improving the results until
% you reach the wanted number of iteration, or you reach convergence
% of the errors.
for i=1:nIter-1
z = zFromQ(q, nQuant);
q = qFromZ(z, pz, nQuant);
error(i+1) = calculateError(z, q, pz, nQuant);
if (error(i) == error(i+1))
break
end
end
% Calculate the new look up table which contains the new intensities
% of the quantized image.
lookUpTable = zeros(1,256);
for i=1:nQuant
lookUpTable(z(i)+1:z(i+1)+1) = q(i);
end
% Quantize the image by mapping each pixel to the new corresponding
% intensity.
imQuant = zeros(size(imOrig));
imQuant(:,:) = lookUpTable(imOrig(:, :)+1);
imQuant = double(imQuant)/255;
% Crop the error vector to remove reccuring converging values.
error = error(error ~= 0);
end
function [z] = computeInitialZ(imHist, numOfPixels, nQuant)
% Compute the initial division of the intensities to segments.
% Each segment contains approximately the same number of pixels.
% Input: imHist - the histogram of the original image.
% numOfPixels - number of pixels in the image.
% nQuant - the number of intensities the output imQuant image will
% have.
% Output: z - the initial division of the intensities to segments.
z = zeros(1, nQuant+1);
z(1) = 0;
z(nQuant+1) = 255;
% Use the cumulative histogram for approximate equal division of the
% segments.
imHistCumSum = cumsum(imHist);
pixelsForSegment = round(numOfPixels/nQuant);
currentPixelCount = pixelsForSegment;
for i=2:nQuant
z(i) = find(imHistCumSum > currentPixelCount, 1)-1;
currentPixelCount = pixelsForSegment*i;
end
end
function [z] = zFromQ(q, nQuant)
% Compute the division of the intensities to segments by using
% the formula to compute z out of q.
% Input: q - the new intensities of the quantized image.
% nQuant - the number of intensities the output imQuant image will
% have.
% Output: z - the division of the intensities to segments.
z = zeros(1, nQuant+1);
z(nQuant+1) = 255;
for i=2:nQuant
z(i) = floor((q(i-1)+q(i))/2);
end
end
function [q] = qFromZ(z, pz, nQuant)
% Compute the new intensities of the quantized image by using the formula
% the formula to compute q out of z and the intensity probability function.
% Input: z - the segment division of the intensities.
% pz - the intensity probabilty function.
% nQuant - the number of intensities the output imQuant image will
% have.
% Output: q - the new intensities of the quantized image.
q = zeros(1, nQuant);
pzSum = zeros(1, nQuant);
zpz = zeros(1, nQuant);
for i=1:nQuant
pzSum(i) = sum(pz(z(i)+1:z(i+1)+1));
zpz(i) = ((z(i)+1):(z(i+1)+1))*(pz(z(i)+1:z(i+1)+1));
q(i) = floor(zpz(i)/pzSum(i));
end
end
function [error] = calculateError(z, q, pz, nQuant)
% Compute the error values from the z and q values.
% Input: z - the segment division of the intensities.
% q - the new intensities of the quantized image.
% pz - the intensity probabilty function.
% nQuant - the number of intensities the output imQuant image will
% have.
% Output: error - the error of the current z and q computation.
error = 0;
for i=1:nQuant
error = error + ((q(i) - (z(i)+1:z(i+1)+1)).^2)*(pz(z(i)+1:z(i+1)+1));
end
end
edit: This is for example a the result of DWT->quantizing the LH,HL,HH values ->IDWT. the image is filled with squares.
Related
I would like to rotate (30 degrees) an image in Matlab but without using imwarp, imtranslate, imrotate, imresize.
My code is following:
image = imread('image.jpg');
theta = 30;
tform = affine2d([cosd(theta) sind(theta) 0; -sind(theta) cosd(theta) 0; 0 0 1]);
[X,Y] = transformPointsForward(tform,1:800,1:800);
I believe I should be using imref2d, but I'm not entirely sure how.
How can I assign the new coordinates? I would like the rest of the space (used by the image) to be black (pixel value = 0).
The correct way doing it is not so trivial.
The rotation matrix in your post is "centered" - (0,0) is the center coordinate.
We need transformation matrix in which (1,1) is the top left coordinate.
You need to transform all the coordinates of the image.
In your post you are only transforming coordinates (1,1), (2,2), (3,3)...
Using forward transformation creates "holes" - not all pixels in the destination image are filled.
We need to use backward transformation, and for every destination pixel, get the coordinate of the source pixel (destination to source transformation is considered "backward transformation").
Using the inverse transformation with transformPointsForward is equivalent to backward transformation.
Note: Your transformation matrix is actually the "backward transformation".
Here is how to solve it (please read the comments):
I = rgb2gray(imread('peppers.png')); % Read sample image and convert to gray.
[rows, cols] = size(I);
theta = 30;
% The rotation matrix is "centered" - coordinate (0, 0) is the center:
cT = [cosd(theta) -sind(theta) 0; sind(theta) cosd(theta) 0; 0 0 1];
top2cen = [1 0 0
0 1 0
(cols+1)/2 (rows+1)/2 1];
cen2top = [1 0 0
0 1 0
-(cols+1)/2 -(rows+1)/2 1];
% We need the rotation matrix to be "top left" - coordinate (1, 1) is the top left coordinate:
T = cen2top*cT*top2cen; % Note: you don't really need to use matrix multiplications for solving this.
tform = affine2d(T);
% All the combinations of u,v coordinates
[U, V] = meshgrid(1:cols, 1:rows);
% Transform all the (u, v) coordinates of the input I.
[X, Y] = transformPointsForward(tform, U, V);
% Round the coordinates - the interpolation method is going to Nearest Neighbor.
X = round(X);
Y = round(Y);
J = zeros(size(I), 'like', I);
% Limit the X,Y coordinates to the valid range.
limX = max(min(X, cols), 1);
limY = max(min(Y, rows), 1);
% Copy the (u,v) pixel in I to position (x,y) in J.
J(sub2ind(size(I), limY, limX)) = I(sub2ind(size(I), V, U));
% Oops... J has many holes...
figure;imshow(J);
imwrite(J, 'fwJ.png');
% Correct way:
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% We must inverse the transformation - use backward transformation instead of forward transformation.
%cT = inv([cosd(theta) -sind(theta) 0; sind(theta) cosd(theta) 0; 0 0 1]);
cT = [cosd(theta) sind(theta) 0; -sind(theta) cosd(theta) 0; 0 0 1]; % Inverse transformation matrix.
% Repeate the process with inversed transformation.
T = cen2top*cT*top2cen;
tform = affine2d(T);
[U, V] = meshgrid(1:cols, 1:rows);
% Transform all the (x, y) coordinates of the input I.
[X, Y] = transformPointsForward(tform, U, V); % Name the coordinates U, V
% Round the coordinates - the interpolation method is going to Nearest Neighbor.
X = round(X);
Y = round(Y);
J = zeros(size(I), 'like', I);
% Limit the X,Y coordinates to the valid range.
limX = max(min(X, cols), 1);
limY = max(min(Y, rows), 1);
J(sub2ind(size(I), V, U)) = I(sub2ind(size(I), limY, limX));
% Zero the margins (place zeros where X, Y are outside of the valid range):
J((X < 1) | (Y < 1) | (X > cols) | (Y > rows)) = 0;
figure;imshow(J)
imwrite(J, 'J.png');
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Testing
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Reference:
K = imrotate(I, 30, 'nearest', 'crop');
figure;imshow(K)
% Display the difference from imrotate (images are equal).
figure;imagesc(double(K) - double(J));
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Result of forward transformation (the wrong way):
Result of backward transformation (the right way):
I am trying to solve a problem which I may struggle to describe, so will attempt to describe with the aid of the following picture (please bear with me!):
I have two matrices which are defined on different coordinate spaces (u,v) for matrix A and (x,y) for matrix B. They have different grid sizes and different numbers of pixels. My goal is to apply a scaling factor S to the matrix A, and then to simply add it to matrix B. (For context, this is an optical imaging problem, where matrix A is located at an object plane, matrix B is located at an image plane, and S is the magnification).
So, I would like to create a new matrix C which is the equivalent of A but brought into the new coordinates (x,y). Matrix C should have the same number of rows and columns as B.
A minimum example of A and B is shown below, where the red dashed lines on the right illustrate the effective physical regions occupied by matrix A's pixels:
This is produced by the following code:
%%% Inputs for matrix A %%%
M = 4; % num columns in matrix A
N = 4; % num rows in matrix A
du = 13; % horizontal size of a pixel in matrix A [mm]
dv = 13; % vertical size of a pixel in matrix A [mm]
%%% Set up matrix A %%%
Lu = (M-1)*du; % physical hor. coord. of centre of last pixel [mm]
Lv = (N-1)*dv; % physical ver. coord. of centre of last pixel [mm]
u = -Lu/2:du:Lu/2; % hor. coordinates for matrix A [mm]
v = -Lv/2:dv:Lv/2; % ver. coordinates for matrix A [mm]
A = zeros(N,M);
A(1,1) = 1; % Set a few values to 1 for testing
A(2,3) = 1;
A(3,4) = 1;
%%% Inputs for matrix B %%%
dx = 0.1; % grid step in matrix B [mm]
dy = 0.1; % grid step in matrix B [mm]
Lx = 6; % physical hor. coord. of centre of last pixel [mm]
Ly = 6; % physical ver. coord. of centre of last pixel [mm]
%%% Set up matrix B %%%
x = -Lx/2:dx:Lx/2;
y = -Ly/2:dy:Ly/2;
B = rand(length(y),length(x));
figure('color','w');
subplot(1,2,1);imagesc(u, v, A); axis equal tight;
subplot(1,2,2);imagesc(x, y, B); axis equal tight;
S = 1/20; % scale factor from matrix A's corrdinates to matrix B's
% C = ?
In this example, I have set the pixel size of matrix A to be 13mm, and the scaling factor to be 1/20. This means that in B's coordinates each pixel should be 13/20 = 0.65mm. This is bigger than the grid size dx=0.1mm, and so in this case the result should be that, after mapping, pixels should span multiple grid points. Any region outside the total extent of matrix A should be padded with zeros.
Is there a simple way (or built-in function) which would quickly generate matrix C in Matlab (ideally without using loops over each pixel, or interpolation)?
I can simply scale the coordinates, which matches the physical dimensions, but the matrices are still different number of rows and columns:
u_scaled = u*S;
v_scaled = v*S;
subplot(1,3,3);imagesc(u_scaled, v_scaled, A); axis equal tight;
You can use interp2 or griddedInterpolant:
C = interp2(u, v, A, x * 20, y.' * 20, 'nearest', 0);
With some modification better result can be produced:
AA = padarray(A, [1 1], 0);
uu = [-du+u(1) u u(end)+du];
vv = [-dv+v(1) v v(end)+dv];
C = interp2(uu, vv, AA, x * 20, y.' * 20, 'nearest', 0);
Currently I have been working on obtaining the length of a curve, with the following code I have managed to get the length of a curve present in an image.
test image one curve
Then I paste the code that I used to get the length of the curve of a simple image. What I did is the following:
I got the columns and rows of the image
I got the columns in x and the rows in y
I obtained the coefficients of the curve, based on the formula of the
parable
Build the equation
Implement the arc length formula to obtain the length of the curve
grayImage = imread(fullFileName);
[rows, columns, numberOfColorBands] = size(grayImage);
if numberOfColorBands > 1
grayImage = grayImage(:, :, 2); % Take green channel.
end
subplot(2, 2, 1);
imshow(grayImage, []);
% Get the rows (y) and columns (x).
[rows, columns] = find(binaryImage);
coefficients = polyfit(columns, rows, 2); % Gets coefficients of the formula.
% Fit a curve to 500 points in the range that x has.
fittedX = linspace(min(columns), max(columns), 500);
% Now get the y values.
fittedY = polyval(coefficients, fittedX);
% Plot the fitting:
subplot(2,2,3:4);
plot(fittedX, fittedY, 'b-', 'linewidth', 4);
grid on;
xlabel('X', 'FontSize', fontSize);
ylabel('Y', 'FontSize', fontSize);
% Overlay the original points in red.
hold on;
plot(columns, rows, 'r+', 'LineWidth', 2, 'MarkerSize', 10)
formula = poly2sym([coefficients(1),coefficients(2),coefficients(3)]);
% formulaD = vpa(formula)
df=diff(formula);
df = df^2;
f= (sqrt(1+df));
i = int(f,min(columns),max(columns));
j = double(i);
disp(j);
Now I have the image 2 which has n curves, I do not know how I can do to get the length of each curve
test image n curves
I suggest you to look at Hough Transformation:
https://uk.mathworks.com/help/images/hough-transform.html
You will need Image Processing Toolbox. Otherwise, you have to develop your own logic.
https://en.wikipedia.org/wiki/Hough_transform
Update 1
I had a two-hour thinking about your problem and I'm only able to extract the first curve. The problem is to locate the starting points of the curves. Anyway, here is the code I come up with and hopefully will give you some ideas for further development.
clc;clear;close all;
grayImage = imread('2.png');
[rows, columns, numberOfColorBands] = size(grayImage);
if numberOfColorBands > 1
grayImage = grayImage(:, :, 2); % Take green channel.
end
% find edge.
bw = edge(grayImage,'canny');
imshow(bw);
[x, y] = find(bw == 1);
P = [x,y];
% For each point, find a point that is of distance 1 or sqrt(2) to it, i.e.
% find its connectivity.
cP = cell(1,length(x));
for i = 1:length(x)
px = x(i);
py = y(i);
dx = x - px*ones(size(x));
dy = y - py*ones(size(y));
distances = (dx.^2 + dy.^2).^0.5;
cP{i} = [x(distances == 1), y(distances == 1);
x(distances == sqrt(2)), y(distances == sqrt(2))];
end
% pick the first point and a second point that is connected to it.
fP = P(1,:);
Q(1,:) = fP;
Q(2,:) = cP{1}(1,:);
m = 2;
while true
% take the previous point from point set Q, when current point is
% Q(m,1)
pP = Q(m-1,:);
% find the index of the current point in point set P.
i = find(P(:,1) == Q(m,1) & P(:,2) == Q(m,2));
% Find the distances from the previous points to all points connected
% to the current point.
dx = cP{i}(:,1) - pP(1)*ones(length(cP{i}),1);
dy = cP{i}(:,2) - pP(2)*ones(length(cP{i}),1);
distances = (dx.^2 + dy.^2).^0.5;
% Take the farthest point as the next point.
m = m+1;
p_cache = cP{i}(find(distances==max(distances),1),:);
% Calculate the distance of this point to the first point.
distance = ((p_cache(1) - fP(1))^2 + (p_cache(2) - fP(2))^2).^0.5;
if distance == 0 || distance == 1
break;
else
Q(m,:) = p_cache;
end
end
% By now we should have built the ordered point set Q for the first curve.
% However, there is a significant weakness and this weakness prevents us to
% build the second curve.
Update 2
Some more work since the last update. I'm able to separate each curve now. The only problem I can see here is to have a good curve fitting. I would suggest B-spline or Bezier curves than polynomial fit. I think I will stop here and leave you to figure out the rest. Hope this helps.
Note that the following script uses Image Processing Toolbox to find the edges of the curves.
clc;clear;close all;
grayImage = imread('2.png');
[rows, columns, numberOfColorBands] = size(grayImage);
if numberOfColorBands > 1
grayImage = grayImage(:, :, 2); % Take green channel.
end
% find edge.
bw = edge(grayImage,'canny');
imshow(bw);
[x, y] = find(bw == 1);
P = [x,y];
% For each point, find a point that is of distance 1 or sqrt(2) to it, i.e.
% find its connectivity.
cP =[0,0]; % add a place holder
for i = 1:length(x)
px = x(i);
py = y(i);
dx = x - px*ones(size(x));
dy = y - py*ones(size(y));
distances = (dx.^2 + dy.^2).^0.5;
c = [find(distances == 1); find(distances == sqrt(2))];
cP(end+1:end+length(c),:) = [ones(length(c),1)*i, c];
end
cP (1,:) = [];% remove the place holder
% remove duplicates
cP = unique(sort(cP,2),'rows');
% seperating curves
Q{1} = cP(1,:);
for i = 2:length(cP)
cp = cP(i,:);
% search for points in cp in Q.
for j = 1:length(Q)
check = ismember(cp,Q{j});
if ~any(check) && j == length(Q) % if neither has been saved in Q
Q{end+1} = cp;
break;
elseif sum(check) == 2 % if both points cp has been saved in Q
break;
elseif sum(check) == 1 % if only one of the points exists in Q, add the one missing.
Q{j} = [Q{j}, cp(~check)];
break;
end
end
% review sets in Q, merge the ones having common points
for j = 1:length(Q)-1
q = Q{j};
for m = j+1:length(Q)
check = ismember(q,Q{m});
if sum(check)>=1 % if there are common points
Q{m} = [Q{m}, q(~check)]; % merge
Q{j} = []; % delete the merged set
break;
end
end
end
Q = Q(~cellfun('isempty',Q)); % remove empty cells;
end
% each cell in Q represents a curve. Note that points are not ordered.
figure;hold on;axis equal;grid on;
for i = 1:length(Q)
x_ = x(Q{i});
y_ = y(Q{i});
coefficients = polyfit(y_, x_, 3); % Gets coefficients of the formula.
% Fit a curve to 500 points in the range that x has.
fittedX = linspace(min(y_), max(y_), 500);
% Now get the y values.
fittedY = polyval(coefficients, fittedX);
plot(fittedX, fittedY, 'b-', 'linewidth', 4);
% Overlay the original points in red.
plot(y_, x_, 'r.', 'LineWidth', 2, 'MarkerSize', 1)
formula = poly2sym([coefficients(1),coefficients(2),coefficients(3)]);
% formulaD = vpa(formula)
df=diff(formula);
lengthOfCurve(i) = double(int((sqrt(1+df^2)),min(y_),max(y_)));
end
Result:
You can get a good approximation of the arc lengths using regionprops to estimate the perimeter of each region (i.e. arc) and then dividing that by 2. Here's how you would do this (requires the Image Processing Toolbox):
img = imread('6khWw.png'); % Load sample RGB image
bw = ~imbinarize(rgb2gray(img)); % Convert to grayscale, then binary, then invert it
data = regionprops(bw, 'PixelList', 'Perimeter'); % Get perimeter (and pixel coordinate
% list, for plotting later)
lens = [data.Perimeter]./2; % Compute lengths
imshow(bw) % Plot image
hold on;
for iLine = 1:numel(data),
xy = mean(data(iLine).PixelList); % Get mean of coordinates
text(xy(1), xy(2), num2str(lens(iLine), '%.2f'), 'Color', 'r'); % Plot text
end
And here's the plot this makes:
As a sanity check, we can use a simple test image to see how good an approximation this gives us:
testImage = zeros(100); % 100-by-100 image
testImage(5:95, 5) = 1; % Add a vertical line, 91 pixels long
testImage(5, 10:90) = 1; % Add a horizontal line, 81 pixels long
testImage(2020:101:6060) = 1; % Add a diagonal line 41-by-41 pixels
testImage = logical(imdilate(testImage, strel('disk', 1))); % Thicken lines slightly
Running the above code on this image, we get the following:
As you can see the horizontal and vertical line lengths come out close to what we expect, and the diagonal line is a little bit more than sqrt(2)*41 due to the dilation step extending its length slightly.
I try with this post but i don´t understand so much, but the idea Colours123 sounds great, this post talk about GUI https://www.mathworks.com/matlabcentral/fileexchange/24195-gui-utility-to-extract-x--y-data-series-from-matlab-figures
I think that you should go through the image and ask if there is a '1' if yes, ask the following and thus identify the beginning of a curve, get the length and save it in a BD, I am not very good with the code , But that's my idea
I have to use an inverse filter to remove the blurring from this image
.
Unfortunately, I have to figure out the transfer function H of the imaging
system used to get these sharper images, It should be Gaussian. So, I should determine the approximate width of the Gaussian by trying different Gaussian widths in an inverse filter and judging which resulting images look the “best”.
The best result will be optimally sharp – i.e., edges will look sharp but will not have visible ringing.
I tried by using 3 approaches:
I created a transfer function with N dimensions (odd number, for simplicity), by creating a grid of N dimensions, and then applying the Gaussian function to this grid. After that, we add zeroes to this transfer function in order to get the same size as the original image. However, after applying the filter to the original image, I just see noise (too many artifacts).
I created the transfer function with size as high as the original image, by creating a grid of the same size as the original image. If sigma is too small, then the PSF FFT magnitude is wide. Otherwise it gets thinner. If sigma is small, then the image is even more blurred, but if we set a very high sigma value then we get the same image (not better at all).
I used the fspecial function, playing with sizes of sigma and h. But still I do not get anything sharper than the original blurred image.
Any ideas?
Here is the code used for creating the transfer function in Approach 1:
%Create Gaussian Filter
function h = transfer_function(N, sigma, I) %N is the dimension of the kernel
%create a 2D-grid that is the same size as the Gaussian filter matrix
grid = -floor(N/2) : floor(N/2);
[x, y] = meshgrid(grid, grid);
arg = -(x.*x + y.*y)/(2*sigma*sigma);
h = exp(arg); %gaussian 2D-function
kernel = h/sum(h(:)); %Normalize so that total weight equals 1
[rows,cols] = size(I);
add_zeros_w = (rows - N)/2;
add_zeros_h = (cols - N)/2;
h = padarray(kernel,[add_zeros_w add_zeros_h],0,'both'); % h = kernel_final_matrix
end
And this is the code for every approach:
I = imread('lena_blur.jpg');
I1 = rgb2gray(I);
figure(1),
I1 = double(I1);
%---------------Approach 1
% N = 5; %Dimension Assume is an odd number
% sigma = 20; %The bigger number, the thinner the PSF in FREQ
% H = transfer_function(N, sigma, I1);
%I1=I1(2:end,2:end); %To simplify operations
imagesc(I1); colormap('gray'); title('Original Blurred Image')
I_fft = fftshift(fft2(I1)); %Shift the image in Fourier domain to let its DC part in the center of the image
% %FILTER-----------Approach 2---------------
% N = 5; %Dimension Assume is an odd number
% sigma = 20; %The bigger number, the thinner the PSF in FREQ
%
%
% [x,y] = meshgrid(-size(I,2)/2:size(I,2)/2-1, -size(I,1)/2:size(I,1)/2-1);
% H = exp(-(x.^2+y.^2)*sigma/2);
% %// Normalize so that total area (sum of all weights) is 1
% H = H /sum(H(:));
%
% %Avoid zero freqs
% for i = 1:size(I,2) %Cols
% for j = 1:size(I,1) %Rows
% if (H(i,j) == 0)
% H(i,j) = 1e-8;
% end
% end
% end
%
% [rows columns z] = size(I);
% G_filter_fft = fft2(H,rows,columns);
%FILTER---------------------------------
%Filter--------- Aproach 3------------
N = 21; %Dimension Assume is an odd number
sigma = 1.25; %The bigger number, the thinner the PSF in FREQ
H = fspecial('gaussian',N,sigma)
[rows columns z] = size(I);
G_filter_fft = fft2(H,rows,columns);
%Filter--------- Aproach 3------------
%DISPLAY FFT PSF MAGNITUDE
figure(2),
imshow(fftshift(abs(G_filter_fft)),[]); title('FFT PSF magnitude 2D');
% Yest = Y_blurred/Gaussian_Filter
I_restoration_fft = I_fft./G_filter_fft;
I_restoration = (ifft2(I_restoration_fft));
I_restoration = abs(I_restoration);
I_fft = abs(I_fft);
% Display of Frequency domain (To compare with the slides)
figure(3),
subplot(1,3,1);
imagesc(I_fft);colormap('gray');title('|DFT Blurred Image|')
subplot(1,3,2)
imshow(log(fftshift(abs(G_filter_fft))+1),[]) ;title('| Log DFT Point Spread Function + 1|');
subplot(1,3,3)
imagesc(abs(I_restoration_fft));colormap('gray'); title('|DFT Deblurred|')
% imshow(log(I_restoration+1),[])
%Display PSF FFT in 3D
figure(4)
hf_abs = abs(G_filter_fft);
%270x270
surf([-134:135]/135,[-134:135]/135,fftshift(hf_abs));
% surf([-134:134]/134,[-134:134]/134,fftshift(hf_abs));
shading interp, camlight, colormap jet
xlabel('PSF FFT magnitude')
%Display Result (it should be the de-blurred image)
figure(5),
%imshow(fftshift(I_restoration));
imagesc(I_restoration);colormap('gray'); title('Deblurred Image')
%Pseudo Inverse restoration
% cam_pinv = real(ifft2((abs(G_filter_fft) > 0.1).*I_fft./G_filter_fft));
% imshow(fftshift(cam_pinv));
% xlabel('pseudo-inverse restoration')
A possible solution is deconvwr. I will first show its performance starting from an undistorted lena image. So, I know exactly the gaussian blurring function. Note that setting estimated_nsr to zero will destroy the performance completely due to quantisation noise.
I_ori = imread('lenaTest3.jpg'); % Download an original undistorted lena file
N = 19;
sigma = 5;
H = fspecial('gaussian',N,sigma)
estimated_nsr = 0.05;
I = imfilter(I_ori, H)
wnr3 = deconvwnr(I, H, estimated_nsr);
figure
subplot(1, 4, 1);
imshow(I_ori)
subplot(1, 4, 2);
imshow(I)
subplot(1, 4, 3);
imshow(wnr3)
title('Restoration of Blurred, Noisy Image Using Estimated NSR');
subplot(1, 4, 4);
imshow(H, []);
The best parameters I found for your problem by trial and error.
N = 19;
sigma = 2;
H = fspecial('gaussian',N,sigma)
estimated_nsr = 0.05;
EDIT: calculating exactly the used blurring filter
If you download an undistorted lena (I_original_fft), you can calculate the used blurring filter as follows:
G_filter_fft = I_fft./I_original_fft
i already have this:
function [h] = histImage (img)
nPix = numel(img);
h = accumarray( img (:)+1 , ones(nPix,1)/nPix, [256 1] , #sum,0)
this function will return a grayscale histogram for a given img into a 1X256 vector
now i want to build this function:
input: img - grayscale image matrix in rage [0..255]
windowSize - a 1x2 array [r c] rows and cols.
output: histArray 3d matrix for every i,j the 1D array histArray(i,j,:) is the histogram of img of the size WindowSize whose top left corner is (i,j)
function [histArray] = localHistograms (img,windowSize)
histArray = zeros(windowSize(1),WindowSize(2),256);
for i = 1:windowSize(1)
for j = 1:windowSize(2)
histArray(i,j,:) = histImage(img( i:windowSize(1), j:windowSize(2) ))
end
end
end
this is what i have so far can u please tell me my mistake?
how can i check my mistakes ? just enter some random images?
ok so my friend help me figuring out my mistake here is the working and tested code:
function [ histArray ] = localHistograms ( img,windowSize )
% Given an image returns a 3D array of histograms –
% one histogram per window in image.
% Input:
% img - a grayscale image in the range [0..255]
% windowSize – a 1x2 array [r c] defining the num rows and num cols
% of image windows.
% Output:
% histArray – an NxMx256 array.
%
% For every (i,j) the 1D array histArray(i,j,:) is the histogram
% of an image window of size windowSize whose top left corner
% pixel is (i,j). Histograms of windows that exceed the boundary
% of the of img are not included in histArray (thus N = number of
% rows of img less the number of rows of window +1.
% Similarly M=size(img,2)-windowSize(2)+1 ).
%
% Method: Scans the img pixel by pixel. For each scanned pixel,
% determines the histogram of the image window starting at the
% pixel and extending windowSize(1) rows and windowSize(2).
N = size(img,1) - windowSize(1) + 1;
M = size(img,2) - windowSize(2) + 1;
histArray = zeros(N ,M,256);
for i = 1:N
for j = 1:M
histArray(i,j,:) = histImage(img(i:i+windowSize(1)-1,j:j+windowSize(2)-1));
end
end
end