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!
Related
While using Matlab for image processing (exactly improving img by Fuzzy Logic) I found a really strange thing. My fuzzy function is correct, I tested it on random values and they are basically simple linear functions.
function f = Udark(z)
if z < 50
f = 1;
elseif z > 125
f = 0;
elseif (z >= 50) && (z <= 125)
f = -z/75 + 125/75;
end
end
where z is a value of a pixel (in grayscale). Now there is a really strange thing going on.
f = -z/75 + 125/75;, where a is an image. However, it is giving really different results if used as an input. I.e. if I use a variable p = 99, the output of the function is 0.3467 as it should be, when if I use A(i,j) it is giving me result f=2. Since it is clearly impossible, I do not know where is the problem. I thought that maybe there is a case with the type of the variable but if I change it to uint8 it stays the same... If you know what's going on, please, let me know :)
1.Changed line:
f = (125/75) - (z/75);
After editing the third condition the resultant/transformed image has no pixel values of 2. Not sure if you intend to work with decimals. If decimals are necessary using the im2double() function to convert the image and scaling it up by a factor of 255 might suffice your needs. See heading 3 for rounding details.
2.Reading in Image and Testing:
%Reading in the image and applying the function%
Image = imread("RGB_Image.png");
Greyscale_Image = rgb2gray(Image);
[Image_Height,Image_Width] = size(Greyscale_Image);
Transformed_Image = zeros(Image_Height,Image_Width);
for Row = 1: +1: Image_Height
for Column = 1: +1: Image_Width
Pixel_Value = Greyscale_Image(Row,Column);
[Transformed_Pixel_Value] = Udark(Pixel_Value);
Transformed_Image(Row,Column) = Transformed_Pixel_Value;
end
end
subplot(1,2,1); imshow(Greyscale_Image);
subplot(1,2,2); imshow(Transformed_Image);
%Checking that no transformed pixels falls in this impossible range%
Check = (Transformed_Image > (125/75)) & (Transformed_Image ~= 1);
Check_Flag = any(Check,'all');
%Function to transform pixel values%
function f = Udark(z)
if z < 50
f = 1;
elseif z > 125
f = 0;
elseif (z >= 50) && (z <= 125)
f = (125/75) - (z/75);
end
end
3.Evaluating the Specifics of the Third Condition
Working with integers (uint8) will force the values to be rounded to the nearest integer. Any number that falls between the range (50,125] will evaluate to 1 or 0.
f = -z/75 + 125/75;
If z = 50.1,
-50.1/75 + 125/75 = 74.9/75 ≈ 0.9987 → rounds to 1
Using MATLAB version: R2019b
I tried to create a gaussian noise mask which should be overlayed over my image with dimension sizeX, sizeY. I have found a way to do so by using the meshgrid function and it worked out fine:
function gaussian = GetGaussNoiseImage(sizeX, sizeY, A, std)
indicator = -floor(sizeX/2) : floor(sizeY/2);
[X Y] = meshgrid(indicator, indicator);
h = exp(-(X.^2 + Y.^2) / (2*std^2));
mesh(h);
My first approach though was the following:
function gaussian = GetGaussNoiseImage(sizeX, sizeY, A, std)
[sizeX sizeY] = size(I)
centerX = sizeX/2;
centerY = sizeY/2;
gaussian = zeros(sizeX, sizeY);
for i = 1:sizeX
for j = 1:sizeY
gaussian(i, j) = A.*exp(- ((i - centerX).^2 + (j - centerY).^2 )/2*std^2);
end
end
mesh(gaussian);
For me it is exactly the same aproach with the difference of including two for-loops. For some reason it does not want to function though. Can anybody explain to me what I did wrong?
Here is the my output image:
.
You have an error in the equation for the Gaussian. You write:
gaussian(i, j) = A.*exp(- ((i - centerX).^2 + (j - centerY).^2 )/2*std^2);
But you should instead do:
gaussian(i, j) = A.*exp(- ((i - centerX).^2 + (j - centerY).^2 )/ ( 2*std^2 ) );
^ ^
Note the added brackets! You have these in the first code snippet, but forgot them in the second.
i am asking for help.. I want to animate the Kaczmarz method on Matlab. It's method allows to find solution of system of equations by the serial projecting solution vector on hyperplanes, which which is given by the eqations of system.
And i want make animation of this vector moving (like the point is going on the projected vectors).
%% System of equations
% 2x + 3y = 4;
% x - y = 2;
% 6x + y = 15;
%%
A = [2 3;1 -1; 6 1];
f = [4; 2; 15];
resh = pinv(A)*f
x = -10:0.1:10;
e1 = (1 - 2*x)/3;
e2 = (x - 2);
e3 = 15 - 6*x;
plot(x,e1)
grid on
%
axis([0 4 -2 2])
hold on
plot(x,e2)
hold on
plot(x,e3)
hold on
precision = 0.001; % точность
iteration = 100; % количество итераций
lambda = 0.75; % лямбда
[m,n] = size(A);
x = zeros(n,1);
%count of norms
for i = 1:m
nrm(i) = norm(A(i,:));
end
for i = 1:1:iteration
j = mod(i-1,m) + 1;
if (nrm(j) <= 0), continue, end;
predx = x;
x = x + ((f(j) - A(j,:)*x)*A(j,:)')/(nrm(j))^2;
p = plot(x);
set(p)
%pause 0.04;
hold on;
if(norm(predx - x) <= precision), break, end
end
I wrote the code for this method, by don't imagine how make the animation, how I can use the set function.
In your code there are a lot of redundant and random pieces. Do not call hold on more than once, it does nothing. Also set(p) does nothing, you want to set some ps properties to something, then you use set.
Also, you are plotting the result, but not the "change". The change is a line between the previous and current, and that is the only reason you'd want to have a variable such as predx, to plot. SO USE IT!
Anyway, this following code plots your algorithm. I added a repeated line to plot in green and then delete, so you can see what the last step does. I also changed the plots in the begging to just plot in red so its more clear what is each of the things.
Change your loop for:
for i = 1:1:iteration
j = mod(i-1,m) + 1;
if (nrm(j) <= 0), continue, end;
predx = x;
x = x + ((f(j) - A(j,:)*x)*A(j,:)')/(nrm(j))^2;
plot([predx(1) x(1)],[predx(2) x(2)],'b'); %plot line
c=plot([predx(1) x(1)],[predx(2) x(2)],'g'); %plot it in green
pause(0.1)
children = get(gca, 'children'); %delete the green line
delete(children(1));
drawnow
% hold on;
if(norm(predx - x) <= precision), break, end
end
This will show:
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,:);
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