making convolution in matlab manualy - matlab-figure

I want to make convolution image processing in matlab without to use (conv2) command
I want to use (.^) command with 2 for loop
I make this code to make LoG 5x5 filter
but it not work in this line (I(r,c) =sum(sum( Mask.* I( (r-2):(c-2), (r+2):(c+2) ) ));)
clc
clear;
Img = imread ('11.jpg'); %reading Image
for x = 1:size(Img,1) % converting to Gray
for y =1:size(Img,2)
G (x,y)= (Img(x,y,1)*0.3 + Img(x,y,2)*0.59 + Img(x,y,1)* 0.11);
end
end
Mask = [0,0,-1,0,0;0,-1,-2,-1,0;-1,-2,16,-2,-1;0,-1,-2,-1,0;0,0,-1,0,0]; % the mask
I=double(G);Mask=double(Mask);
% I=conv2(G,Mask); % masking quickly
for r = 3: size(I,1)-2 %masking manualy
for c = 3: size(I,2)-2
I(r,c) =sum(sum( Mask.* I( (r-2):(c-2), (r+2):(c+2) ) ));
end
end
imshow(Img);title('Orginal Image');
figure,imshow(G);title('Gray Image');
figure,imshow(uint8(I));title('Proccessed Image');

Debug is a good way to solve some problems.
When c = 4, r = 3(The second loop in "for c = 3: size(I,2)-2")
I( (r-2):(c-2), (r+2):(c+2) ) is a 2 * 2 Matrix,
and Mask is a 5*5 Matrix.
So the error message is "Matrix dimensions must be consistent".

Related

Octave: Function to display greyscale matrix shows and all black image instead

I'm doing assignment 3 from Andrew Ng's Machine Learning course on Coursera. The assignment comes with a .mat containing a 5000x400 matrix (denoted X) with values between 0 and 1 corresponding to a gray scale. Each row represents and image of size 20x20.
The assignment comes with a pre-made function that is used to display the images in a sort of grid, called DisplayData(X, width).
The problem is, this function only displays an all black figure. Since this code is course standard and I didn't mess with it at all, my guess is something must be wrong with my Octave. I'm using popOS and installed Octave via terminal with 'apt'. I'm working with Octave console in an open shell. Anyhow, I'll leave the function's code here:
function [h, display_array] = displayData(X, example_width)
%DISPLAYDATA Display 2D data in a nice grid
% [h, display_array] = DISPLAYDATA(X, example_width) displays 2D data
% stored in X in a nice grid. It returns the figure handle h and the
% displayed array if requested.
% Set example_width automatically if not passed in
if ~exist('example_width', 'var') || isempty(example_width)
example_width = round(sqrt(size(X, 2)));
end
% Gray Image
colormap(gray);
% Compute rows, cols
[m n] = size(X);
example_height = (n / example_width);
% Compute number of items to display
display_rows = floor(sqrt(m));
display_cols = ceil(m / display_rows);
% Between images padding
pad = 1;
% Setup blank display
display_array = - ones(pad + display_rows * (example_height + pad), ...
pad + display_cols * (example_width + pad));
% Copy each example into a patch on the display array
curr_ex = 1;
for j = 1:display_rows
for i = 1:display_cols
if curr_ex > m,
break;
end
% Copy the patch
% Get the max value of the patch
max_val = max(abs(X(curr_ex, :)));
display_array(pad + (j - 1) * (example_height + pad) + (1:example_height), ...
pad + (i - 1) * (example_width + pad) + (1:example_width)) = ...
reshape(X(curr_ex, :), example_height, example_width) / max_val;
curr_ex = curr_ex + 1;
end
if curr_ex > m,
break;
end
end
% Display Image
h = imagesc(display_array, [-1 1]);
% Do not show axis
axis image off
drawnow;
end
Using the command graphics_toolkit('gnuplot'); solved the problem!

K-means for image compression only gives black-and-white result

