MATLAB: Create a predefined array of images - arrays

I need to load many small grayscale images in MATLAB. All images are of the same type/size.
How can I predefine an array and place a different image in each of its cell?
For example, an array of 100 images, inserting an image at position 50:
my_array = zeros(100);
...
my_array(50) = my_image;
...
imshow(my_array(50));
Thanks!

You can do this using a cell array, simply define it as:
my_array = cell(100,1);
my_array{50} = my_image;
imshow(my_array{50})
Each cell of a cell array can hold different size arrays and types. I did assume that your my_image variable was an array. Also notice the curly brackets, this is how you access/define the content in a cell array. Here is a small example:
a = rand(100); % 100x100 size array in cell position 1
r = rand(100,100,3); % Different size array in cell position 2
b = cell(2,1); % initialize cell
b{1} = a; % assign cell content
b{2} = r;
imshow(b{1})
The image is the results of imshow(b{1})

Related

Concatenate cell array in MATLAB

In Matlab you can concatenate arrays by saying:
a=[];
a=[a,1];
How do you do something similar with a cell array?
a={};
a={a,'asd'};
The code above keeps on nesting cells within cells. I just want to append elements to the cell array. How do I accomplish this?
If a and b are cell arrays, then you concatenate them in the same way you concatenate other arrays: using []:
>> a={1,'f'}
a =
1×2 cell array
{[1]} {'f'}
>> b={'q',5}
b =
1×2 cell array
{'q'} {[5]}
>> [a,b]
ans =
1×4 cell array
{[1]} {'f'} {'q'} {[5]}
You can also use the functional form, cat, in which you can select along which dimension you want to concatenate:
>> cat(3,a,b)
1×2×2 cell array
ans(:,:,1) =
{[1]} {'f'}
ans(:,:,2) =
{'q'} {[5]}
To append a single element, you can do a=[a,{1}], but this is not efficient (see this Q&A). Instead, do a{end+1}=1 or a(end+1)={1}.
Remember that a cell array is just an array, like any other. You use the same tools to manipulate them, including indexing, which you do with (). The () indexing returns the same type of array as the one you index into, so it returns a cell array, even if you index just a single element. Just about every value in MATLAB is an array, including 6, which is a 1x1 double array.
The {} syntax is used to create a cell array, and to extract its content: a{1} is not a cell array, it extracts the contents of the first element of the array.
{5, 8, 3} is the same as [{5}, {8}, {3}]. 5 is a double array, {5} is a cell array containing a double array.
a{5} = 0 is the same as a(5) = {0}.

How to find the maximum element value across multiple arrays?

I am trying to manually convert a BGR image to HSV. I need to find the maximum pixel value each of 3 image channels (numPy arrays) and create a new array which contains the maximum of the 3 channels.
def convertBGRtoHSV(image):
# normalize image
scaledImage = image // 256
# split image into 3 channels
B, G, R = cv2.split(scaledImage)
# find the shape of each array
heightB, widthB = B.shape
V = []
for h_i in range(0, height):
for w_i in range(0, width):
V[h_i][w_i] = max(B[h_i][w_i], G[h_i][w_i], R[h_i][w_i])
I am getting this error: IndexError: list index out of range
I know this loop is incorrect. I know to access the value of a pixel in an array you must say the location as such as x[:,:] but I am not sure how to loop over all the pixels of each image and make a new array with the max value of each array element.
If possible I would like to know how to use a numPy "Vectorized Operation" to accomplish this as well as the for loop.
There is a builtin function for element-wise maximum:
V = np.maximum(np.maximum(R, G), B)
... and you are done
Following up on my comment:
import cv2
import numpy as np
image = cv2.imread(image)
height, width, _ = image.shape
# initialize your output array 'v'
v = np.zeros((height, width))
# loop over each index in ranges dictated by the image shape
for row in range(height):
for col in range(width):
# assign the maximum value across the 3rd dimension (color channel)
# from the original image to your output array
v[row, col] = max(image[row, col, :])

How do I convert a cell array w/ different data formats to a matrix in Matlab?

So my main objective is to take a matrix of form
matrix = [a, 1; b, 2; c, 3]
and a list of identifiers in matrix[:,1]
list = [a; c]
and generate a new matrix
new_matrix = [a, 1;c, 3]
My problem is I need to import the data that would be used in 'matrix' from a tab-delimited text file. To get this data into Matlab I use the code:
matrix_open = fopen(fn_matrix, 'r');
matrix = textscan(matrix_open, '%c %d', 'Delimiter', '\t');
which outputs a cell array of two 3x1 arrays. I want to get this into one 3x2 matrix where the first column is a character, and the second column an integer (these data formats will be different in my implementation).
So far I've tried the code:
matrix_1 = cell2mat(matrix(1,1));
matrix_2 = cell2mat(matrix(1,2));
matrix = horzcat(matrix_1, matrix_2)
but this is returning a 3x2 matrix where the second column is empty.
If I just use
cell2mat(matrix)
it says it can't do it because of the different data formats.
Thanks!
This is the help of matlab for the cell2mat function:
cell2mat Convert the contents of a cell array into a single matrix.
M = cell2mat(C) converts a multidimensional cell array with contents of
the same data type into a single matrix. The contents of C must be able
to concatenate into a hyperrectangle. Moreover, for each pair of
neighboring cells, the dimensions of the cell's contents must match,
excluding the dimension in which the cells are neighbors. This constraint
must hold true for neighboring cells along all of the cell array's
dimensions.
From what I understand the contents you want to put in a matrix should be of the same type otherwise why do you want a matrix? you could simply create a new cell array.
It's not possible to have a normal matrix with characters and numbers. That's why cell2mat won't work here. But you can store different datatypes in a cell-array. Use cellstr for the strings/characters and num2cell for the integers to convert the contents of matrix. If you have other datatypes, use an appropriate function for this step. Then assign them to the columns of an empty cell-array.
Here is the code:
fn_matrix = 'data.txt';
matrix_open = fopen(fn_matrix, 'r');
matrix = textscan(matrix_open, '%c %d', 'Delimiter', '\t');
X = cell(size(matrix{1},1),2);
X(:,1) = cellstr(matrix{1});
X(:,2) = num2cell(matrix{2});
The result:
X =
'a' [1]
'b' [2]
'c' [3]
Now we can do the second part of the question. Extracting the entries where the letter matches with one of the list. Therefore you can use ismember and logical indexing like this:
list = ['a'; 'c'];
sel = ismember(X(:,1),list);
Y(:,1) = X(sel,1);
Y(:,2) = X(sel,2);
The result here:
Y =
'a' [1]
'c' [3]

