How to divide a vector into frames in MATLAB? - matlab

I'am building a voice morphing system using MATLAB and I need to divide the source and target, training and test samples into frames of 128 samples so that I can then apply DWT on each of the frame.
So please guide me how to divide the vector into frames?

You can change a vector into a matrix of equally-sized columns/rows (i.e. frames) using the reshape function:
x = rand(128 * 100, 1);
X = reshape(x, 128, 100);
% X is a 128-by-100 matrix; the i-th column of 128 elements
% is addressed by X(:,i)

An alternative to using reshape would be to use buffer if you have the signal processing toolbox available. Simply . . .
y = buffer(x,128)
.. in your instance. The buffer command will also add trailing zeros to the final frame if the number of elements in your original signal (x) is not an integer multiple of 128.

Related

What is the reverse process of the repmat or repemel command?

I have a matrix of 50-by-1 that is demodulated data. As this matrix has only one element in each row, I want to repeat this only element 16 times in each row so the matrix become 50 by 16. I did it using the repmat(A,16) command in Matlab. Now at receiving end noise is also added in matrix of 50 by 16. I want to get it back of 50 by 1 matrix. How can I do this?
I tried averaging of all rows but it is not a valid method. How can I know when an error is occurring in this process?
You are describing a problem of the form y = A * x + n, where y is the observed data, A is a known linear transform, and n is noise. The least squares estimate is the simplest estimate of the unknown vector x. The keys here are to express the repmat() function as a matrix and the observed data as a vector (i.e., a 50*16x1 vector rather than a 50x16 matrix).
x = 10 * rand(50,1); % 50x1 data vector;
A = repmat(eye(length(x)),[16,1]); % This stacks 16 replicas of x.
n = rand(50*16,1); % Noise
y = A * x + n; % Observed data
xhat = A \ y; % Least squares estimate of x.
As for what the inverse (what I assume you mean by 'reverse') of A is, it doesn't have one. If you look at its rank, you'll see it is only 50. The best you can do is to use its pseudoinverse, which is what the \ operator does.
I hope the above helps.

Sample 1D vectors from 3D array using a vector of points

I have a n channel image and I have a 100x2 matrix of points (in my case n is 20 but perhaps it is more clear to think of this as a 3 channel image). I need to sample the image at each point and get an nx100 array of these image points.
I know how to do this with a for loop:
for j = 1:100
samples(j,:) = image(points(j,1),points(j,2),:);
end
How would I vectorize this? I have tried
samples = image(points);
but this gives 200 samples of 20 channels. And if I try
samples = image(points,:);
this gives me 200 samples of 4800 channels. Even
samples = image(points(:,1),points(:,2));
gives me 100 x 100 samples of 20 (one for each possible combination of x in X and y in Y)
A concise way to do this would be to reshape your image so that you force your image that was [nRows, nCols, nChannels] to be [nRows*nCols, nChannels]. Then you can convert your points array into a linear index (using sub2ind) which will correspond to the new "combined" row index. Then to grab all channels, you can simply use the colon operator (:) for the second dimension which now represents the channels.
% Determine the new row index that will correspond to each point after we reshape it
sz = size(image);
inds = sub2ind(sz([1, 2]), points(:,2), points(:,1));
% Do the reshaping (i.e. flatten the first two dimensions)
reshaped_image = reshape(image, [], size(image, 3));
% Grab the pixels (rows) that we care about for all channels
newimage = reshaped_image(inds, :);
size(newimage)
100 20
Now you have the image sampled at the points you wanted for all channels.

Increase/decrease play speed of a WAV file in MATLAB

