Matlab Cell array accessing data - matlab

I am trying to access the first and last number in a cell array. More specifically I need the first and last X value to see how much displacement there is. I am importing a trackmate file, which is why I've added the trackmate script below (hoping it might be of some help).
The script below is the one I use; I work on a mac
addpath('/Applications/Fiji.app/scripts')
clipZ = true;
scaleT = true;
[tracks] = importTrackMateTracks('8Tracks.xml', clipZ, scaleT);
n_tracks = numel( tracks );
tracks{:,:,:};
% tracks = IMPORTTRACKMATETRACKS(file) opens the track file 'file' and
% returns the tracks in the variable 'tracks'. 'tracks' is a cell array,
% one cell per track. Each cell is made of 4xN double array, where N is the
% number of spots in the track. The double array is organized as follow:
% [ Ti, Xi, Yi, Zi ; ...] where T is the index of the frame the spot has been
% detected in. T is always an integer. X, Y, Z are the spot spatial
% coordinates in physical units.

I think the answer is the following, and it is based upon IMPORTTRACKMATETRACKS help paragraph, even if it appears badly written (it is incongruous in dimensions for the double arrays):
tracks = importTrackMateTracks('8Tracks.xml', clipZ, scaleT);
x_displacements = zeros(length(tracks), 1);
for i = 1:length(tracks)
current_track = tracks{i};
first_x = current_track(1, 2);
last_x = current_track(end, 2);
x_displacements(i) = last_x - first_x;
end
is that what you are searching for?

Related

How to delete specific values from matrix in matlab

I have image matrix 420x700, and I want to delete a specific value in each row, changing the image dimensions. It is like deleting a column from it, but not in a straight line, to become 420x699 image. I should keep the values before the deleted value horizontally and shift all the values after it back by 1 position.
RGB = imread('image.jpg');
I1 = RGB(:,:,1);
How do I do that?
This is a good question, and I cannot think of a way to do this without a for-loop.
Let M be the nr-by-nc matrix from which you want to remove a column, and R the nr-by-1 vector with the column index of the element to be remove on each row.
The following code creates a new matrix A with the "column" removed from M, and vector B with the elements that were removed:
[nr,nc] = size(M);
A = zeros(nr,nc-1,'like',M);
B = zeros(nr,1,'like',M);
for k = 1:nr
r = R(k);
t = [ 1:r-1, r+1:nc ];
A(k,:) = M(k,t);
B(k) = M(k,r);
end
#beaker and #Cris are correct, but just to add some flavor to this, I've attempted to demonstrate an alternate method - using linear indexing, which can teach an interesting lesson on column major indexing of 2D arrays in MATLAB.
Another point to note is that this kind of process is what's followed in the seam carving algorithm, where we remove a vertical seam in this manner.
Load a test image to run this on - crop it to analyze easier.
I = imread('peppers.png');
I = I(100:100+9, 100:100+19, :);
figure, imshow(I)
Create a mask indicating which pixels are to be removed. This simulates the condition which I think you're pointing to - in this case, we choose random column indices for each row to be removed. You'd likely have this information as an input.
mask = zeros(size(I, [1:2]), 'logical');
for idx = 1:size(mask, 1)
randidx = randi(size(mask, 2));
mask(idx, randidx) = 1;
end
figure, imshow(mask)
Use the column major linear indexing trick to do the removal faster! Since we're removing a column at at time, we rotate the image 90 degrees, and translate this problem to removing one row at a time. MATLAB indexes 'vertically', and so we can then use linear indexing to simply remove the masked pixels all at once (rather than one row/column at a time), and then restore the shape using reshape, and finally rotate back to the original orientation.
It = rot90(I);
maskt = rot90(mask);
% Preallocate output
Ioutput = zeros([size(I, 1), size(I, 2) - 1, size(I, 3)], 'like', I);
for nchannel = 1:3
Icropped = It(:, :, nchannel);
% MATLAB indexes column wise - so, we can use linear indexing to make
% this computation simpler!
Icropped = Icropped(maskt(:) == 0);
Icropped = reshape(Icropped, [size(maskt, 1) - 1, size(maskt, 2)]);
% Restore the correct orientation after removing element!
Icropped = rot90(Icropped, 3);
Ioutput(:, :, nchannel) = Icropped;
end
figure, imshow(Ioutput)
I've cropped the 'peppers' image to demonstrate this, so that you can convince yourself that this is doing it right. This method should work similarly for larger images as well.

