How to reorientation as axial axis of raw image from brainweb - matlab

I have a raw image with the information such as
image dimensions: zspace yspace xspace
dimension name length step start
-------------- ------ ---- -----
zspace 181 1 -72
yspace 217 1 -126
xspace 181 1 -90
should be interpreted as follows:
the file scans the 3D image volume such that the 'X' coordinate changes fastest, and the 'Z' changes slowest.
the image sizes along the X-Y-Z axes are 181x217x181 voxels (pixels).
the voxel sizes along the X-Y-Z axes are 1x1x1 mm.
One (unsigned) byte is used for each voxel, and the data is scaled such that it will use the entire 0...255 range of values.
Currently, I am using below code to read that raw file. It can be read the raw image and display as right figure. However, it does not look like my expected result where image is reorientation as axial axis.
Could you help me solving it by Matlab code?
filepath=strcat('t1_icbm_normal_1mm_pn5_rf20.rawb');
fid = fopen(filepath,'r');
rima=zeros(dim(1:3));
for z=1:dim(3),
rima(:,:,z) = fread(fid,dim(1:2),'uchar');
end;
fclose(fid);
imshow(rima(:,:,91),[]); %% Show slice 91th
The reference link is http://brainweb.bic.mni.mcgill.ca/about_data_formats.html .
The input file can be downloaded from here or brainweb

The reason why is because when MATLAB reads in data, it places the data in column major order. This means that the data you read in via rows get placed in columns. Therefore, this has the appearance that your image gets rotated 90 degrees and reflected.
One easy solution would be to take your matrix and transpose each slice individually. A simple call to permute should do the trick:
rima = permute(rima, [2 1 3]);
The above code swaps the second and first dimensions over each slice of your matrix, effectively performing a transpose of each slice independently. I've also noticed that when you do this, there is a reflection across the horizontal axis. Make a call to flipdim to fix this:
rima = flipdim(permute(rima, [2 1 3]), 1);
To reproduce, I've downloaded the file and ran the code on my computer. I show the 91th slice before and after I permute and flipdim:
filepath=strcat('t1_icbm_normal_1mm_pn5_rf20.rawb');
fid = fopen(filepath,'r');
dim = [181 217 281]; %// Added for code to run
rima=zeros(dim(1:3));
for z=1:dim(3),
rima(:,:,z) = fread(fid,dim(1:2),'uchar');
end;
fclose(fid);
imshow(rima(:,:,91),[]); %% Show slice 91th
%// New - Permute dimensions and flip rows
rima = flipdim(permute(rima, [2 1 3]), 1);
figure;
imshow(rima(:,:,91),[]); %%// Show corrected slice
Here's what we get for before and after:

Related

Need to make a 4D plot (3D + Colour)