MatLab find cells with specific values in two cell arrays

I want to find cells, which are at the same position in two different cell arrays and which have specific values.
The two cell arrays have the following structure:
cell array C1= cell(20,1). In each cell there is another cell cell(8129,8) holding double values in the range of [0,1].
Cell array C2= cell(20,1). In each cell there is another cell cell(8192,8) also holding double values in the range of [0,1].
I know want to find those cells, which (1) have a specific value that I determine (e.g. C1_value = 0.8 and C2_value = 0.85) and (2) are at the same position in the respective sub cell (!) array (e.g. C1{2}(736) == 0.8 and C2(19)(736) == 0.85). NOTE: The same position only refers to the subcell arrays (cell(8192,8)) not the "main" cell arrays C1(:) and C2(:)
Thanks in advance!
See if this approach works for you -
sz = cell2mat(cellfun(#size,C1(1),'uni',0))
row1 = sz(1);
col1 = sz(2);
t1 = reshape(horzcat(C1{:}),row1,col1,[])
t2 = reshape(horzcat(C2{:}),row1,col1,[])
b1 = t1==C1_value
b2 = t2==C2_value
tt1 = reshape(b1,row1*col1,[])' %//'
tt2 = reshape(b2,row1*col1,[])' %//'
tt22 = permute(tt2,[3 2 1])
tt3 = bsxfun(#and,tt1,tt22)
[C1_cellnum,subcellnum,C2_cellnum] = ind2sub(size(tt3),find(tt3)) %// outputs
Thus, with your sample data, you must have -
C1_cellnum as 2, C2_cellnum as 19 and subcellnum as 736.

How do concatenation and indexing differ for cells and arrays in MATLAB?

I am a little confused about the usage of cells and arrays in MATLAB and would like some clarification on a few points. Here are my observations:
An array can dynamically adjust its own memory to allow for a dynamic number of elements, while cells seem to not act in the same way:
a=[]; a=[a 1]; b={}; b={b 1};
Several elements can be retrieved from cells, but it doesn't seem like they can be from arrays:
a={'1' '2'}; figure; plot(...); hold on; plot(...); legend(a{1:2});
b=['1' '2']; figure; plot(...); hold on; plot(...); legend(b(1:2));
%# b(1:2) is an array, not its elements, so it is wrong with legend.
Are these correct? What are some other different usages between cells and array?
Cell arrays can be a little tricky since you can use the [], (), and {} syntaxes in various ways for creating, concatenating, and indexing them, although they each do different things. Addressing your two points:
To grow a cell array, you can use one of the following syntaxes:
b = [b {1}]; % Make a cell with 1 in it, and append it to the existing
% cell array b using []
b = {b{:} 1}; % Get the contents of the cell array as a comma-separated
% list, then regroup them into a cell array along with a
% new value 1
b{end+1} = 1; % Append a new cell to the end of b using {}
b(end+1) = {1}; % Append a new cell to the end of b using ()
When you index a cell array with (), it returns a subset of cells in a cell array. When you index a cell array with {}, it returns a comma-separated list of the cell contents. For example:
b = {1 2 3 4 5}; % A 1-by-5 cell array
c = b(2:4); % A 1-by-3 cell array, equivalent to {2 3 4}
d = [b{2:4}]; % A 1-by-3 numeric array, equivalent to [2 3 4]
For d, the {} syntax extracts the contents of cells 2, 3, and 4 as a comma-separated list, then uses [] to collect these values into a numeric array. Therefore, b{2:4} is equivalent to writing b{2}, b{3}, b{4}, or 2, 3, 4.
With respect to your call to legend, the syntax legend(a{1:2}) is equivalent to legend(a{1}, a{2}), or legend('1', '2'). Thus two arguments (two separate characters) are passed to legend. The syntax legend(b(1:2)) passes a single argument, which is a 1-by-2 string '12'.
Every cell array is an array! From this answer:
[] is an array-related operator. An array can be of any type - array of numbers, char array (string), struct array or cell array. All elements in an array must be of the same type!
Example: [1,2,3,4]
{} is a type. Imagine you want to put items of different type into an array - a number and a string. This is possible with a trick - first put each item into a container {} and then make an array with these containers - cell array.
Example: [{1},{'Hallo'}] with shorthand notation {1, 'Hallo'}

Resources