How do you flip a NIFTI image (.nii) in MATLAB? - matlab

I know there are functions imrotate3 and imtransform for doing geometric transformations with .nii files. However, I'm not even sure how they work.
I'm trying the flip the nifti image along the x-axis. Would someone be able to give a detailed explanation of the functions?

You could very well use imrotate3 and such for this, but it could be easier to do it as follows:
Start by reading a NIfTI file, and displaying a coronal slice using the imshow function:
V = niftiread('brain.nii');
imshow(V(:, :, 14))
Here's how you flip along the x-axis (horizontal direction). If you'd like the other axis, consider flipud - for up down.
Vflip = fliplr(V);
Now display the same slice again, but for the Vflip volume. Notice that it's flipped as intended.
figure, imshow(Vflip(:, :, 14))

You can use the multi-dimensional indexing for this if you want:
>> a = reshape( 1:8, [ 2 2 2 ] )
a(:,:,1) =
1 3
2 4
a(:,:,2) =
5 7
6 8
>> b = a ( end:-1:1, :, : )
b(:,:,1) =
2 4
1 3
b(:,:,2) =
6 8
5 7
Mind you, the 1st dimension in Matlab selects the row, so flipping the 1st dimension (x?) is displayed on the screen as flipping each 2d plane upside-down.

Related

drow cumulative distribution function in matlab

I have two vectors of the same size. The first one can have any different numbers with any order, the second one is decreasing (but can have the same elements) and consists of only positive integers. For example:
a = [7 8 13 6];
b = [5 2 2 1];
I would like to plot them in the following way: on the x axis I have points from a vector and on the y axis I have the sum of elements from vector b before this points divided by the sum(b). Therefore I will have points:
(7; 0.5) - 0.5 = 5/(5+2+2+1)
(8; 0.7) - 0.7 = (5+2)/(5+2+2+1)
(13; 0.9) ...
(6; 1) ...
I assume that this explanation might not help, so I included the image
Because this looks to me as a cumulative distribution function, I tried to find luck with cdfplot but with no success.
I have another option is to draw the image by plotting each line segment separately, but I hope that there is a better way of doing this.
I find the values on the x axis a little confusing. Leaving that aside for the moment, I think this does what you want:
b = [5 2 2 1];
stairs(cumsum(b)/sum(b));
set(gca,'Ylim',[0 1])
And if you really need those values on the x axis, simply rename the ticks of that axis:
a = [7 8 13 6];
set(gca,'xtick',1:length(b),'xticklabel',a)
Also grid on will add grid to the plot

Pixels between 2 intersecting lines

I need to find pixel values that are between the intersection of 2 lines. The following image shows the points that I want namely the brown region.
These 4 co-ordinates can change and are not necessarily the corner points.
What is the fastest way to get the pixel values ? Is there any function that can give me the necessary mask.
You should calculate for each point, whether it is above the line or below. If the line is given in its equation form Ax+By+C, then it is as simple as calculating the sign of this expression, per your point (x,y). If your lines are given in any other form, you should first calculate the form above. (See here and here)
Let L1 be the set of all points below the first line, and L2 the set of all points below the second line. Then, your set is X = Xor(L1,L2)
[ ] Xor []
Equals:
Here is a Matlab code that solves you problem for the corner points, based on the solution that I've described. You can adjust the line equations in your code.
function CreateMask()
rows = 100;
cols = 200;
[X,Y] = ndgrid(1:cols,1:rows);
belowFirstLine = X*(1/cols) + Y*(-1/rows) + 0 < 0;
belowSecondLine = X*(-1/cols) + Y*(-1/rows) + 1 < 0;
figure;imshow( transpose(xor(belowSecondLine,belowFirstLine)));
end
Here is geometrical, rather than analytic solution.
First, you need to construct a mask image, initially filled with all zeroes. Then you should draw both lines using Bresenham's algorithm. There is no default implementation in Matlab, but you can pick one at Matlab Central. I assume, you have coordinates of intersections of the lines with image borders.
After that your image is divided into four areas and you need to flood-fill two of them using bwfill. And now you have the mask.
You can start with generating two matrices with x & y coordinates:
1 2 3 4 5 1 1 1 1 1
1 2 3 4 5 vs. 2 2 2 2 2 sized as the region
1 2 3 4 5 3 3 3 3 3
Then one needs 4 line equations that convert x*a + y*b < c into 4 masks:
diagonals have to be XORED and top/bottom masks ANDED
or without logical expressions: mask=mod(diag1+diag2,2)*top_mask*bot_mask;
The line width can be controlled by adding to 'c' half of the line width, assuming that a and b are normalized.

MATLAB: Four-part color logo(polygon)