I need to make a 3D surface where colour will represent the fourth variable. I know "surf" is SIMILAR to what I need, but that did not work fine. Basically my data obtained from photododie sensor scanning along x,y,z and the forth variable is the intensity( data). The data are stored in text files in the following order.
Total files=2380
in each file there are 4 columns and 480 rows. the columns represent x,y,z,data
I was trying to plot the 3D surface but got this error " Error using
matlab.graphics.chart.primitive.Surface/set
Value must be a vector or 2D array of numeric
type". Please help
Here is the code
close all;
close all;
Axstep=2.5; % scanning with 2.5 micron step along x and y directions
Axlines=2380; %number of text files( in each file there are 4 column of equal
sized data (x,y,z,data) and 480 rows)
Path = 'C:\Users\asay0001\Google Drive\matlab\exp2_27-11-17_CONF09\all data - Copy';
Data = zeros(480,Axlines); % 480 rows in one file out of 2380
for i = 1:Axlines
DataTemp = importdata([Path '\DATA (' num2str(i) ').txt']);
Data(:,i) = DataTemp(:,4); % read column 4 which represents data to be ploted
end
[x y,z] = meshgrid([-3200:2.5:-2602.5],[325:2.5:672.5],[-800:100:800]);
surf(x,y,z,Data')

How to save image while keeping dimensions and pixels same?

I have to save the image. But when I try and keep the dimensions same, pixel values change. Is there any way to keep both intact.
C=imread('download.jpg');
C=rgb2gray(C);
%convert to DCT
[r1 c1]=size(C);
CDCT=floor(dct2(C));
dct=floor(dct2(C));
[r c]= size(dCipherText);
bye=c; %lenght of message bits
for i=r1:r1
for j=c1:-1:c1-28
.....%some operation on CDCT
end
end
imshow(idct2(CDCT),[0 255])
i=idct2(CDCT);
set(gcf,'PaperUnits','inches','PaperPosition',[0 0 c1 r1])
print -djpeg fa.jpg -r1
end
Don't use print to save the picture.
Use:
imwrite(i,'downdload_dct.jpg')
print will use the paper dimensions etc defined on your figure, rather than the image data itself. imwrite uses the data in i. You don't need imshow if you just want to re-save the image.
--
Update - sorry I see now that when you mean 'scaling', you don't mean the scaling of the picture but of the pixel values, and converting back from scalars to a colour. imshow only "scales" things on the screen, not in your actual data. So you will need to do that manually / numerically. Something like this would work, assuming i is real.
% ensure i ranges from 1 to 255
i = 1 + 254*(i-min(i(:))*(max(i(:))-min(i(:))) ;
% convert indices to RGB colour values (m x n x 3 array)
i = ind2rgb(i,jet(256));
not tested!

Matlab: trouble with taking derivative of image?

So I need to take the derivative of an image in the x-direction for this assignment, with the goal of getting some form of gradient. My thought is to use the diff(command) on each row of the image and then apply a Gaussian filter. I haven't started the second part because the first is giving me trouble. In attempting to get the x-derivative I have:
origImage = imread('TightRope.png');
for h = 1:3 %%h represents color channel
for i = size(origImage,1)
newImage(i,:,h) = diff(origImage(i,:,h)); %%take derivative of row and translate to new row
end
end
The issue is somewhere along the way I get the error 'Subscripted assignment dimension mismatch.'.
Error in Untitled2 (line 14)
newImage(i,:,h) = diff(origImage(i,:,h));
Does anyone have any ideas on why that might be happening and if my approach is correct for getting the gradient/gaussian derivative?
Why not use fspecial along with imfilter instead?
figure;
I = imread('cameraman.tif');
subplot 131; imshow(I); title('original')
h = fspecial('prewitt');
derivative = imfilter(I,h','replicate'); %'
subplot 132; imshow(derivative); title('derivative')
hsize = 5;
sigma = 1;
h = fspecial('gaussian', hsize, sigma) ;
gaussian = imfilter(derivative,h','replicate'); %'
subplot 133; imshow(gaussian); title('derivative + gaussian')
The result is the following one:
If your goal is to use diff to generate the derivative rather than to create a loop, you can just tell diff to give you the derivative in the x-direction (along dimension 2):
newImage = diff(double(origImage), 1, 2);
The 1 is for the first derivative and 2 is for the derivative along the second dimension. See diff.
As #rayryeng mentions in his answer, it's important to cast the image as double.
Given a N element vector, diff returns a N-1 length vector, so the reason why you are getting an alignment mismatch is because you are trying to assign the output of diff into an incorrect number of slots. Concretely, supposing that N is the total number of columns, you are using diff on a 1 X N vector which thus returns a 1 x (N - 1) vector and you are trying to assign this output as a single row into the output image which is expected to be 1 x N. The missing element is causing the alignment mismatch. diff works by taking pairs of elements in the vector and subtracting them to produce new elements, thus the reason why there is one element missing in the final output.
If you want to get your code working, one way is to pad each row of the image or signal vector with an additional zero (for example) as input into diff. Something like this could work. Take note that I'll be converting your image to double to allow the derivative to take on negative values:
origImage = imread('...'); %// Place path to image here and read in
origImage = im2double(origImage); %// Change - Convert to double precision
newImage = zeros(size(origImage)); %// Change - Create blank new image and populate each row per channel manually
for h = 1:3 %%h represents color channel
for ii = 1:size(origImage,1) %// Change - fixed for loop iteration
newImage(ii,:,h) = diff([0 origImage(ii,:,h)]); %// Change
end
end
Take note that your for loop was incorrect since it didn't go over every row... just the last row.
When I use the onion.png image that's part of the image processing toolbox:
...and when I run this code, I get this image using imshow(newImage,[]);:
Take note that the difference filter was applied to each channel individually and I changed the intensities per channel so that the smallest value gets mapped to 0 and the largest value gets mapped to 1. How you can interpret this image is that any areasthat have a non-black colour have some non-zero differences and hence there is some activity going on in those areas and any areas that have a dark / black colour means that there is no activity going on in those areas. Take note that we applied a horizontal filter, so if you wanted to do this vertically, you'd simply repeat the behaviour but apply this column-wise instead of row-wise as you did above.

Find the index of pixels in an image statisfies one condition

I have an image include 4 values {3,-3,1,-1} as figure
Let call the index of pixel that its values equals 1 or -1 pixel in contour. These pixels will create a contour that surrounds the yellow color (-3). Now, I want to find all index pixels in the contour and plus padding position inward and outward contour. As the red color, padding is set 1, hence, the index of these pixels include pixel in the contour {1,-1} and padding index as the red color. In that task, I want to find all pixel indices. How to implement that idea in matlab code. This is my code to find the index in the contour
%% Let define the image I
idx=find(I==1|I==-1);
padding=1;
%%Continue
Update: My expected result as the above figure in white region. Hence, the indices are such as 13,14,15,..21,24,...
UPDATE
Firstly, thank Andrew and Rayryeng for your answer. I would like to extedn my problem. As the above description, the contour is created by {1,-1}. Now, I want to ignore 1 and -1, so the image I only has {3,-3}. And I defined the contour is pixel in the edge of {3,-3} such as figure. Keep the same idea of padding and pixel index. How to find the indices of pixels in contour and near contour (call narrow band of contour)(expected result is white color)
Not too difficult you are on the right track. If you have the image processing toolbox, I recommend taking a look at morphological operators. Specifically you want to use imdilate my code has all the details you need.
%rather than using find, we create a binary mask. Its not the indicies of
%the matching elements as find gives. its is 1/true if the value matches the
%criteria, and 0/false otherwise.
mask = (im=1 | im=-1);
%create a 3x3 rectangle structuring element. We use a 3x3 because we want
%to expand the image by one pixel. basically the structring element (Strel)
%is our kernal, if you know image processing this is the same thing.
%a = [0 0 0 0;
% 0 1 1 1;
% 0 1 1 1;
% 0 1 1 1];
%our kernal is center at 2,2 (for this example) which are these elements
% 0 0 0 of a think a(1:3,1:3) now what the dialate operation
% 0 1 1 says is, if the majority of these pixels are ones... they
% 0 1 1 should probabaly all be ones so all those 0s will become ones
%the size of the kernal 3x3 ensures we are only growing our image one
%pixel, hope that makes sense
se = strel('square',3);
%now we dilate, or 'expand' our mask with our structuring element
expanded_mask = imdilate(mask,se);
%if you still want the indicies you can use find on our expanded mask
idx = find(expanded_mask==1);
EDIT: without morphological operations/image processing toolbox
This method uses lots of for loops, so it isn't the fastest, and doens't do error checking, but it will work. My dilate function says if the majority of the pixels are ones make them all ones.
function expanded_mask=DilateBinaryImage(bin_im, kernal_size)
[max_row,max_col] = size(bin_im);
%since we are opening the mask (only adding 1s), we can start off with the
%same values of the mask, and simply add extra 1's as needed
expanded_mask = bin_im;
%we don't want to go off the edge of our image with this kernal
%so we offset it a bit
kern_padding = floor(kernal_size/2);
%this ignores the edges
for (curr_row=kern_padding+1:1:max_row - kern_padding)
for (curr_col=kern_padding+1:1:max_col - kern_padding)
%we do 2 sums, one for rows, one for columns
num_ones = sum(sum(bin_im(curr_row-kern_padding:curr_row+kern_padding,curr_col-kern_padding:curr_col+kern_padding)));
%if the majority of vlaues are 1, we use floor to help with corner
%cases
if (num_ones >= floor((kernal_size*kernal_size)/2))
%make all the values one
expanded_mask(curr_row-kern_padding:curr_row+kern_padding,curr_col-kern_padding:curr_col+kern_padding) = 1;
end
end
end
end
and then called it like this
kernal_size= 3;
mask = (I==1 | I==-1);
expanded_mask = DilateBinaryImage(mask, kernal_size);
idx = find(expanded_mask==1);
my dilate function doesn't work at the edges of the binary image. it just copies them exactly.
Lets say your image is N-by-M pixles. In MATLAB arrays are stored in column order (see http://www.mathworks.com/help/matlab/math/matrix-indexing.html for more information). You can use I in column format as follows. First you contour pixels are given by
idx=find(I(:)==1|I(:)==-1);
Now, if you wish to pad downward and upward it is quite simple:
idx_up=idx - padding;
idx_up = idx_up(idx_up>0);
idx_down=idx + padding;
idx_down = idx_down(idx_down<=N*M);
Note that idx_up and idx_down will also contain contour pixels.
Similarly you can pad to the left\right:
idx_left=idx - padding*N;
idx_left = idx_left(idx_left>0);
idx_right=idx + padding*N;
idx_right = idx_right(idx_right<=N*M);
And combine the overall pixels:
PaddedContour = false(N,M);
PaddedContour(unique([idx;idx_up;idx_down;idx_left;idx_right])) = true;

How to split a binary file into different frames

So I have a quite big binary file that contains the information of about 70 video frames.
I read the binary file into MATLAB using the following
fid = fopen('data.binary');
B = fread(fid,'int64');
fclose(fid);
But then the variable B still contains a huge number of data. So I was wondering how can we split the variable B such that I can get data from one frame only one by one. Like let's say 30 FPS.
Is that even possible?
Thanks
PS: the pixel precision is uint8 and the Frame size 424X512. This is the code I am using:
fid = fopen('C:\KinectData\Depth\Depth_Raw_0.binary');
B = fread(fid,'uint8');
fclose(fid);
B = uint8(B);
Z = B(1:217088)
n = 424; % No. of columns of T
BB = reshape(Z, n,[]);
BB = uint8(BB);
imshow(BB)
But the picture isn't quite there yet.
OK, so we know a few things given your comments:
Each frame is 424 x 512
The precision of each element in your video is uint8
This is a grayscale video, so colour is not going to be considered
I'm going to assume your data is read in row major format. Bear in mind that MATLAB reads in data in column major format if you want to read in the data as a matrix, so you'll have to do a transpose operation, and ensure that you read the data into a transposed matrix first.
What I'm going to do is put each frame into a cell entry inside a cell array. The reason why I'm doing this is because we don't know how many frames are really in your sequence. You said "70 or so" frames, and since we don't know the exact number, we will dynamically populate the cell array as we go.
The code you have written will predominantly be the same, but we're going to run a while loop until what we read in from file is empty. In the while loop, we will read one frame at a time and store it into the cell array. I'll also make a counter that counts the number of frames we have to for later, and you'll see why. As such:
%// Open the file
fid = fopen('C:\KinectData\Depth\Depth_Raw_0.binary');
col = 424; %// Change if the dimensions are not proper
row = 512;
frames = {}; %// Empty cell array - Put frames in here
numFrames = 0; %// Let's record the number of frames too
while (true) %// Until we reach the end of the file:
B = fread(fin, [col row],'uint8=>uint8'); %// Read in one frame at a time
if (isempty(B)) %// If there are no more frames, get out
break;
end
frames{end+1} = B.'; %// Transpose to make row major and place in cell array
numFrames = numFrames + 1; %// Count frame
end
%// Close the file
fclose(fid);
As such, if you want to access the ith frame, you would simply do:
frm = frames{i};
As an additional bonus, you can play this as a movie in MATLAB. What we can do is preallocate a movie structure that is compatible to play the movie, then when you run the movie command, this will play the frames for you. Let's specify a frame rate of 10 fps, so that it will play slow enough to see the results. Therefore, when you're done do something like this:
%// Preallocate the movie structure array
movieFrames(numFrames) = struct('cdata',[],'colormap',[]);
for idx = 1 : numFrames
img = frames{idx};
movieFrames(idx) = im2frame(cat(3, img, img, img));
end
figure;
imshow(movieFrames(1).cdata); %// Show first frame to establish figure size
movie(movieFrames, 1, 10); %// Play the movie once at 10 FPS
Note that movies can only be played in colour, and so you would have to make your grayscale image artificially into colour. A colour frame is a 3D matrix, where each 2D slice tells you the amount of red, green or blue. For grayscale, each of these slices are the same, and so you would just replicate each grayscale frame for each slice. I used cat to make the grayscale frame into a 3D matrix. I also use im2frame to convert each image into a movie frame structure compatible to be played with movie.
Small caveat
I don't have access to your binary file, so this code is untested. Use at your own risk!