Loop function in Matlab Programming

I am trying to make a loop as below description in Matlab programming.
It likes two trees exploration.
Problem1:
I create a function with two input variables and output with four vars.
From originCoord(x,y,z) it creates two new coordinates R(x,y,z), L(x,y,z); (R means Right, L: left)
next R(x,y,z) -> new R1(x1,y1,z1) & L1(x1,y1,z1)
and L(x,y,z) -> new L2(x2,y2,z2) & R2(x2,y2,z2)
then to be continued
.....
loop will stop when one of the newCcoordinates() == targetCoordinates(xtarget, ytarget).
%from initial 3D point (x y z) using treeExploreation fuction to create two
%new3D points with coordinates (x1,y1,z1) and (x2,y2,z2)
%then from these new point, using this function two create new four 3D_Points...
%x y z are scala
rightPoint = [x1,y1,z1];
leftPoint = [x2,y2,z2];
targetPoint = [xtarget, ytarget, ztarget];
%store twop 3D points into coordExplore
coordExplore = [rightPoint,leftPoint];
temp = [];
flag = 0;
while (~flag)
for i=1:length(coordExplore)
[newrightPoint,newleftPoint]=treeExploration(coordExplore(i)); %help me at here !!!!
%this function with input (x,y,z) output two new coordinates i.e.
% newrightPoint(x3,y3,z3) and newleftPoint(x4,y4,z4)
if (newrightPoint==targetPoint) || (newleftPoint==targetPoint)
%this condition is to compare the output coordinates whether the same as
%the targetPoint
flag=1;
break;
else
temp =[newrightPoint,newleftPoint];
end
end
coordExplore = temp;
temp = [];
end
I got stuck when the output always greater than input. I cannot use all the output for the next loop.
Please help me to comment on how to make a loop for this case. Thanks.
Updated problems:
*I wish coordExplore(1) = rightPoint (x1 y1 z1)
and coordExplore(2) = leftPoint (x2 y2 z2)
BUT with index i=1, coordExplore(1) = x1; i=2 -> coordExplore(2) = y1;
I use the loop with coordExplore(i) in order to work from point-to-point within each point has its own coordinates(x y z). How can I do that?*
Problem2:
when one of the newCcoordinates() == targetCoordinates(xtarget, ytarget), how can I know which varibales in which direction from origin loop to last loop generating the result? (like which brands of the tree achieving the target).
In C++, I can use stack to save but in Matlab I do not know how can I save the variable for each loop.
Problem 1:
If I have understood what you want to achieve correctly, something like this should do the job.
reached_target = False;
coord = [x, y];
while ~reached_target
number_of_nodes = size(coord, 1)
new_coord = zeros(2*number_of_nodes)
for ii = 1:number_of_nodes
new_coord(ii*2-1, :) = doRightRunning(coord(ii, 1);
new_coord(ii*2, :) = doLeftRunning(coord(ii, 2);
end
target_ind = new_coord(:, 1) == x_target && new_coord(:, 2) == y_target;
if any(target_ind)
reached_target = True;
disp(find(target_ind));
end
end
However, the code you've shown doesn't match your explanations, so it's not clear if the next layer of the tree is 2 times or 4 times the size of the previous layer.
The code here basically calculates all the left and right runs for the current coordinates until the target is reached.
I haven't tested it yet, so look for bugs.
Problem 2:
It is not necessary to save the trail for knowing the turns it has made to reach the target. When a matching coordinate is found, its place in the list of coordinates reveal its trail. All you need to do is convert its index to binary and interpret 0 as right turn and 1 as left turn (since in the code, the right turn is placed on top, and the left turn on the bottom).
Example: Let's say we are in the 3rd layer of the tree with 8 coordinates and let's say the 6th coordinate matches the target. So starting from index 0, we have found a match at index which is 101 in binary format. It reveals that the turns to reach this coordinate are Left-Right-Left.

insert value in a matrix in a for loop

I wrote this matlab code in order to concatenate the results of the integration of all the columns of a matrix extracted form a multi matrix array.
"datimf" is a matrix composed by 100 matrices, each of 224*640, vertically concatenated.
In the first loop i select every single matrix.
In the second loop i integrate every single column of the selected matrix
obtaining a row of 640 elements.
The third loop must concatenate vertically all the lines previously calculated.
Anyway i got always a problem with the third loop. Where is the error?
singleframe = zeros(224,640);
int_frame_all = zeros(1,640);
conc = zeros(100,640);
for i=0:224:(22400-224)
for j = 1:640
for k = 1:100
singleframe(:,:) = datimf([i+1:(i+223)+1],:);
int_frame_all(:,j) = trapz(singleframe(:,j));
conc(:,k) = vertcat(int_frame_all);
end
end
end
An alternate way to do this without using any explicit loops (edited in response to rayryeng's comment below. It's also worth noting that using cellfun may not be more efficient than explicitly looping.):
nmats = 100;
nrows = 224;
ncols = 640;
datimf = rand(nmats*nrows, ncols);
% convert to an nmats x 1 cell array containing each matrix
cellOfMats = mat2cell(datimf, ones(1, nmats)*nrows, ncols);
% Apply trapz to the contents of each cell
cellOfIntegrals = cellfun(#trapz, cellOfMats, 'UniformOutput', false);
% concatenate the results
conc = cat(1, cellOfIntegrals{:});
Taking inspiration from user2305193's answer, here's an even better "loop-free" solution, based on reshaping the matrix and applying trapz along the appropriate dimension:
datReshaped = reshape(datimf, nrows, nmats, ncols);
solution = squeeze(trapz(datReshaped, 1));
% verify solutions are equivalent:
all(solution(:) == conc(:)) % ans = true
I think I understand what you want. The third loop is unnecessary as both the inner and outer loops are 100 elements long. Also the way you have it you are assigning singleframe lots more times than necessary since it does not depend on the inner loops j or k. You were also trying to add int_frame_all to conc before int_frame_all was finished being populated.
On top of that the j loop isn't required either since trapz can operate on the entire matrix at once anyway.
I think this is closer to what you intended:
datimf = rand(224*100,640);
singleframe = zeros(224,640);
int_frame_all = zeros(1,640);
conc = zeros(100,640);
for i=1:100
idx = (i-1)*224+1;
singleframe(:,:) = datimf(idx:idx+223,:);
% for j = 1:640
% int_frame_all(:,j) = trapz(singleframe(:,j));
% end
% The loop is uncessary as trapz can operate on the entire matrix at once.
int_frame_all = trapz(singleframe,1);
%I think this is what you really want...
conc(i,:) = int_frame_all;
end
It looks like you're processing frames in a video.
The most efficent approach in my experience would be to reshape datimf to be 3-dimensional. This can easily be achieved with the reshape command.
something along the line of vid=reshape(datimf,224,640,[]); should get you far in this regard, where the 3rd dimension is time. vid(:,:,1) then would display the first frame of the video.

Canonical Way to Aggregate Structures into a Vector

I feel dumb even having to ask this, it really should be dead simple, but being new to MatLab I'd like to know how a more experienced person would do it.
Simple problem; I need to find some regions in multiple images, correlate them by position, save those regions of interest, and use them later. One way to do that would be to store the regions in a vector.
%% pseudo code
regions = [];
for i = some_vector_of_images
% segment, get mask
% find regions
cc = bwconncomp(mask);
stats = regionprops(cc, 'all');
% correlate against known x/y
% save for later
regions[index++] = stats;
end
% use 'regions'
However, the array declaration is problematic. Its default type is double, so that won't work (can't assign a struct to an element). I've tried struct.empty, but the array is not resizable. I've tried a cell array, but I get a similar error (Conversion to cell from struct is not possible.)
Really, I just need a way to have some collection declared prior to the loop that will hold instances of these structures. Again, pretty noobish question and slightly embarrassed here... please take pity.
See if using struct2cell helps you with this. Give this pseudo-code a try -
regions = cell(num_of_images,1) %// This will be before the loop starts
...
regions[index++] = {struct2cell(stats)} %// Inside the loop
Please not that this a pseudo-code, so square brackets and ++ won't work.
Thus, the complete version of pseudo-code would be -
%%// --- pseudo code
%// Without this pre-allocation you would get the error -
%%// "Conversion to cell from struct is not possible"
regions = cell(numel(some_vector_of_images),1)
for i = some_vector_of_images
% segment, get mask
% find regions
cc = bwconncomp(mask);
stats = regionprops(cc, 'all');
% correlate against known x/y
% save for later
regions(i) = {struct2cell(stats)}
end
You can cast your empty array to a structure array by appending a structure. Replace regions[index++] = stats; with
regions = [regions, stats];
This line will continue to build the array within the loop. This idiom is generally frowned on in MATLAB because a new array needs to be created each loop.
Another method is to preallocate the array with a template structure, using repmat.
stats = some_operations_on(some_vector_of_images(1));
regions = repmat(stats, numel(some_vector_of_images), 1);
and within the loop, assign with
regions(i) = stats;
In this scenario, typically I just don't preallocate at all, or use a cell-cat pattern.
Not initializing
This one doesn't initialize the struct array, but works fine. Make sure i is an index of each element in this case.
for i = 1:numel(some_vector_of_images)
% mask = outcome of some_vector_of_images(i)
cc = bwconncomp(mask);
regions(i) = regionprops(cc, 'all');
end
cell-cat pattern
This one catches results in a cell array, and concatenates all elements at the end.
regions = cell(numel(some_vector_of_images), 1);
index = 1;
for i = some_vector_of_images
% mask = outcome of i
cc = bwconncomp(mask);
regions{index} = regionprops(cc, 'all');
index = index + 1;
end
regions = cat(1, regions{:});

PCA codes input, use for PalmPrint Recognition

I'm new to Matlab.
I'm trying to apply PCA function(URL listed below)into my palm print recognition program to generate the eigenpalms. My palm print grey scale images dimension are 450*400.
Before using it, I was trying to study these codes and add some codes to save the eigenvector as .mat file. Some of the %comments added by me for my self understanding.
After a few days of studying, I still unable to get the answers.
I decided to ask for helps.I have a few questions to ask regarding this PCA.m.
PCA.m
What is the input of the "options" should be? of "PCA(data,details,options)"
(is it an integer for reduced dimension? I was trying to figure out where is the "options" value passing, but still unable to get the ans. The msgbox of "h & h2", is to check the codes run until where. I was trying to use integer of 10, but the PCA.m processed dimension are 400*400.)
The "eigvector" that I save as ".mat" file is ready to perform Euclidean distance classifier with other eigenvector? (I'm thinking that eigvector is equal to eigenpalm, like in face recognition, the eigen faces. I was trying to convert the eigenvector matrix back to image, but the image after PCA process is in Black and many dots on it)
mySVD.m
In this function, there are two values that can be changed, which are MAX_MATRIX_SIZE set by 1600 and EIGVECTOR_RATIO set by 0.1%. May I know these values will affect the results? ( I was trying to play around with the values, but I cant see the different. My palm print image dimension is set by 450*400, so the Max_matrix_size should set at 180,000?)
** I hope you guys able to understand what I'm asking, please help, Thanks guys (=
Original Version : http://www.cad.zju.edu.cn/home/dengcai/Data/code/PCA.m
mySVD: http://www.cad.zju.edu.cn/home/dengcai/Data/code/mySVD.m
% Edited Version by me
function [eigvector, eigvalue] = PCA(data,details,options)
%PCA Principal Component Analysis
%
% Usage:
% [eigvector, eigvalue] = PCA(data, options)
% [eigvector, eigvalue] = PCA(data)
%
% Input:
% data - Data matrix. Each row vector of fea is a data point.
% fea = finite element analysis ?????
% options.ReducedDim - The dimensionality of the reduced subspace. If 0,
% all the dimensions will be kept.
% Default is 0.
%
% Output:
% eigvector - Each column is an embedding function, for a new
% data point (row vector) x, y = x*eigvector
% will be the embedding result of x.
% eigvalue - The sorted eigvalue of PCA eigen-problem.
%
% Examples:
% fea = rand(7,10);
% options=[]; %store an empty matrix in options
% options.ReducedDim=4;
% [eigvector,eigvalue] = PCA(fea,4);
% Y = fea*eigvector;
%
% version 3.0 --Dec/2011
% version 2.2 --Feb/2009
% version 2.1 --June/2007
% version 2.0 --May/2007
% version 1.1 --Feb/2006
% version 1.0 --April/2004
%
% Written by Deng Cai (dengcai AT gmail.com)
%
if (~exist('options','var'))
%A = exist('name','kind')
% var = Checks only for variables.
%http://www.mathworks.com/help/matlab/matlab_prog/symbol-reference.html#bsv2dx9-1
%The tilde "~" character is used in comparing arrays for unequal values,
%finding the logical NOT of an array,
%and as a placeholder for an input or output argument you want to omit from a function call.
options = [];
end
h2 = msgbox('not yet');
ReducedDim = 0;
if isfield(options,'ReducedDim')
%tf = isfield(S, 'fieldname')
h2 = msgbox('checked');
ReducedDim = options.ReducedDim;
end
[nSmp,nFea] = size(data);
if (ReducedDim > nFea) || (ReducedDim <=0)
ReducedDim = nFea;
end
if issparse(data)
data = full(data);
end
sampleMean = mean(data,1);
data = (data - repmat(sampleMean,nSmp,1));
[eigvector, eigvalue] = mySVD(data',ReducedDim);
eigvalue = full(diag(eigvalue)).^2;
if isfield(options,'PCARatio')
sumEig = sum(eigvalue);
sumEig = sumEig*options.PCARatio;
sumNow = 0;
for idx = 1:length(eigvalue)
sumNow = sumNow + eigvalue(idx);
if sumNow >= sumEig
break;
end
end
eigvector = eigvector(:,1:idx);
end
%dt get from C# program, user ID and name
evFolder = 'ev\';
userIDName = details; %get ID and Name
userIDNameWE = strcat(userIDName,'\');%get ID and Name with extension
filePath = fullfile('C:\Users\***\Desktop\Data Collection\');
userIDNameFolder = strcat(filePath,userIDNameWE); %ID and Name folder
userIDNameEVFolder = strcat(userIDNameFolder,evFolder);%EV folder in ID and Name Folder
userIDNameEVFile = strcat(userIDNameEVFolder,userIDName); % EV file with ID and Name
if ~exist(userIDNameEVFolder, 'dir')
mkdir(userIDNameEVFolder);
end
newFile = strcat(userIDNameEVFile,'_1');
searchMat = strcat(newFile,'.mat');
if exist(searchMat, 'file')
filePattern = strcat(userIDNameEVFile,'_');
D = dir([userIDNameEVFolder, '*.mat']);
Num = length(D(not([D.isdir])))
Num=Num+1;
fileName = [filePattern,num2str(Num)];
save(fileName,'eigvector');
else
newFile = strcat(userIDNameEVFile,'_1');
save(newFile,'eigvector');
end
You pass options in a structure, for instance:
options.ReducedDim = 2;
or
options.PCARatio =0.4;
The option ReducedDim selects the number of dimensions you want to use to represent the final projection of the original matrix. For instance if you pick option.ReducedDim = 2 you use only the two eigenvectors with largest eigenvalues (the two principal components) to represent your data (in effect the PCA will return the two eigenvectors with largest eigenvalues).
PCARatio instead allows you to pick the number of dimensions as the first eigenvectors with largest eigenvalues that account for fraction PCARatio of the total sum of eigenvalues.
In mySVD.m, I would not increase the default values unless you expect more than 1600 eigenvectors to be necessary to describe your dataset. I think you can safely leave the default values.