Resampling Matrix and restoring in one single Matrix - matlab

I am new to this forum, so please bear with me.
I have been working on this Matlab problem for a while now:
I have a digital elevation model (DEM) new_sub(x,y) in tif format. So it is a x-by-y matrix containing heights (z). I wish to resample parts of this DEM in different resolutions and restore this in another matrix. So far I have been working with for loops to change the resolution of different areas of the DEM and then wrote the results to an xyz-file:
x y z
1 1 123
1 2 233
1 3 231
2 1 235
2 2 531
2 3 452
and so forth.
Here is the code:
xmax = size(new_sub,2);
ymax = size(new_sub,1);
for k=1:200 % y
for l=1:xmax % x
fprintf(fid, '%d %d %d \n',l,xmax+1-k,new_sub(k,l));
end
end
% 1:4
for k=200/2+1:size(new_sub,1)/2
for l=1:size(new_sub,2)/2
fprintf(fid, '%d %d %d \n',l*2,ymax+2-k*2,new_sub(k*2,l*2));
end
end
This does work, but seems to be rather complicated. Moreover, it does not allow me to store the resampled areas in a single matrix within Matlab.
Is there a more efficient way of resampling certain areas of a Matrix with different resolutions, writing them into a new Matrix containg all resampled areas and then writing it to a file? I was looking into repmap, but could not think of a clever way of using it!
Your help is much appreciated!
THeo

To re-sample a matrix in Matlab:
For example matrix M:
M = [1 2 3 4 5;
6 7 8 9 10;
11 12 13 14 15;
16 17 18 19 20;
21 22 23 24 25];
If we wanted to sample on every nth pixel, it is as simple as this:
m = M(1:n:end, 1:n:end)
So for n=2
m = 1 3 5
11 13 15
21 23 25
I suggest you read up on indexing in matlab and also on using the colon operator to create vectors in matlab
Now in order to get in the "x y z" format you mentioned, first use meshgrid to generate matrices of X and Y coordinates.
[X, Y] = meshgrid(1:n:size(M,1), 1:n:size(M,2))
notice I use n to downsample X and Y. Now you just need to flatten the three matrices and combine them:
final = [X(:), Y(:), m(:)]
Finally to save as a file I suggest you type help save or help dlmwrite in the Matlab command promt and use either of those functions to save final

To me the easiest way to do looks like using imresize. You can treat your elevation map as an image I. Then you can cut sections out by indexing and rescaling as follows:
I = imread('my.tiff'); % read
section = I(1:200, :); % cut the first 200 rows and all columns
sectionResized = imresize(section, [numrows numcols]) % resample
imwrite(sectionResized, 'mynew.tiff'); % save

Related

Building adjacency matrix from faces array

