How to fix the undefined function or variable error? - image

I am working on Matlab 17.a program's image processing. My work is about histogram equalization. The code is as follows. But when I run the code "Undefined function or variable 'cumulavite_hist'." I get an error. How do I fix this problem? Thank you for your help.
The output will be the histogram next to the original image. Below it will be the changing picture and histogram. Thank you for your help.
>> img= imread ('C:\Users\emre.guzel\Desktop\homeworkimage.png');
if (size(img,3)>1)
img=rgb2gray(img);
end
max_r = size (img,1);
max_c =size (img,2);
histogram =zeros ([1 256]);
cumulative_hist = zeros ([1 256]);
for r=1:max_r
for c=1:max_c
for count =1:256
if(img(r,c) == count-1 )
histogram (count) =histogram (count)+ 1;
break ;
end
end
end
end
%find cumulative histogram
current_value = 0;
for count=1:256
current_value = current_value + histogram (count);
cumulative_hist(count) = current_value;
end
%find h =(cdf-cdf(min) / (MN - cdf (min) )) * 255
%this is the normalized cumulative histogram normalize dediğine bakma sen.
%histogram equalization formulu bu . aşağıda da bunu uygulamış.
normalized_hist = zeros ([1 256]);
cdf_min = min (cumulavite_hist) ;
for count = 1:256
normalized_hist(count) = cumulative_hist(count) - cdf_min;
normalized_hist(count) = normalized_hist (count) / ((max_r*max_c)- cdf_min);
normalized_hist(count) = round (normalized_hist (count) * 255);
end
%replace the values with given equalized values
equalized_image = zeros ([max_r max_c]);
for r =1:max_r
for c=1:max_c
for count = 1:256
if(img(r,c) ==(count-1))
%
%
equlized_img(r,c) = normalized_hist(count);
break;
end
end
end
end
subplot(2,2,1)
imshow(img);
title('Orijinal Image');
subplot (2,2,2);
imhist(img) ;
title ('Hist of Orijinal Image');
subplot(2,2,3) ;
imhist (uint8(equalized_img));
title('Histogram Equalized Image');
H = uint (equalized_img);
subplot(2,2,4) ;
imhist(H) ;
title ('Histogram of Histogram Equalized Image');
a = histeq(img);
figure
imshow(a)

You have cumulative_hist variable at line 10 and cumulavite_hist variable used in line 33. It's just wrong name in line 33. Fix it and program will work.

Related

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,:);

Optimizing for loop in Matlab

I'm writing a "Peak finder" in Matlab. I've never used Matlab or anything similar before this project, so I'm new to "vectorizing" my code. Essentially, the program needs to take a video of molecules and plot circles on the molecules present in each frame of the video. If a molecule is crowded then it gets a red circle, but if it is not crowded it gets a green circle.
My problem is that some of these videos have 2000 frames and my program takes up to ~25 seconds to process a single frame, which is not practical.
Using tic and toc I've found the trouble maker: A for-loop which calls a function that contains a for-loop.
function getPeaks( orgnl_img, processed_img, cut_off, radius )
% find large peaks peaks by thresholding, i.e. you accept a peak only
% if its more than 'threshold' higher than its neighbors
threshold = 2*std2(orgnl_img);
peaks = (orgnl_img - processed_img) > threshold;
% m and n are dimensions of the frame, named peaks
[m, n] = size(peaks);
cc_centroids = regionprops(peaks, 'centroid');
% Pre-allocate arrays
x_centroid = zeros(1, length(cc_centroids));
y_centroid = zeros(1, length(cc_centroids));
for i = 1:length(cc_centroids)
% Extract the x and y components from cc_centroids struct
x_centroid(i) = cc_centroids(i).Centroid(1);
y_centroid(i) = cc_centroids(i).Centroid(2);
row = int64(x_centroid(i));
col = int64(y_centroid(i));
% Assure that script doesnt attempt to exceed frame
if col-2 > 0 && row-2 > 0 && col+2 < m && row+2 < n
region_of_interest = orgnl_img(col-2:col+2,row-2:row+2);
local_intensity = max(region_of_interest(:));
% Do not plot circle when intensity is 'cut off' or lower
if local_intensity > cut_off
dist_bool = findDistance(cc_centroids, x_centroid(i), y_centroid(i), radius);
if dist_bool == 1
color = 'g';
else
color = 'r';
end
plotCircle(color, x_centroid(i), y_centroid(i), radius)
end
end
end
end
And here is the findDistance function which contains another for-loop and determines if the circles overlap:
function dist_bool = findDistance( all_centroids, x_crrnt, y_crrnt, radius )
x_nearby = zeros(1, length(all_centroids));
y_nearby = zeros(1, length(all_centroids));
for i = 1:length(all_centroids)
if all_centroids(i).Centroid(1) < (x_crrnt+2*radius) &&...
all_centroids(i).Centroid(1) > (x_crrnt-2*radius) &&...
all_centroids(i).Centroid(2) < (y_crrnt+2*radius) &&...
all_centroids(i).Centroid(2) > (y_crrnt-2*radius)
x_nearby(i) = all_centroids(i).Centroid(1);
y_nearby(i) = all_centroids(i).Centroid(2);
pts_of_interest = [x_nearby(i),y_nearby(i);x_crrnt,y_crrnt];
dist = pdist(pts_of_interest);
if dist == 0 || dist > 2*radius
dist_bool = 1;
else
dist_bool = 0;
break
end
end
end
end
I think that there must be much improvement to be done here. I would appreciate any advice.
Thanks! :)
UPDATE: Here are the profiler results. The first section of code is the "getPeaks" function
http://i.stack.imgur.com/VaLdH.png
The hold comes from the plot circle function:
function plotCircle( color, x_centroid, y_centroid, radius )
hold on;
th = 0:pi/50:2*pi;
xunit = radius * cos(th) + x_centroid;
yunit = radius * sin(th) + y_centroid;
plot(xunit, yunit, color);
hold off;
end

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)

Discrete cosine transform (DCT) of an image

I work on a function in Matlab that calculates the DCT (discrete cosine transform) of an image. I don't know what is not working in my code, but I got an output image with the same number. I want to use this formula for my DCT.
Any ideas please.
function image_comp = dctII(image, b)
[h w] = size(image);
image = double(image) - 128;
block = zeros(b,b);
image_t=zeros(size(image));
for k=1:b:h
for l=1:b:w
image_t(k:k+b-1,l:l+b-1)= image(k:k+b-1,l:l+b-1);
for u=1:b
for v=1:b
if u == 0
Cu = 1/sqrt(2);
else
Cu = 1;
end
if v == 0
Cv = 1/sqrt(2);
else
Cv = 1;
end
Res_sum=0;
for x=1:b;
for y=1:b
Res_sum = Res_sum + ((image_t(x,y))*cos(((2*x)+1)*u*pi/(2*b))*cos(((2*y)+1)*v*pi/(2*b)));
end
end
dct= (1/4)*Cu*Cv*Res_sum;
block(u,v) = dct;
end
end
image_comp(k:k+b-1,l:l+b-1)=block(u,v);
end
end
end
In the inner loop over x and y, you are not reading from the correct place in image_t. You have copied the local block into a location with k,l as the upper left corner for use in processing, but in the inner loop you are always reading from the same block that starts at 1,1 as the upper left corner in image_t.

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