My task is to write MATLAB code to produce a 4-part logo as shown in the screenshot. The top left should be black and the bottom right should be white. The other
two colours should be chosen randomly by the program.
I have taken the following approach:
clear all
clc
close all
x = [1 4 1 4 1 6.5 7 7];
y = [3 4 5.5 5 8 7 8 3];
fill(x,y,'k')
which creates the upper left black part. I wonder if that approach is good enough and if it is, what is the next step. I thought of storing those two variables in a shape object or something (I'm not familiar with Matlab) and rotate it somehow. Could you help me with that?
You don't need to rotate, just use the symmetry
clear all
clc
close all
x = [1 4 1 4 1 6.5 7 7];
y = [3 4 5.5 5 8 7 8 3]-3;
clrs=jet(10);
fill(x,y,'k')
hold on;
fill(2*max(x)-x,y,clrs(round(rand*10),:))
fill(x,-y,clrs(round(rand*10),:))
fill(2*max(x)-x,-y,'w')
The easiest way to do this all this, is to make sure that your center point (i.e. the point where the different colors meet), is positioned at [0,0]. Then a rotation of the figure (by multiple of 90°) boils down to changing the sign of either the x and/or y values of your contour.
If you need the figure to be at a point different from [0 0], just add these coordinates after you did the rotation.
So starting from your code, you can do this:
x = [1 4 1 4 1 6.5 7 7]-7;
y = [3 4 5.5 5 8 7 8 3]-3;
c = [5 6];
col = [0 0 0;
rand(2,3);
1 1 1];
fill( x+c(1), y+c(2),col(1,:)); hold on;
fill(-x+c(1), y+c(2),col(2,:));
fill( x+c(1),-y+c(2),col(3,:));
fill(-x+c(1),-y+c(2),col(4,:)); hold off;
edit: Clarification for the col and c variables.
The variable col contains the colors to be used in rgb style, where each row is a color. rand generates uniformly random numbers in the range [0,1], which is also where the values for the colors are expected to be. In the code above a 2x3 random matrix is generated, so that means 2 random colors which fits perfectly within the col matrix.
The variable c contains the center of your figure. If you look at the plot, the center will be at [5 6] (so 5 along the x axis and 6 along the y axis). You could use two variables instead, but I think that keeping both together in a variable is easier to deal with. I would personally do the same for your x and y variables, as that would allow you to use rotation matrices more easily, but that's just a matter of choice.

Generalize this matlab code for non-square matrices

I am working on some fourier transform code in matlab, and have come across the following:
xx = meshgrid(1:N);
% Center on DC
xx = xx - dcN;
% normalize dynamic range from -1 to 1
xx = xx./max(abs(xx(:)));
% form y coordinate from negative transpose of x coordinate (maintains symmetry about DC)
yy = -xx';
% compute the related radius of the x/y coordinates centered on DC
rr = sqrt(xx.^2 + yy.^2);
How can I generalize this for non-square matrices? This code is assuming my matrix is square, so dcN is the center of the square matrix (in other words, with 11x11, dcN = 6).
The math doesnt work out for that yy variable when the transpose is taken for a non-square matrix.
I have tried to figure out if I can make a meshgrid going from "top to bottom" instead of left to right - but I havent been able to figure taht out either.
Thanks
I have tried to figure out if I can
make a meshgrid going from "top to
bottom" instead of left to right - but
I havent been able to figure taht out
either.
>> N=5
N =
5
>> rot90(meshgrid(N:-1:1))
ans =
1 1 1 1 1
2 2 2 2 2
3 3 3 3 3
4 4 4 4 4
5 5 5 5 5
From your question I guess that you want to find rr, i.e. the distance of any element in the matrix from the center.
If you want this for a M-by-N array, you'd do the following
%# note that using meshgrid instead of ndgrid will swap xx and yy
[xx,yy] = ndgrid(-(M-1)/2:(M-1)/2,-(N-1)/2:(N-1)/2);
%# normalize to the max of xx,yy
nrm = max((M-1)/2,(N-1)/2);
xx = xx./nrm;
yy = yy./nrm;
rr = sqrt(xx.^2+yy.^2)

Need help in plotting lines between points

I need help in plotting lines between points.
Suppose, I start with creating 6 random points-
x = rand(6,1);
y = rand(6,1);
So my points are (x(1),y(1)), (x(2),y(2)), (x(3),y(3)), (x(4),y(4)), (x(5),y(5)), (x(6),y(6))
Now I want to draw straight lines between the points 1 & 5, 2 & 6, 3 & 4
and plot them in a single diagram. So I get 3 straight lines.
Any help would be highly appreciated.
You can do this with one call to PLOT. If you reshape your x and y data into matrices with each column containing a set of coordinates for one line, then PLOT will draw a different colored line for each column:
index = [1 2 3; 5 6 4]; %# The index to reshape x and y into 2-by-3 matrices
plot(x(index),y(index)); %# Plot the lines
Here are two ways to do this:
First way, using hold on. These lines are separate, i.e if you turn one red, the others will stay blue.
%# plot the first line
plot([x(1);x(5)],[y(1);y(5)]);
hold on %# this will prevent the previous plot from disappearing
%# plot the rest
plot([x(2);x(6)],[y(2);y(6)]);
plot([x(3);x(4)],[y(3);y(4)]);
Second way, making use of the fact that NaN does not get plotted. These lines are grouped, i.e. if you turn one red, all will be red.
%# create array for plotting
xy = NaN(8,2);
%# fill in data
xy([1 2 4 5 7 8],1) = x([1 5 2 6 3 4]);
xy([1 2 4 5 7 8],2) = y([1 5 2 6 3 4]);
%# plot
plot(xy(:,1),xy(:,2))