I am trying to make a custom autocorrelation function in matlab according to info in the image below:
the function works but i get an error that index exceeds matrix dimensions, mathematically it's wright but in programming am i missing something? Here is my code:
close all; clear all; clc;
[x,fs]=audioread('c1.wav');
N=length(x); %// length of signal
n1=128; %// length of window
win_num=floor(N/n1); %// number of windows
m=1:n1;
for l=1:n1/2:win_num %// 50% overlapping - 64 samples for a 128 window
for n=1:N-m
cmax(n)=max(sum(x(n+m)*conj(x(n))));
end
end
thanks in advance.
I am assuming that when you do for n=1:N-m you want to do for n=1:N-max(m) (or for n=N-m(end)).
If you do the first one N-m returns an array, not a single value, as m is an array!
Related
I need a matlab code to make MxN sliding window without nfilter() function to do adaptive and local operation like adaptive threshold.
For example, I want to implement OTSU's thresholding method graythresh() in each rectangle (MxN window) not pixel to pixel.
I wrote this code but it has some problem:
im=imread('cameraman.tif');
imshow(im);figure,title('original image')
M=64; %lenght of window
N=64; %width of widow
[row,col]=size(im);
out=zeros(M,N);
out1=zeros(row,N);
for i=1:N:row
for j=1:M:col
mask=im(i:i+N-1,j:j+M-1);
bw=im2bw(mask,graythresh(mask));
out=[out,bw];imshow(out),title('output')
end
% out1=[out1;out];
% out=zeros(M,N);
end
% figure,imshow(out1)
input image:
http://i.stack.imgur.com/L0EZo.png
output image:
http://i.stack.imgur.com/dmP9j.png
This is a complete rewrite of my original post as I now know what you're trying to do. Your code does work in that you want to extract M x N distinct neighbourhoods, perform Otsu's algorithm on each neighbourhood, then set these neighbourhoods to an output image.
However, you are not constructing the final image properly. You are stacking the neighbourhoods column-wise but what you need to do you need to move down to the next rows once you reach the end column of the image. To get your code working, the easiest thing would be to have another matrix that you create within the loop that goes over the columns and when you get to the end, concatenate this matrix to the output image row-wise. I've removed some fluff from your code to get to my point quickly:
im=imread('cameraman.tif');
M=64; %//height of window
N=64; %//width of widow
[row,col]=size(im);
out = []; %// Create output image
for i=1:N:row
out1 = []; %// Inner matrix
for j=1:M:col
mask=im(i:i+N-1,j:j+M-1);
bw=im2bw(mask,graythresh(mask));
out1 = [out1 bw]; %// Concatenate column-wise
end
out = [out; out1]; %// Take inner matrix and concatenate row-wise
end
figure; subplot(1,2,1); imshow(im); title('Original Image');
subplot(1,2,2); imshow(out); title('Thresholded Image');
I'm placing the original image and thresholded image in the same figure, and we get:
However, because in your comments above you mentioned that you have blockproc available, I would recommend you use that to minimize how much code you write. blockproc allows you to process distinct pixel neighbourhoods in an image. With each pixel neighbourhood, you can do whatever you want to them. In our case, we want to apply Otsu's algorithm to each block and threshold it. You can very much achieve the above resulting code in one line:
out = blockproc(im, [64 64], #(x) im2bw(x.data, graythresh(x.data)));
im would be the input image and out would be the output image. The second parameter tells you how big each block is and the third function is a custom function you write that is applied to each block. The input into this function is a structure where data is a structure element that gives you a block in an image. Therefore, you would use im2bw and graythresh in the same method like you did above, but you would do this with the data field.
To go one more step further, you said you also have colfilt available which does the same thing above as blockproc but it reshapes the image so that the neighbourhood blocks are placed into columns, applies the function to each column then reconstructs the image back to its original dimensions.
As such:
out = colfilt(im, [64 64], 'distinct', #(x) im2bw(x, graythresh(x)));
You can see that the above syntax is almost the same as blockproc, but here we must specify the 'distinct' flag to tell colfilt that we want distinct neighbourhoods, and not overlapping ones. Also, it is known that colfilt is faster than blockproc (consult the documentation on colfilt - link above).
I have a code to find the pdf's approximation of a vector based on the formula for kernel estimation:
I implemented this formula in the code below (see previous question). However, that code takes long time to run (two loops are used). Could you see the below code and help me to make it faster?
This is the code:
function pdf_est=KDE()
close all;
%%Random values of 20 pixels, range=[1 256]
data=randi([1 256],1,20)-1; %// changed: "-1"
%% Estimate histogram%%%%%
pdf_est=zeros(1,256);
z=256;
for i=0:z-1 %// changed_ subtracted 1
for j=1:length(data)
pdf_est(i+1)=pdf_est(i+1)+Gaussian(i-data(j)); %// changed: "+1" (twice)
end
end
%% Plot real histogram 1 to 256; binsize=1;
hold on
plot(0:255, imhist(uint8(data))./length(data),'r'); %// changed: explicit x axis
%% Plot histogram estimation
plot(0:255, pdf_est./length(data),'b'); %// changed: explicit x axis
hold off
function K=Gaussian(x)
sigma=1; %// change? Set as desired
K=1./(sqrt(2*pi)*sigma)*exp(-x^2./(2*sigma^2));
You can get rid of both of those nasty nested loops and then use the hardcoded sigma to have a mega-reduced vectorized solution -
pdf_est = sum(1./(sqrt(2*pi))*exp(-bsxfun(#minus,[0:z-1]',data).^2/2),2)
Or if you would like to have the flexibility to have sigma around, use this -
sum(1./(sqrt(2*pi)*sigma)*exp(-bsxfun(#minus,[0:z-1]',data).^2/(2*sigma^2)),2)
That's all really there is!
Quick tests put this to speedup the original code by 10x!
I have a m-by-n matrix of values between 10^-20 and 10^-8
I drew it by
figure();
hist(My_mat(:),15);
I obtain only one bins of the hist,also with '15' but I would to obtain several of bins between min and max values
Do you have any suggestions?
Indeed. To draw a histogram having arbitrary bins use:
nbins=10;
figure();
hist(data,nbins)
However, if no second argument is given the standard of 10 bins is used. I suspect your vector contains all identical numbers therefore yielding only a single column. Could you verify this?
Kind regards,
Ernst Jan
This works for me (I get 15 bins):
C=rand(300,600)*1e-20; % to have similar numbers as you have
nbins = 15;
hist(C(:),nbins);
If you still have problems, try
close all; clearvars;
before executing the rest.
I was wondering if anyone could look at this code. I'm trying to do a 3x3 gaussian kernel without using any matlab built-in functions. (Yes I am aware of all the built in functions of gaussian and convolution ie fspecial)
the result gives me a white image instead. not sure what's the problem with it.
clc;
close all;
clear all;
img=imread('image.jpg');
figure,imshow(img);
img2=zeros(size(img)+2);
newImg=zeros(size(img));
for rgb=1:3
for x=1:size(img,1)
for y=1:size(img,2)
img2(x+1,y+1,rgb)=img(x,y,rgb);
end
end
end
for i= 1:size(img2,1)-2
for j=1:size(img2,2)-2
window=zeros(9,1);
inc=1;
for x=1:3
for y=1:3
window(inc)=img2(i+x-1,j+y-1,rgb);
inc=inc+1;
end
end
kernel=[1;2;1;2;4;2;1;2;1];
% kernel=[0;1;0;1;-4;1;0;1;0];
med=window.*kernel;
disp(med);
med=sum(med);
med=floor(med);
newImg(i,j,:)=med;
end
end
newImg=uint8(newImg);
figure,imshow(newImg);
Thanks.
I guess you should normalize the kernel. I mean, devide each element by the sum of their value (16), to make their sum equal to 1:
kernel=[1;2;1;2;4;2;1;2;1]/16;
when i try to resize an image by computing the average of 4 pixels to get one pixel, i got a problem, and following are my code, help me please, it's driving me crazy
a=imread('c:\black and white.jpg');
[rows,columns,phases]=size(a);
i=1;j=1;k=1;
c=zeros(rows/2,columns/2,phases);
c=uint8(c);
for x=1:2:rows-1;
for y=1:2:columns;
for z=1:phases;
c(i,j,k)=1/4*(a(x,y,z)+a(x,y+1,z)+a(x+1,y,z)+a(x+1,y+1,z));
k=k+1;
end
j=j+1;
k=1;
end
i=i+1;
j=1;
k=1;
end
figure, imshow(a)
figure, imshow(c)
You can do it without loops, by computing block averages along each column and then alog each row, as follows.
I am assuming your data is an image, i.e. a 2D array. If you have a 3D array with several images piled along the 3rd dimension (as it seems to be in your code), just apply this to each image (that is, for each value of the 3rd index).
Matrix size and block size are arbitrary, as long as block size divides the number of rows and columns of the input matrix a.
a = rand(100,120); % example data
n = 2; % block size
m = size(a)/n; % assumed to be integer
c = reshape(mean(reshape(a,n,[])),m(1),[]).'; % mean by colummns in groups of n
c = reshape(mean(reshape(c,n,[])),m(2),[]).'; % mean by rows in groups of n
Perhaps your question is as simple as this, assuming you have a image called myImage:
First make sure the number of pixels in each direction is even
myImage = myImage(1:fix(end/2)*2,1:fix(end/2)*2)
Then take the average of each 4 pixels
(myImage(1:2:end,1:2:end)+myImage(2:2:end,1:2:end)+ ...
myImage(1:2:end,2:2:end)+myImage(2:2:end,2:2:end))/4
Note that this assumes that you don't mind losing the last row or column of pixels, otherwise you need to do something smarter.