MATLAB 3D matrix, max in different directions + rotation using MIP - matlab

I have a 3D image called img, let's say it is a 291x287x801 int16 array. I am using the MIP (Maximum intensity projection) to find the image with the maximum intensity in different directions. I know that I could use max to get the MIP:
MIPimg=max(img,[],3);
imagesc(MIPimg);
However, this is not giving me the right direction. I think it is along the z-direction, but what should I do if I want to find the MIP along the y or x direction?
I did try to change that 3 which indicates dimension to 1 or 2, but MATLAB tells me
Error using image
Color data must be an m-by-n-by-3 or m-by-n matrix.
when calling imagesc(MIPimg).
I also tried MIPimg=max(img,[ ],[2 3]); but that didn't help.

Your problem is that imagesc expects either a 2D array as input, or a 3D array where the 3rd dimension has exactly 3 values (this is the way MATLAB represents an RGB image). When you do max(img,[],1), you get an 1x287x801 array back, which has 801 elements along the 3rd dimension, not 3 as MATLAB expects.
What you need to do for display is to convert this 1x287x801 array into an 287x801 array. The function squeeze does this (it removes all dimensions with size 1):
MIPimg = squeeze(max(img,[],1));

I cannot reproduce your problem:
% create random 3D-unit8-matrix (to mimic an image)
img = uint8(randi(255,10,12,3)); % 10x12x3 matrix
% maximum over all rows (direction 1) of each of the 3 10x12 matrices => returns 3 1x12 arrays
[val,idx] = max(img,[],1); % default direction
% maximum over all columns (direction 2) of each of the 3 10x12 matrices => returns 3 10x1 vectors
[val,idx] = max(img,[],2);
% maximum over all slices (direction 3) of each of the 10x12 1x3 "depth" arrays => returns a 10x12 matrix
[val,idx] = max(img,[],3);
overall maximum
max(max(max(img))) % no useful information about the position
position of maximum:
[val_slc,idx_slc] = max(img,[],3); % I can better think in 2D
[val_row,idx_row] = max(val_slc);
[val_col,idx_col] = max(val_row);
idx_max = [idx_row(idx_col),idx_col,idx_slc(idx_row(idx_col),idx_col)];
check
assert( max(max(max(img))) == img(idx_max(1),idx_max(2),idx_max(3)) )

Related

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.

Color scatter plot in Matlab according to 0 or 1 value