Hello I need help in MATLAB.
My wave file plays with this code:
x=wavread('D:\\Sample.wav');
Now I want to increase/decrease the play speed of a WAV file in MATLAB with reshape. For example, double the speed.
Let me to Explain it .
when We use this code:
x=wavread('D:\\\Sample.wav');
now x is a Matrix 92086 * 1
and now I want to set zero for Decussate of X Like this:
0
value1
0
value2
...
...
now how can i do it whit reshape?
After that, I need to merge two WAV files into one WAV file. For example I have two files:
x=wavread('D:\\Sample1.wav');
y=wavread('D:\\Sample2.wav');
and need to merge these and play it.
I assume you mean to use the resample and not the reshape function. reshape is used to (well..) reshape a matrix, i.e. change the number of rows and columns. The resample function can be used to change the sampling rate of a signal. You can use this to increase / decrease the play speed of your WAV file. The syntax of resample is:
y = resample(x,p,q);
where x is the input signal, p is the desired sampling rate and q is the current sampling rate. The output y is then the input x, resampled at p/q times the original rate.
Now how can we double the speed? - If we set p=2 and q=1 we get a resampled signal at double the sampling rate, i.e. we have twice as many samples. If you play the WAV with the same command, then the signal takes twice as long to play, so we divided the play speed by 2.
To double the play speed, we'll have to do the opposite and set p=1 and q=2:
x = wavread('D:\\Sample.wav');
y = resample(x,1,2);
--
As requested in an edit, it is of course possible to add zeros e.g. at every second position to change the sampling rate. Note that this creates high-frequency noise, which is usually removed by FIR-filtering. The procedure however is quite easy:
x = x(:).'; % Make x a row vector
y = [x; zeros(1,numel(x))]; % add one zero between elements
y = y(:);
The last row does the magic here: it takes the columns of y and stacks them above each other. As x was one row, and we added a row of zeros below that, the resulting y will be a row containing all elements of x with zeros between the values.
As you specifically wanted to use reshape, we can do the same using reshape:
x = x(:).'; % Make x a row vector
y = [x; zeros(1,numel(x))]; % add one zero between elements
y = reshape(y,[],1);
--
To merge two WAV files into one, we can simply concatenate the vectors using the [...] notation or the cat function.
x = wavread('D:\\Sample1.wav');
y = wavread('D:\\Sample2.wav');
z = [x,y];
z = cat(2,x,y);

Using SVD to compress an image in MATLAB

