local histograms - recomputing histograms for all parts of the image - Matlab - image

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

Related

Image deblurring using gaussian filter in matlab without additive noise

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

Image quantization in matlab

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.

Matlab transparent overlay matrix

I want to load an image and then create a Matrix with the size of the image.
The Matrix should be transparent with only some spare values (points).
I then want to show the image in a figure and put the Matrix on top.
The code so far:
world = imread('map1.jpg'); % import image of location
[x_world,y_world] = size(world); % get the size of the image
A = zeros(x_world,y_world); % create matrix with dimension of image
imshow(world); % display image
axis image; % label the axis
My Matrix contains some points:
A(200,300) = 1;
A(500,500) = 5;
A(580,200) = 3;
if I now iterate through each value in the Matrix like that:
for i = 1:x_world
for j = 1:y_world
if(A(i,j) == 1)
plot(i,j,'r.','MarkerSize',20); % plot a single point
elseif(A(i,j) == 2)
plot(i,j,'y.','MarkerSize',20); % plot a single point
elseif(A(i,j) == 3)
plot(i,j,'m.','MarkerSize',20); % plot a single point
elseif(A(i,j) == 4)
plot(i,j,'g.','MarkerSize',20); % plot a single point
elseif(A(i,j) == 5)
plot(i,j,'b.','MarkerSize',20); % plot a single point
elseif(A(i,j) == 6)
plot(i,j,'w.','MarkerSize',20); % plot a single point
end
end
end
it would be really slow.
So what I want to do is create a transparent Matrix and then set some points, so that I just can print the Matrix over the original image.
Is that possible? How do I do that? Is there maybe another better way to do that?
As a start, you could avoid looping over all of theese rows and columns by actually looping over your 6 groups. The code blow should give the same result:
markers = {'r.', 'y.', 'm.', 'g.', 'b.', 'w.'}; % // define some markers
figure
hold on
for group = 1:6
[i, j] = ind2sub(size(A), find(A==group)); % // find indices of current group
plot(i, j, markers{group}, 'markersize', 20) % // plot them with their marker
end
If speed is an issue, you maybe can have a look at gscatter() and or sparse().

How to draw repeating straight lines with specific radius and angle in matlab?

Suppose i would like to draw an image like the following:
Where the pixel values are refined to 0 for black and white for 1.
These line are drawn with specific radius and angles
Now I create a 80 x 160 matrix
texturematrix = zeros(80,160);
then i want to change particular elements to be 1 according to the lines conditions
but how do i make them repeatedly with specific distance apart from each others effectively?
Thanks a lot everyone!
This might not be what you are looking for, but generating such an image could be done by plotting a set of lines, as follows:
% grid sizes
m = 6;
n = 5;
% line length and angle
len = 1;
theta = .1*pi;
[a,b] = meshgrid(1:m,1:n);
x = reshape([a(:),a(:)+len*cos(theta),nan(numel(a),1)]',[],1);
y = reshape([b(:),b(:)+len*sin(theta),nan(numel(b),1)]',[],1);
h = figure();
plot(x,y,'k', 'LineWidth', 2);
But this has nothing to do with a texture matrix. So, we construct a matrix of desired size:
set(gca, 'position',[0 0 1 1], 'units','normalized', 'YTick',[], 'XTick',[]);
frame = frame2im(getframe(h),[0 0 1 1]);
im = imresize(frame,[80 160]);
M = ~(im(2:end,2:end,1)==255);

drawn image, converted back

i want to draw image, do not know how to portray the image output kmeans
my code:
close all; clc; clear;
img = imread('pic7.png');
figure(), imshow(img);
impixelregion;
% nastavenie noveho obrazka
[y x z] = size(img)
for i=1:1:y
for j=1:1:x
imgNew(i, j, :) = 0;
end
end
[X_no_dither, map]= rgb2ind(img,8,'nodither');
figure, imshow(X_no_dither, map);
impixelregion;
m = im2double(X_no_dither)
idx = kmeans(m,4,'emptyaction','singleton');
how i draw image ?
Thanks.
In kmeans, the rows are the things we want to cluster (i.e. pixels by colour), the columns are the variables. Therefore, we cannot just pass in a image straight in, it has to be reshaped first. For example if we look at this MATLAB example., the image is first converted into lab colorspace (and is in lab_he).
First, they take only the a and b elements:
ab = double(lab_he(:,:,2:3));
Then, reshape so that ab is of size n x m where n = total number of pixels and m = 2 - this is because each pixel is being clustered based on both a and b values:
nrows = size(ab,1);
ncols = size(ab,2);
ab = reshape(ab,nrows*ncols,2);
Now, sort those pixels into three colors:
nColors = 3;
% repeat the clustering 3 times to avoid local minima
[cluster_idx cluster_center] = kmeans(ab,nColors,'distance','sqEuclidean', ...
'Replicates',3);
The result then has to be reshape'd back into an image to be displayed:
pixel_labels = reshape(cluster_idx,nrows,ncols);
imshow(pixel_labels,[]), title('image labeled by cluster index');
In your case, as you're using a indexed image, try something like this:
idx = kmeans(m(:),4,'emptyaction','singleton');
idx = reshape(idx,size(m));
imshow(idx, []);
m(:) just arranges the pixels as a single column. kmeans then sorts them into four clusters. Afterwards, we reshape the indexes back using the size of our input image, and then display with imshow as normal.
You should read the linked example closely and make sure you understand what they are doing and why.

Resources