I populate a grid data=zeros(n,n); with 0's and 1's (could also be thought of as an adjacency grid, if you'd like). I just want to plot the grid with colors according to whether the value at that point is 0 or 1. For example,
scatter(1:n,1:n,data);
It gives me the error:
Error using scatter (line 77)
C must be a single color, a vector the same length as X, or an M-by-3 matrix.
Any suggestions?
you are telling matlab to plot only n points ((1,1), (2,2), ..., (n,n)) where you want actually the cartesian product (1:nX1:n).
Try
[X,Y] = meshgrid(1:n,1:n);
scatter(X(:), Y(:), 10, data(:));
scatter allows you to plot points with different options (color, size, etc) for each point depending on a 'Z' value, but it creates a lot of graphic objects (one for each point).
In your case, you only have 2 subsets of data (among all your points). The points with value 1 and with value 0. So another option is to extract these 2 subsets then plot each subset with each a set of common properties.
%% // prepare test data
n = 10 ;
data=randi([0 1],n); %// create a 10x10 matrix filled with `0` and `1`
%% // extract the 2 subsets
[x0 , y0] = find( data == 0 ) ;
[x1 , y1] = find( data == 1 ) ;
%% // display
figure ; axes('Nextplot','add')
plotOptions = {'LineStyle','none','MarkerEdgeColor','k','MarkerSize',10} ; %// common options for both plots
plot(x0,y0,'o','MarkerFaceColor','r', plotOptions{:} ) %// circle marker, red fill
plot(x1,y1,'d','MarkerFaceColor','g', plotOptions{:} ) %// diamond marker, green fill
This way you have full control on each subset property (you can control the size, color, shape etc...). And you only have 2 graphic objects to handle (instead of n^2).

Matlab bar3 plot

I have a problem with MATLAB bar3 plots: Here is what I have:
m x n Array Values containing values of a measurement.
Another m x n Array Angles Represents the angle at which a value was measured (e.g. the 3rd value was measured at an angle of 90°). The angular values for each measurement value are stored in another variable.
I need a range for my x-axis from -180° to +180°. This alone is no problem. But how do I hand over my measurement values? I have to somehow link them to the angular values. So that each value in Values is somehow linked to it's angular value in Angles. For my y-axis, I can simply count from 0 to the amount of rows of my Values Array.
EXAMPLE:
Valueslooks like:
3 5 6
2 1 7
5 8 2
Angles looks like:
37° 38° 39°
36° 37° 38°
34° 35° 36°
Values(1,1) = 3 was measured at Angles(1,1) = 37° for example.
At each angle, the number of bars varies depending on how many measurements exist for that angle. bar3 needs a matrix input. In order to build a matrix, missing values are filled with NaN.
Warning: NaNs are usually ignored by plotting commands, but bar3 apparently breaks this convention. It seems to replace NaNs by zeros! So at missing values you'll get a zero-height bar (instead of no bar at all).
[uAngles, ~, uAngleLabels] = unique(Angles); %// get unique values and
%// corresponding labels
valuesPerAngle = accumarray(uAngleLabels(:), Values(:), [], #(v) {v});
%// cell array where each cell contains all values corresponding to an angle
N = max(cellfun(#numel, valuesPerAngle));
valuesPerAngle = cellfun(#(c) {[c; NaN(N-numel(c),1)]}, valuesPerAngle);
%// fill with NaNs to make all cells of equal lenght, so that they can be
%// concatenated into a matrix
valuesPerAngle = cat(2, valuesPerAngle{:}); %// matrix of values for each angle,
%// filled with NaNs where needed
bar3(uAngles, valuesPerAngle.'); %'// finally, the matrix can be plotted
ylabel('Angles')
xlabel('Measurement')
With your example Values and Angles this gives:

Matlab - Trying to use vectors with grid coordinates and value at each point for a color plot

I'm trying to make a color plot in matlab using output data from another program. What I have are 3 vectors indicating the x-position, y-yposition (both in milliarcseconds, since this represents an image of the surroundings of a black hole), and value (which will be assigned a color) of every point in the desired image. I apparently can't use pcolor, because the values which indicate the color of each "pixel" are not in a matrix, and I don't know a way other than meshgrid to create a matrix out of the vectors, which didn't work due to the size of the vectors.
Thanks in advance for any help, I may not be able to reply immediately.
If we make no assumptions about the arrangement of the x,y coordinates (i.e. non-monotonic) and the sparsity of the data samples, the best way to get a nice image out of your vectors is to use TriScatteredInterp. Here is an example:
% samplesToGrid.m
function [vi,xi,yi] = samplesToGrid(x,y,v)
F = TriScatteredInterp(x,y,v);
[yi,xi] = ndgrid(min(y(:)):max(y(:)), min(x(:)):max(x(:)));
vi = F(xi,yi);
Here's an example of taking 500 "pixel" samples on a 100x100 grid and building a full image:
% exampleSparsePeakSamples.m
x = randi(100,[500 1]); y = randi(100,[500 1]);
v = exp(-(x-50).^2/50) .* exp(-(y-50).^2/50) + 1e-2*randn(size(x));
vi = samplesToGrid(x,y,v);
imagesc(vi); axis image
Gordon's answer will work if the coordinates are integer-valued, but the image will be spare.
You can assign your values to a matrix based on the x and y coordinates and then use imagesc (or a similar function).
% Assuming the X and Y coords start at 1
max_x = max(Xcoords);
max_y = max(Ycoords);
data = nan(max_y, max_x); % Note the order of y and x
indexes = sub2ind(size(data), max_y, max_x);
data(indexes) = Values;
imagesc(data); % note that NaN values will be colored with the minimum colormap value

extracting matrix values from another matrix

I have a problem like that;
points (size = 65,2) is a variable that has pixel coordinates of an image. In the first column, there are x coordinates, and in the second y coordinates and I want to take the magnitude values of a matrix (size = 256,256,6) from those pixel coordinates of only one channel eg. 3 (three).
I couldn't succeed that.
intensities = images(points(:,2), points(:,1), 3);
makes a matrix 65x65.
Thanks
Jimenez
You can convert your x,y indices to linear indices to get values you want from your image:
% some sample data
list = round(256*rand(65,2));
im = rand(256,256);
% calculate linear indices
ind = sub2ind([256,256],list(:,1),list(:,2));
intensities = im(ind);
This results in an intensities matrix that is 65x1 where each element corresponds to the x,y pair from your list.