I'm doing this exercise by Andrew NG about using k-means to reduce the number of colors in an image. But the problem is my code only gives a black-and-white image :( . I have checked every step in the algorithm but it still won't give the correct result. Please help me, thank you very much
Here is the link of the exercise, and here is the dataset.
The correct result is given in the link of the exercise. And here is my black-and-white image:
Here is my code:
function [] = KMeans()
Image = double(imread('bird_small.tiff'));
[rows,cols, RGB] = size(Image);
Points = reshape(Image,rows * cols, RGB);
K = 16;
Centroids = zeros(K,RGB);
s = RandStream('mt19937ar','Seed',0);
% Initialization :
% Pick out K random colours and make sure they are all different
% from each other! This prevents the situation where two of the means
% are assigned to the exact same colour, therefore we don't have to
% worry about division by zero in the E-step
% However, if K = 16 for example, and there are only 15 colours in the
% image, then this while loop will never exit!!! This needs to be
% addressed in the future :(
% TODO : Vectorize this part!
done = false;
while done == false
RowIndex = randperm(s,rows);
ColIndex = randperm(s,cols);
RowIndex = RowIndex(1:K);
ColIndex = ColIndex(1:K);
for i = 1 : K
for j = 1 : RGB
Centroids(i,j) = Image(RowIndex(i),ColIndex(i),j);
end
end
Centroids = sort(Centroids,2);
Centroids = unique(Centroids,'rows');
if size(Centroids,1) == K
done = true;
end
end;
% imshow(imread('bird_small.tiff'))
%
% for i = 1 : K
% hold on;
% plot(RowIndex(i),ColIndex(i),'r+','MarkerSize',50)
% end
eps = 0.01; % Epsilon
IterNum = 0;
while 1
% E-step: Estimate membership given parameters
% Membership: The centroid that each colour is assigned to
% Parameters: Location of centroids
Dist = pdist2(Points,Centroids,'euclidean');
[~, WhichCentroid] = min(Dist,[],2);
% M-step: Estimate parameters given membership
% Membership: The centroid that each colour is assigned to
% Parameters: Location of centroids
% TODO: Vectorize this part!
OldCentroids = Centroids;
for i = 1 : K
PointsInCentroid = Points((find(WhichCentroid == i))',:);
NumOfPoints = size(PointsInCentroid,1);
% Note that NumOfPoints is never equal to 0, as a result of
% the initialization. Or .... ???????
if NumOfPoints ~= 0
Centroids(i,:) = sum(PointsInCentroid , 1) / NumOfPoints ;
end
end
% Check for convergence: Here we use the L2 distance
IterNum = IterNum + 1;
Margins = sqrt(sum((Centroids - OldCentroids).^2, 2));
if sum(Margins > eps) == 0
break;
end
end
IterNum;
Centroids ;
% Load the larger image
[LargerImage,ColorMap] = imread('bird_large.tiff');
LargerImage = double(LargerImage);
[largeRows,largeCols,~] = size(LargerImage); % RGB is always 3
% Dist = zeros(size(Centroids,1),RGB);
% TODO: Vectorize this part!
% Replace each of the pixel with the nearest centroid
for i = 1 : largeRows
for j = 1 : largeCols
Dist = pdist2(Centroids,reshape(LargerImage(i,j,:),1,RGB),'euclidean');
[~,WhichCentroid] = min(Dist);
LargerImage(i,j,:) = Centroids(WhichCentroid);
end
end
% Display new image
imshow(uint8(round(LargerImage)),ColorMap)
imwrite(uint8(round(LargerImage)), 'D:\Hoctap\bird_kmeans.tiff');
You're indexing into Centroids with a single linear index.
Centroids(WhichCentroid)
This is going to return a single value (specifically the red value for that centroid). When you assign this to LargerImage(i,j,:), it will assign all RGB channels the same value resulting in a grayscale image.
You likely want to grab all columns of the selected centroid to provide an array of red, green, and blue values that you want to assign to LargerImage(i,j,:). You can do by using a colon : to specify all columns of Centroids which belong to the row indicated by WhichCentroid.
LargerImage(i,j,:) = Centroids(WhichCentroid,:);

error in box averaging filter of an image using matlab

I need to downsize an image using a box averaging filter , I tried to write this code but there was an error : Unknown command option. , where is the error and what is the correct algorithm for box filter i know the idea of it ,the new pixel = averaging the four neighboring pixels .
the code:
clear, clc
image=imread('p128.jpg');
old_size=size(image);
out_image=zeros(old_size(1)/2 , old_size(2)/2);
for i = 1 : old_size(1) - 1
for j= 1 : old_size(2) - 1
for k= i : i+1
for t= j : j+1
out_image(k,t)=(image(i,j)+image(i+1,j)+image(i,j+1)+...
image(i+1,j+1))/4 ;
end
end
end
end
figure(1), imshow(out_image)
You can use im2cols with 'distinct' from Image Processing Toolbox to re-arrange the windows elements into columns and then calculate the average of each column, which would represent the average of each window. Now, in the comments you said you don't want to use any function from IP toolbox, so we have replaced im2cols with our own custom made implementation. Thus, assuming im to be the input grayscale image data, you can use this -
box_len = 2; %// length of the box
im_cols = im2col_distinct(im,[box_len box_len]);
im_downsized = uint8(reshape(mean(im_cols,1),size(im,1)/box_len,[]));
Associated function -
function out = im2col_distinct(A,blocksize)
nrows = blocksize(1);
ncols = blocksize(2);
nele = nrows*ncols;
row_ext = mod(size(A,1),nrows);
col_ext = mod(size(A,2),ncols);
padrowlen = (row_ext~=0)*(nrows - row_ext);
padcollen = (col_ext~=0)*(ncols - col_ext);
A1 = zeros(size(A,1)+padrowlen,size(A,2)+padcollen);
A1(1:size(A,1),1:size(A,2)) = A;
t1 = reshape(A1,nrows,size(A1,1)/nrows,[]);
t2 = reshape(permute(t1,[1 3 2]),size(t1,1)*size(t1,3),[]);
t3 = permute(reshape(t2,nele,size(t2,1)/nele,[]),[1 3 2]);
out = reshape(t3,nele,[]);
return;
Thus, you would be avoiding all that messy nested loops with your original code.
Input :
Output :

Matlab histogram equilization without using built in function

Hello I am new at Matlab..I am trying to do histogram equilzation without using histeq...
but for some reason i always get an error of : ??? Index exceeds matrix dimensions.
here is my code..................................................Thanks for your help
clc
I = imread ('Machine-Edge.PNG');
I2 = rgb2gray(I);
colormap gray;
y = imhist(I2);
%using hist eq. built in fn
I3= histeq(I2);
z= imhist(I3);
%my equalization
r = size(I2,1);
c = size(I2,2);
A= zeros(1,256);
%counting number of pixels of the image and putting the count in Array A
for j=1:r
for x=1:c
v=I2(j,x);
A(v+1)=A(v+1)+1;
end
end
%pi=n/size
for y=1;256
pi(y)= ((A(y))/(r*c));
end
%calculate CI (cumulated pi )
ci(1)=pi(1);
for yy=2;256
ci(yy) = ci(yy-1)+ pi(yy);
end
%calculate T=range *Ci
for b=1;256
T(b)=ci(b)*255;
end
%equilization..replacing each pixel with T value
for j=1:r
for x=1:c
I4(j,x) =T(I2(j,x));
end
end
vv= imhist(I4);
figure
subplot(3,2,1)
imagesc(I2)
subplot(3,2,2)
plot(y)
subplot(3,2,3)
imagesc(I3)
subplot(3,2,4)
plot(z)
subplot(3,2,5)
imagesc(I4)
subplot(3,2,6)
plot(vv)
This is an old post but the OP used ; instead of : in their for loops (i.e. for y=1;256 should read for y=1:256). the corrected code is below:
clc
I = imread ('Machine-Edge.PNG');
I2 = rgb2gray(I);
colormap gray;
y = imhist(I2);
%using hist eq. built in fn
I3= histeq(I2);
z= imhist(I3);
%my equalization
r = size(I2,1);
c = size(I2,2);
A= zeros(1,256);
%counting number of pixels of the image and putting the count in Array A
for j=1:r
for x=1:c
v=I2(j,x);
A(v+1)=A(v+1)+1;
end
end
%pi=n/size
for y=1:256
pi(y)= ((A(y))/(r*c));
end
%calculate CI (cumulated pi )
ci(1)=pi(1);
for yy=2:256
ci(yy) = ci(yy-1)+ pi(yy);
end
%calculate T=range *Ci
for b=1:256
T(b)=ci(b)*255;
end
%equilization..replacing each pixel with T value
for j=1:r
for x=1:c
I4(j,x) =T(I2(j,x));
end
end
vv= imhist(I4);
figure
subplot(3,2,1)
imagesc(I2)
subplot(3,2,2)
plot(y)
subplot(3,2,3)
imagesc(I3)
subplot(3,2,4)
plot(z)
subplot(3,2,5)
imagesc(I4)
subplot(3,2,6)
plot(vv)

How to make a Gaussian filter in Matlab

I have tried to make a Gaussian filter in Matlab without using imfilter() and fspecial().
I have tried this but result is not like the one I have with imfilter and fspecial.
Here is my codes.
function Gaussian_filtered = Gauss(image_x, sigma)
% for single axis
% http://en.wikipedia.org/wiki/Gaussian_filter
Gaussian_filtered = exp(-image_x^2/(2*sigma^2)) / (sigma*sqrt(2*pi));
end
for 2D Gaussian,
function h = Gaussian2D(hsize, sigma)
n1 = hsize;
n2 = hsize;
for i = 1 : n2
for j = 1 : n1
% size is 10;
% -5<center<5 area is covered.
c = [j-(n1+1)/2 i-(n2+1)/2]';
% A product of both axes is 2D Gaussian filtering
h(i,j) = Gauss(c(1), sigma)*Gauss(c(2), sigma);
end
end
end
and the final one is
function Filtered = GaussianFilter(ImageData, hsize, sigma)
%Get the result of Gaussian
filter_ = Gaussian2D(hsize, sigma);
%check image
[r, c] = size(ImageData);
Filtered = zeros(r, c);
for i=1:r
for j=1:c
for k=1:hsize
for m=1:hsize
Filtered = Filtered + ImageData(i,j).*filter_(k,m);
end
end
end
end
end
But the processed image is almost same as the input image. I wonder the last function GaussianFiltered() is problematic...
Thanks.
here's an alternative:
Create the 2D-Gaussian:
function f=gaussian2d(N,sigma)
% N is grid size, sigma speaks for itself
[x y]=meshgrid(round(-N/2):round(N/2), round(-N/2):round(N/2));
f=exp(-x.^2/(2*sigma^2)-y.^2/(2*sigma^2));
f=f./sum(f(:));
Filtered image, given your image is called Im:
filtered_signal=conv2(Im,gaussian2d(N,sig),'same');
Here's some plots:
imagesc(gaussian2d(7,2.5))
Im=rand(100);subplot(1,2,1);imagesc(Im)
subplot(1,2,2);imagesc(conv2(Im,gaussian2d(7,2.5),'same'));
This example code is slow because of the for-loops. In matlab you can better use conv2, as suggested by user:bla, or just use filter2.
I = imread('peppers.png'); %load example data
I = I(:,:,1);
N=5; %must be odd
sigma=1;
figure(1);imagesc(I);colormap gray
x=1:N;
X=exp(-(x-((N+1)/2)).^2/(2*sigma^2));
h=X'*X;
h=h./sum(h(:));
%I=filter2(h,I); %this is faster
[is,js]=size(I);
Ib = NaN(is+N-1,js+N-1); %add borders
b=(N-1)/2 +1;
Ib(b:b+is-1,b:b+js-1)=I;
I=zeros(size(I));
for i = 1:is
for j = 1:js
I(i,j)=sum(sum(Ib(i:i+N-1,j:j+N-1).*h,'omitnan'));
end
end
figure(2);imagesc(I);colormap gray

Resources