I am brand new to MATLAB but am trying to do some image compression code for grayscale images.
Questions
How can I use SVD to trim off low-valued eigenvalues to reconstruct a compressed image?
Work/Attempts so far
My code so far is:
B=imread('images1.jpeg');
B=rgb2gray(B);
doubleB=double(B);
%read the image and store it as matrix B, convert the image to a grayscale
photo and convert the matrix to a class 'double' for values 0-255
[U,S,V]=svd(doubleB);
This allows me to successfully decompose the image matrix with eigenvalues stored in variable S.
How do I truncate S (which is 167x301, class double)? Let's say of the 167 eigenvalues I want to take only the top 100 (or any n really), how do I do that and reconstruct the compressed image?
Updated code/thoughts
Instead of putting a bunch of code in the comments section, this is the current draft I have. I have been able to successfully create the compressed image by manually changing N, but I would like to do 2 additional things:
1- Show a pannel of images for various compressions (i/e, run a loop for N = 5,10,25, etc.)
2- Somehow calculate the difference (error) between each image and the original and graph it.
I am horrible with understanding loops and output, but this is what I have tried:
B=imread('images1.jpeg');
B=rgb2gray(B);
doubleB=im2double(B);%
%read the image and store it as matrix B, convert the image to a grayscale
%photo and convert the image to a class 'double'
[U,S,V]=svd(doubleB);
C=S;
for N=[5,10,25,50,100]
C(N+1:end,:)=0;
C(:,N+1:end)=0;
D=U*C*V';
%Use singular value decomposition on the image doubleB, create a new matrix
%C (for Compression diagonal) and zero out all entries above N, (which in
%this case is 100). Then construct a new image, D, by using the new
%diagonal matrix C.
imshow(D);
error=C-D;
end
Obviously there are some errors because I don't get multiple pictures or know how to "graph" the error matrix
Although this question is old, it has helped me a lot to understand SVD. I have modified the code you have written in your question to make it work.
I believe you might have solved the problem, however just for the future reference for anyone visiting this page, I am including the complete code here with the output images and graph.
Below is the code:
close all
clear all
clc
%reading and converting the image
inImage=imread('fruits.jpg');
inImage=rgb2gray(inImage);
inImageD=double(inImage);
% decomposing the image using singular value decomposition
[U,S,V]=svd(inImageD);
% Using different number of singular values (diagonal of S) to compress and
% reconstruct the image
dispEr = [];
numSVals = [];
for N=5:25:300
% store the singular values in a temporary var
C = S;
% discard the diagonal values not required for compression
C(N+1:end,:)=0;
C(:,N+1:end)=0;
% Construct an Image using the selected singular values
D=U*C*V';
% display and compute error
figure;
buffer = sprintf('Image output using %d singular values', N)
imshow(uint8(D));
title(buffer);
error=sum(sum((inImageD-D).^2));
% store vals for display
dispEr = [dispEr; error];
numSVals = [numSVals; N];
end
% dislay the error graph
figure;
title('Error in compression');
plot(numSVals, dispEr);
grid on
xlabel('Number of Singular Values used');
ylabel('Error between compress and original image');
Applying this to the following image:
Gives the following result with only first 5 Singular Values,
with first 30 Singular Values,
and the first 55 Singular Values,
The change in error with increasing number of singular values can be seen in the graph below.
Here you can notice the graph is showing that using approximately 200 first singular values yields to approximately zero error.
Just to start, I assume you're aware that the SVD is really not the best tool to decorrelate the pixels in a single image. But it is good practice.
OK, so we know that B = U*S*V'. And we know S is diagonal, and sorted by magnitude. So by using only the top few values of S, you'll get an approximation of your image. Let's say C=U*S2*V', where S2 is your modified S. The sizes of U and V haven't changed, so the easiest thing to do for now is to zero the elements of S that you don't want to use, and run the reconstruction. (Easiest way to do this: S2=S; S2(N+1:end, :) = 0; S2(:, N+1:end) = 0;).
Now for the compression part. U is full, and so is V, so no matter what happens to S2, your data volume doesn't change. But look at what happens to U*S2. (Plot the image). If you kept N singular values in S2, then only the first N rows of S2 are nonzero. Compression! Except you still have to deal with V. You can't use the same trick after you've already done (U*S2), since more of U*S2 is nonzero than S2 was by itself. How can we use S2 on both sides? Well, it's diagonal, so use D=sqrt(S2), and now C=U*D*D*V'. So now U*D has only N nonzero rows, and D*V' has only N nonzero columns. Transmit only those quantities, and you can reconstruct C, which is approximately like B.
For example, here's a 512 x 512 B&W image of Lena:
We compute the SVD of Lena. Choosing the singular values above 1% of the maximum singular value, we are left with just 53 singular values. Reconstructing Lena with these singular values and the corresponding (left and right) singular vectors, we obtain a low-rank approximation of Lena:
Instead of storing 512 * 512 = 262144 values (each taking 8 bits), we can store 2 x (512 x 53) + 53 = 54325 values, which is approximately 20% of the original size. This is one example of how SVD can be used to do lossy image compression.
Here's the MATLAB code:
% open Lena image and convert from uint8 to double
Lena = double(imread('LenaBW.bmp'));
% perform SVD on Lena
[U,S,V] = svd(Lena);
% extract singular values
singvals = diag(S);
% find out where to truncate the U, S, V matrices
indices = find(singvals >= 0.01 * singvals(1));
% reduce SVD matrices
U_red = U(:,indices);
S_red = S(indices,indices);
V_red = V(:,indices);
% construct low-rank approximation of Lena
Lena_red = U_red * S_red * V_red';
% print results to command window
r = num2str(length(indices));
m = num2str(length(singvals));
disp(['Low-rank approximation used ',r,' of ',m,' singular values']);
% save reduced Lena
imwrite(uint8(Lena_red),'Reduced Lena.bmp');
taking the first n max number of eigenvalues and their corresponding eigenvectors may solve your problem.For PCA, the original data multiplied by the first ascending eigenvectors will construct your image by n x d where d represents the number of eigenvectors.