I am using this code used in a toolbox for calculating adjacency matrix from a set of faces. My faces is an m*3 array for example:
23 13 12
12 22 23
13 4 12
23 14 13
22 35 23
From what I have understood, the adjacency matrix should be an nxn matrix where n is the number of vertices. For some of my mesh .ply files I get adjacency matrix which has a smaller dimension than the number of vertices. For example, n=5047 but my adjacency matrix has dimensions nxn= 4719x4719.
What could be the reason for this behavior? I get this error not on all but some mesh files only.
The code:
function A = triangulation2adjacency(face,vertex)
% triangulation2adjacency - compute the adjacency matrix
% of a given triangulation.
%
% A = triangulation2adjacency(face);
% or for getting a weighted graph
% A = triangulation2adjacency(face,vertex);
%
% Copyright (c) 2005 Gabriel Peyr
[tmp,face] = check_face_vertex([],face);
f = double(face)';
A = sparse([f(:,1); f(:,1); f(:,2); f(:,2); f(:,3); f(:,3)], ...
[f(:,2); f(:,3); f(:,1); f(:,3); f(:,1); f(:,2)], ...
1.0);
% avoid double links
A = double(A>0);
return;
nvert = max(max(face));
nface = size(face,1);
A = spalloc(nvert,nvert,3*nface);
for i=1:nface
for k=1:3
kk = mod(k,3)+1;
if nargin<2
A(face(i,k),face(i,kk)) = 1;
else
v = vertex(:,face(i,k))-vertex(:,face(i,kk));
A(face(i,k),face(i,kk)) = sqrt( sum(v.^2) ); % euclidean distance
end
end
end
% make sure that all edges are symmetric
A = max(A,A');
You can find a compact function here with name triangulation2adjacency.
That graph toolbox is very useful for 3d mesh and graph functions.
Ran into a similar problem a while a go... in a difffent context but you migth still find my experience usefull:
My Problem was the misunderstanding that n≠No.Faces. n is the number of vertices and each face can have three or more. Some Faces share vertices and thats why n≠No.Faces.
In Your example try:
B=[23 13 12;...
12 22 23;...
13 4 12;...
23 14 13;...
22 35 23];
NoVert=numel(unique(B));
NoFace=size(B,2);
In an adjacency matrix each node/vertice gets a row/colum so for B this would be a Matrix of 7x7.
Even bigger matrices result if the nodes are not numbered consecutively, for B this would result in a 35x35 Matrix, because the highest node number is 35.
a bit off topic, but try this :
G = digraph([B(:,1);B(:,2);B(:,3)],[B(:,2);B(:,3);B(:,1)]);
A = adjacency(G);
you will get the adjacency matrix with a lot less code. (and maybe time, did not test)

How to find K random different pixels in an image? [duplicate]

This question already has answers here:
Randomly Selecting Pixels in a Picture Matlab
(3 answers)
Closed 7 years ago.
I know how to find a random pixel by using rand function, for both x&y in the limits of the image. Then do it K times with a loop.
However I'd like to do it in smarter way and make sure I don't pick the same
(x, y) coordinate. Thanks in advance!
Use randperm (no toolbox required):
K = 10;
[h, w, c] = size(image);
[X, Y] = ind2sub([h w], randperm(h*w, K));
The tricky part here is avoiding repetition. If you have the Statistics Toolbox you can use randsample:
k = 10;
[m,n] = size(image(:,:,1)); %// works with 3- and 1-channel images
s = randsample(m*n, k); %// get k random indices
[X, Y] = ind2sub([m, n], s); %// convert indices to x,y coordinates
On my test run with a 512x512x3 image I got the following coordinates:
X =
464 143 174 235 437 201 348 272 212 260
Y =
499 449 508 148 107 114 341 196 60 224
randi generates integers between 1 and a specified limit, you can use that with your image size to generate pixel coordinates. To make sure you don't pick the same coordinates again maintain a matrix of logicals and mark pixels you are picking.
If you just want to pick K random pixels from the image I would suggest use something like randi(imgSize,K,2) to generate a matrix of indices. You could end up with duplicates in the matrix and to eliminate those you can use unique with the 'rows' argument.

How to do data dimensionailty reduction?

I have a set of 25 images of label 'Infected' and 25 images of label 'Normal'.
I am trying to extract the dual-tree complex wavelet transform based coefficients as features for each of the images.
My code to obtain coefficients using DT-CWT ia as follows:
I = imread('infected_img1.jpg'); %read image
I = rgb2gray(I); %rgb ro gray-scale
L = 6; %no. of levels for wavelet decomposition
I = reshape(I',1,size(I,1)*size(I,2)); %change into a vector
I = [I,zeros(1,2^L - rem(length(I),2^L))]; %pad zeros to make dim(I) a multiple of 2^L
I = double(I);
dt = dddtree('cplxdt',I,L,'dtf3'); %perform DT-CWT
dt_Coeffs = (dt.cfs{L}(:,:,1) + 1i*dt.cfs{L}(:,:,2)); %extract coefficents at Level 6
Now, since I have 24 more images to extract coefficients from, I do this block for each of the images. My ultimate aim is to append all coefficient vectors generated in each iteration to form a matrix. But each image tends to give a different sized coefficient vector.
I want to know about some dimension reduction method that can reduce each vector to a uniform size and at the same time preserve its information.
Can anyone suggest methods with a good amount of clarity?
As I mentioned in my comment,
You can't shrink something (i.e. remove information) and still preserve all of the information.
Instead you can pad all of the vectors to the length of the largest vector and then concatenate them to create a matrix. You could program your own method but in the spirit of not reinventing the wheel I've previously used padcat(). It is very easy to use and pads with NaN but you can easily change this to 0.
Here's an example usage which also contains a handy conversion from NaN to 0.
>> a = [1 2 3 4];
>> b = [1 2 3];
>> c = padcat(a, b);
c =
1 2 3 4
1 2 3 NaN
>> c(isnan(c)) = 0
c =
1 2 3 4
1 2 3 0

MATLAB Data Interpolation - Basics

I have a dataset consisting of a position and a signal - the signal is sampled at scattered positions (0, 115, 230....):
0 1.709219858
115 1.676595745
230 1.643026005
345 1.609456265
460 1.574940898
575 1.540898345
690 1.506855792
806 1.473286052
I would like to smooth this data and then interpolate it to fill in the intervening positions i.e.:
0 x
1 x
2 x
3 x
4 x
5 x
6 x
7 x
8 x
9 x
10 x
Where x is the smoothed signal. I've been smoothing data with the commands:
>> hann250=hanning(250);
>> smooth250=conv(signal,hann250,'same');
But I am not sure at all how to interpolate the data - what commands can I use and what would I type? I'm totally new to MATLAB! I am also not sure what interpolation method I need but I intend to try various one's and see (once I know how!). Thanks,
T
You could try spline interpolation:
http://www.mathworks.com/help/matlab/ref/spline.html
% read x, y from your file
xx = linspace(min(x), max(x), 1000); % generate 1000 equally spaced points
yy = spline(x,y,xx); % interpolate
plot(x,y); % original
hold all;
plot(xx,yy); % new
You can use interp1:
data = [0 1.7092
115.0000 1.6766
230.0000 1.6430
345.0000 1.6095
460.0000 1.5749
575.0000 1.5409
690.0000 1.5069
806.0000 1.4733];
index_interp = 0:806; %// indices on which to interpolate
data_interp = interp1(data(:,1),data(:,2),index_interp,'linear');
There are other interpolation methods available in addition to 'linear'; see the above link.

How to mark the peak with Matlab?

How can I use the plot function to mark the peak?
Example:
a = [0 1 3 23 3 9 10 28 2]
[p,locs] = findpeaks(a)
Result:
p =
23 28
locs =
4 8
You dont provide an x range so create one (you can change this to what you want).
figure
x = [1:length(a)];
plot(x,a,'k');
The above plots your original data points the following will
hold on
plot(locs,p,'ro');
plot your peaks as red circle points on top of the original series. If you need a non-integer x-range you will need to calculate the appropriate values that correspond to the indices in your locs array and use those x values instead.