Matlab: Performing operations with 'struct' in image processing - image

I have two images - one binarized, and one original.
I use the binarized image to segment using bwconncomp and then for every blob/region, I want to sum the pixel-intensities from the original image.
I do that by:
blobMeasurements = regionprops(binarizedImage, originalImage, 'pixelvalues');
Now, I have a struct with a 'p x 1' vector for each blob/region. I need to sum these pixel intensities, such that I have one 'sum' value for each blob/region. How do I perform this operation? Is there a better way of doing this?
Thanks.

Try this:
blobIntensities = arrayfun(#(x) sum(x.pixelvalues(:)), blobMeasurements);
arrayfun runs the given function #(x) sum(x.pixelvalues(:)) on each of the pelement of the structure array blobMeasurements. Hope this helps.

Related

Importing Stack of Images

So I have the code to import a stack of images, but I am getting an error: Subscripted assignment dimension mismatch.
myPath = 'E:\folder name\'; %'
fileNames = dir(fullfile(myPath, '*.tif'));
width = 1400;
height = 1050;
nbImages = length(fileNames);
C=uint8(zeros(width, height, nbImages));
for i=1:length(fileNames)
C(:,:,i)=imread(cat(2,'E:\folder name\',fileNames(i).name));
i
end
I understand that the error is originating from the for loop, but I don't know of any other way to fill in an empty matrix with images.
Your images must not be all the same size. You can handle this by using explicit assignment for the first two dimensions. This will zero-pad any images which are smaller than the rest.
im = imread(...);
C(1:size(im, 1), 1:size(im, 2), i) = im;
Also, there is a good chance that your images have multiple color channels (the third dimension), so you'll likely want to concatenate along the fourth dimension rather than the third.
C(:,:,:,i) = imread(...)
Obviously it all depends what you want to do with the images, but in general, if you want a "stack" of images (or a "stack" of anything, really), then it sounds like you should be collecting them as a cell array instead.
Also, the correct way to create safe filenames is using the fullfile command
e.g.
C = cell(1, length(nbImages));
for i = 1 : length (fileNames)
C{i} = imread (fullfile ('E:','folder name', fileNames(i).name));
end
If you really want to concatenate to a 3D matrix from your cell array, assuming you have checked this is possible, you can do this very easily using comma-separated-list generator syntax:
My3DMatrix = cat(3, C{:});

VTK - How to read Tensors/Matrix per cell from a NIFTI Image?

I'm trying to implement a MRT-DTI real-time fibertracking visualization tool based on VTK.
Therefore we need to read the DTI tensors/matrices per cell stored in a NIFTI Image (.nii) and I really can't figure out how to do this.
It's not a problem to retrieve a single scalar value from the NIFTI file, but I don't know how to get the tensor (3x3/4x4 matrix).
We would really appreciate any help !
Since the NIFTIImageReader is supposed to read a tensor NIFTI image as a multi-component vtkImage we tried this:
vtkSmartPointer<vtkImageExtractComponents> extractTupel1 = vtkSmartPointer<vtkImageExtractComponents>::New();
extractTupel1->SetInputConnection(reader->GetOutputPort());
extractTupel1->SetComponents(0,1,2);
extractTupel1->Update();
vtkSmartPointer<vtkImageExtractComponents> extractTupel2 = vtkSmartPointer<vtkImageExtractComponents>::New();
extractTupel2->SetInputConnection(reader->GetOutputPort());
extractTupel2->SetComponents(3, 4, 5);
extractTupel2->Update();
vtkSmartPointer<vtkImageExtractComponents> extractTupel3 = vtkSmartPointer<vtkImageExtractComponents>::New();
extractTupel3->SetInputConnection(reader->GetOutputPort());
extractTupel3->SetComponents(6, 7, 8);
extractTupel3->Update();
extractTupel1->GetOutput()->GetPoint(pointId, tupel1);
extractTupel2->GetOutput()->GetPoint(pointId, tupel2);
extractTupel3->GetOutput()->GetPoint(pointId, tupel3);
But it doesn't work. Maybe the GetPoint-Method is the wrong choice?
Please help :)
Answer by David Gobbi, really much thanks to him!:
No, the GetPoint() method will not return the tensor value. It will return the coordinates of the voxel. So vtkImageExtractComponents is not necessary here, either.
A vtkImageData always stores the voxel values as its "Scalars" array, even if the voxel values are not scalar quantities.
A simple (but inefficient way) to get the scalar values is this method:
GetScalarComponentAsDouble (int x, int y, int z, int component)
For each voxel, you would call this method 9 times with component = [0..8].
A much more efficient way of getting the tensors is to get the scalar array from the data, and then look up the tensors via the pointId:
reader->Update();
vtkDataArray *tensors = reader->GetOutput()->GetPointData()->GetScalars();
double tensor[9];
tensors->GetTuple(pointId, tensor);
This is orders of magnitude more efficient than GetScalarComponentAsDouble().

how to store the image immediately after reading it in a for loop?

I tried the following program for reading multiple images(about 300 images). Now I want to store these images immediately after reading each to some location by some name as g1,g2,g3... Is it possible to do this in a loop?
Here is my attempt:
for i=1:5
m=imread(['C:\Users\shree\Desktop\1\im' num2str(i) '.jpg']);
figure,imshow(m);
end
I highly recommend that you store them in a cell array:
for k=1:5
image_path = ['C:\Users\shree\Desktop\1\im' num2str(i) '.jpg']; %// I have moved this to be on its own line as it will make debugging easier. You don't have to, but I think it's a good idea.
images_all{k} = imread(image_path);
end
By using eval to create variable names like g1, g2 etc you pollute your workspace with an unmanageable amount of variables. Plus if they are all in a cell array then it's really easy to apply the same function to each of them either in a loop or with cellfun.
For example if you want to convert them all to greyscale now:
images_grey = cellfun(#rgb2gray, images_all, 'UniformOutput', false);
You can simply save all them into one big matrix:
for i=1:5
images_all(:, :, :, i) = imread(['C:\Users\shree\Desktop\1\im' num2str(i) '.jpg'])
end
After this, all images will be stored in images_all (here assume that all images are colored images, i.e. 3 channels).
Try this -
for i=1:5
img =imread(['C:\Users\shree\Desktop\1\im' num2str(i) '.jpg']);
evalc(['g' num2str(i) '=img;']);
end
figure,imshow(g1);
figure,imshow(g2);
Another approach could be to use STRUCT and store those images as fields of a struct.
Storing as a 4D matrix is another efficient way as suggested by herohuyongtao.

Add two images in MATLAB

I am trying to overlay an activation map over a baseline vasculature image but I keep getting the same error below:
X and Y must have the same size and class or Y must be a scalar double.
I resized each to 400x400 so I thought it would work but no dice. Is there something I am missing? It is fairly straight forward for a GUI I am working on. Any help would be appreciated.
a=imread ('Vasculature.tif');
b = imresize (a, [400,400]);
c=imread ('activation.tif');
d= imresize (c, [400,400]);
e=imadd (b,d);
Could it be the bit depth or dpi?
I think one of your images is RGB (size(...,3)==3) and the other is grayscale (size(...,3)==1). Say the vasculature image a is grayscale and the activation image c is RGB. To convert a to RGB to match c, use ind2rgb, then add.
aRGB = ind2rgb(a,gray(256)); % assuming uint8
Alternatively, you could do aRGB = repmat(a,[1 1 3]);.
Or to put the activation image into grayscale:
cGray = rgb2gray(c);
Also, according to the documentation for imadd the two images must be:
nonsparse numeric arrays with the same size and class
To get the uint8 and uint16 images to match use the im2uint8 or im2uint16 functions to convert. Alternatively, just rescale and cast (e.g. b_uint8 = uint8(double(b)*255/65535);).
Note that in some versions of MATLAB there is a bug with displaying 16-bit images. The fix depends on whether the image is RGB or gray scale, and the platform (Windows vs. Linux). If you run into problems displaying 16-bit images, use imshow, which has the fix, or use the following code for integer data type images following image or imagesc:
function fixint16disp(img)
if any(strcmp(class(img),{'int16','uint16'}))
if size(img,3)==1,
colormap(gray(65535)); end
if ispc,
set(gcf,'Renderer','zbuffer'); end
end
chappjc's answers is just fine, I want to add a more general answer to the question how to solve the error message
X and Y must have the same size and class or Y must be a scalar double
General solving strategy
At which line does the error occur
Try to understand the error message
a. "... must have the same size ...":
Check the sizes of the input.
Try to understand the meaning of your code for the given (type of) input parameters. Is the error message reasonable?
What do you want to achieve?
Useful command: size A: returns the size of A
b. "... must have the same class ...":
Check the data types of the input arguments.
Which common data type is reasonable?
Convert it to the chosen data type.
Usefull command: whos A: returns all the meta information of A, i.e. size, data type, ...
Implement the solution: your favorite search engine and the matlab documentation are your best friend.
Be happy: you solved your problem and learned something new.
A simple code :
a=imread ('image1.jpg');
b=imresize (a, [400,400]);
subplot(3,1,1), imshow(b), title('image 1');
c=imread ('image2.jpg');
d= imresize (c, [400,400]);
subplot(3,1,2), imshow(d), title('image 2');
[x1, y1] = size(b) %height and wedth of 1st image
[x2, y2] = size(d) %height and wedth of 2nd image
for i = 1: x1
for j = 1: y1
im3(i, j)= b(i, j)+d(i, j);
end
end
subplot(3,1,3), imshow (im3), title('Resultant Image');

Finding area of the image

I used connected component labeling algorithm (bwconncomp) to label the different parts of a binary image (MATLAB). Now i need to calculate the area of different labels and remove the labels with smaller area. Can i use the default area finding command or is there any specific commands for that in matlab...Help..
From the documentation:
CC = bwconncomp(BW) returns the connected components CC found in BW.
The binary image BW can have any dimension. CC is a structure with
four fields...
The final field in CC is PixelIdxList, which is:
[a] 1-by-NumObjects cell array where the kth element in the cell array is
a vector containing the linear indices of the pixels in the kth object.
You can find the area of each label by looking at the length of the corresponding entry in the cell array. Something like:
areas_in_pixels = cellfun(#length, CC.PixelIdxList);
The PixelIdxList is a cell array, each member of which contains the linear indexes of the pixels present in that connected component. The line of code above finds the length of each cell in the cell array - i.e. the number of pixels in each connected component.
I've used cellfun to keep the code short and efficient. A different way of writing the same thing would be something like:
areas_in_pixels = nan(1, length(CC.PixelIdxList);
for i = 1:length(CC.PixelIdxList)
areas_in_pixels(i) = length(CC.PixelIdxList{i});
end
For each connected component, you can then find the size of that component in pixels by accessing an element in areas_in_pixels:
areas_in_pixels(34) %# area of connected component number 34
If you don't want to write lots of code like above just use built-in functions of MATLAB to detect the area. Label your components and from the properties of the component you can find out the area of that component. Suppose Bw is the binary image:
[B,L] = bwboundaries(Bw,'noholes');
stats = regionprops(L,'Area','perimeter');
for k = 1:length(B)
area(k)=stats.Area;
end
You can make this better still by avoiding the for loop with the following:
[B,L] = bwboundaries(Bw,'noholes');
stats = regionprops(L,'Area','perimeter');
area = [stats.Area];
Best,
-Will

Resources