MATLAB windowed FFT for a 2D matrix data (image)

Data: Say I have a 2000 rows by 500 column matrix (image)
What I need: Compute the FFT of 64 rows by 10 column chunks of above data. In other words, I want to compute the FFT of 64X10 window that is run across the entire data matrix. The FFT result is used to compute a scalar value (say peak amplitude frequency) which is used to create a new "FFT value" image.
Now, I need the final FFT image to be the same size as the original data (2000 X 500).
What is the fastest way to accomplish this in MATLAB? I am currently using for loops which is relatively slow. Also I use interpolation to size up the final image to the original data size.
As #EitanT pointed out, you can use blockproc for batch block processing of an image J. However you should define your function handle as
fun = #(block_struct) fft2(block_struct.data);
B = blockproc(J, [64 10], fun);
For a [2000 x 500] matrix this will give you a [2000 x 500] output of complex Fourier values, evaluated at sub-sampled pixel locations with a local support (size of the input to FFT) of [64 x 10]. Now, to replace those values with a single, e.g. with the peak log-magnitude, you can further specify
fun = #(block_struct) max(max(log(abs(fft2(block_struct.data)))));
B = blockproc(J, [64 10], fun);
The output then is a [2000/64 x 500/10] output of block-patch values, which you can resize by nearest-neighbor interpolation (or something else for smoother versions) to the desired [2000 x 500] original size
C = imresize(B, [2000 500], 'nearest');
I can include a real image example if it will further help.
Update: To get overlapping blocks you can use the 'Bordersize' option of blockproc by setting the overlap [V H] such that the final windows of size [M + 2*V, N + 2*H] will still be [64, 10] in size. Example:
fun = #(block_struct) log(abs(fft2(block_struct.data)));
V = 16; H = 3; % overlap values
overlap = [V H];
M = 32; N = 4; % non-overlapping values
B1 = blockproc(J, [M N], fun, 'BorderSize', overlap); % final windows are 64 x 10
However, this will work with keeping the full Fourier response, not the single-value version with max(max()) above.
See also this post for filtering using blockproc:Dealing with “Really Big” Images: Block Processing.
If you want to apply the same function (in your case, the 2-D Fourier transform) on individual distinct blocks in a larger matrix, you can do that with the blkproc function, which is replaced in newer MATLAB releases by blockproc.
However, I infer that you wish to apply apply fft2 on overlapping blocks in a "sliding window" fashion. For this purpose you can use colfilt with the 'sliding' option. Note that the function that we're applying on each block is the fft:
block_size = [64, 10];
temp_size = 5 * block_size;
col_func = #(x)cellfun(#(y)max(max(abs(fft2(y)))), num2cell(x, 1), 'Un', 0);
B = colfilt(A, block_size, 10 * block_size, 'sliding', col_func);
How does this work? colfilt processes the matrix A by rearranging each "sliding" block into a separate column of a new temporary matrix, and then applying the col_func to this new matrix. col_func in turn restores each column into the original block and applies fft2 on it, returning the largest amplitude value for each column.
Important things to note:
Since this mentioned temporary matrix includes all possible "sliding" blocks, memory could be a limitation. Therefore, in order to use less memory in calculations, colfilt breaks up the original matrix A into sub-matrices of temp_size, and performs calculations separately on each. The resulting matrix B is still the same, of course.
Each element in the resulting matrix B is computed from the corresponding block neighborhood. The larger your image is, the more blocks you will need to process, so the computation time will increase geometrically. I believe that you'll have to wait quite a bit until MATLAB finishes processing all sliding windows on your 2000-by-500 matrix.