Matlab subtract without rounding off negative number to zero - matlab

I have two arrays,
X = uint8 ([ 255 0 75; 44 225 100]);
Y = uint8 ([ 50 50 50; 50 50 50]);
When I perform X-Y, I get the result as
205 0 25
0 175 50
What I expect is
205 -50 25
-6 175 50
How to achieve this. Kindly help.

uint8 is can only contain values between 0 and 255 - it can't contain negative values. Use a signed data type (one without a u as its first letter).
Incidentally, do you have a good reason to specify the data type at all?

Related

Is graycomatrix's NumLevels and GrayLimits the same thing MATLAB

Ive been looking at implementing GLCM within MATLAB using graycomatrix. There are two arguments that I have discovered (NumLevels and GrayLimits) but in in my research and implementation they seem to achieve the same result.
GrayLimits specified bins between a range set [low high], causing a restricted set of gray levels.
NumLevels declares the number of gray levels in an image.
Could someone please explain the difference between these two arguments, as I don't understand why there would be two arguments that achieve the same result.
From the documentation:
'GrayLimits': Range used scaling input image into gray levels, specified as a two-element vector [low high]. If N is the number of gray levels (see parameter 'NumLevels') to use for scaling, the range [low high] is divided into N equal width bins and values in a bin get mapped to a single gray level.
'NumLevels': Number of gray levels, specified as an integer.
Thus the first parameter sets the input gray level range to be used (defaults to the min and max values in the image), and the second parameter sets the number of unique gray levels considered (and thus the size of the output matrix, defaults to 8, or 2 for binary images).
For example:
>> graycomatrix(img,'NumLevels',8,'GrayLimits',[0,255])
ans =
17687 1587 81 31 7 0 0 0
1498 7347 1566 399 105 8 0 0
62 1690 3891 1546 298 38 1 0
12 335 1645 4388 1320 145 4 0
2 76 305 1349 4894 959 18 0
0 16 40 135 965 7567 415 0
0 0 0 2 15 421 2410 0
0 0 0 0 0 0 0 0
>> graycomatrix(img,'NumLevels',8,'GrayLimits',[0,127])
ans =
1 9 0 0 0 0 0 0
7 17670 1431 156 50 31 23 15
1 1369 3765 970 350 142 84 92
0 128 1037 1575 750 324 169 167
0 46 361 836 1218 747 335 260
0 16 163 330 772 1154 741 547
0 10 74 150 370 787 1353 1208
0 4 67 136 294 539 1247 21199
>> graycomatrix(img,'NumLevels',4,'GrayLimits',[0,255])
ans =
28119 2077 120 0
2099 11470 1801 5
94 1829 14385 433
0 2 436 2410
As you can see, these parameters modify the output in different ways:
In the first case above, the range [0,255] was mapped to columns/rows 1-8, putting 32 different input grey values into each.
In the second case, the smaller range [0,127] was mapped to 8 indices, putting 16 different input grey values into each, and putting the remaining grey values 128-255 into the 8th index.
In the third case, the range [0,255] was mapped to 4 indices, putting 64 different input grey values into each.

Create adjacency matrix from nearest neighbour search. (convert adjacency list to adjacency matrix) - Matlab

I have a matrix 2000x5, in the first column the point number, and in columns 2-5 the 4 neighbours (0s if there isnt a neighbour). Is there an efficient way to create an adjacency matrix out of this ?
1 129 0 65 0
2 130 0 66 85
3 131 169 67 0
4 132 170 68 87
5 133 0 69 81
6 134 0 70 82
7 135 173 71 83
8 136 174 72 84
9 137 161 73 0
10 138 162 74 93
11 139 163 75 0
12 140 164 76 95
13 141 165 77 89
14 142 166 78 90
15 143 167 79 91
16 144 168 80 92
17 145 0 81 65
18 146 0 82 66
....
I found the following thread, where it is explained for just one neighbour, but I am not sure how to use it for multiple neighbours.
matlab adjacency list to adjacency matrix
I would very much appreciate any help.
A quick and simple technique:
adjMat = zeros(size(A,1));
for ind = 1:size(A,1)
% Flag 1 on each row 'ind' at the indices mentioned in col 2-5
adjMat(ind, nonzeros(A(ind,2:end))) = 1;
end
Since you have mentioned using the nearest neighbour search, it is likely that the adjacency list should be completely filled to result in a undirected graph, in the sense that if row 1 has 20 as a neighbour, row 20 very likely has 1 as a neighbour.
However technically speaking, this will produce an adjacency matrix exactly equivalent to the adjacency list, assuming nothing by itself.
Example:
For an adjacency list
A = [1 2 3; 2 0 1; 3 1 4; 4 5 3; 5 4 0]
A =
1 2 3
2 0 1
3 1 4
4 5 3
5 4 0
The result is:
adjMat =
0 1 1 0 0
1 0 0 0 0
1 0 0 1 0
0 0 1 0 1
0 0 0 1 0
P.S. To force undirected-ness, you can simply add another statement in the for loop body:
adjMat(nonzeros(A(ind,2:end)),ind) = 1;
This will ensure that the adjacency matrix will be symmetric, which is a characteristic of undirected graphs.
Firstly, I'm going to assume that the adjacency list is undirected. In any case, it's not that far of a stretch to go to multiple neighbours. What you need to do first is detect the total number of non-zero elements per row from columns 2 to 5. Once you do this, for the rows of the adjacency matrix, you would copy the point number for as many times as there are non-zero elements per that row. The function repelem is perfectly suitable to do that for you. The column indices would simply be the second to fifth columns removing all of the zero elements. How you can do this is first transpose the matrix resulting in indexing the second to fifth columns, then using a logical indexing matrix to remove out the zero entries. Doing this will unroll your vector in a column-major fashion, which is why transposing is required before doing this operation. Once you do this, you can create row and column access indices so that these can be input into sparse much like that post you linked.
Supposing that your matrix was stored in A, you would do something like this. This also assumes that each of the weights connecting the nodes are 1:
% Find total number of non-zero elements per row, skipping first column
non_zero = sum(A(:,2:end) ~= 0, 2);
% Create row indices
rows = repelem(A(:,1), non_zero);
% Create column indices
cols = A(:,2:end).';
cols = cols(cols ~= 0);
% Create adjacency matrix
adj = sparse([rows; cols],[cols; rows], 1);
The above representation is in sparse. If you want the full numeric version, cast the output using full:
adj = full(adj);
If your graph is directed
If you have a directed graph instead of an undirected graph, the above call to sparse duplicates edges so that you are creating links to and from each of the neighbours. If your graph is actually directed, then you simply have to only use the row and column indices once instead of twice as seen in the above code:
% Create adjacency matrix
adj = sparse(rows, cols , 1);
Test Case
Here's a small test case to show you that this works. Supposing my adjacency list looked like the following:
>> A = [1 0 2 3; 2 4 0 0; 3 0 0 4]
A =
1 0 2 3
2 4 0 0
3 0 0 4
The adjacency matrix is now:
>> full(adj)
ans =
0 1 1 0
1 0 0 1
1 0 0 1
0 1 1 0
Taking a look at the list above and how the matrix is populated, we can verify that this is correct.
Note about repelem
repelem assumes you have MATLAB R2015a or later. If you don't have this, you can consult this answer by user Divakar on a custom implementation of repelem here: Repeat copies of array elements: Run-length decoding in MATLAB

Calculate Variance of a Group data

I have a table contain height and frequency.I want to calculate the variance of it.
Height 140 150 160 170 180 190
Frequency 3 5 57 63 30 2
I have tried the below code:
height=[140 150 160 170 180 190;3 5 57 63 30 2]
height=height(:)
V = var(height) %Calculate Variance
**This give an answer of 5.7316e+03**
while with formula it give an answer of 81.8594. Now please tell me how can i do this?
Use weighted variance:
h=height;
var(h(1,:),h(2,:))

MATLAB: Plot raster map with custom colormap

In MATLAB, I have a matrix map_data associated with referencing object R (both in this MAT-file). I want to map it with a discrete colorbar given an irregular range of values to look something like this:
I would like to use geoshow() or something similar that allows me to reproject at will and to overlay shapefiles on top of the raster. But really anything that gets me on the right track would be much appreciated.
I'm using MATLAB r2014b. Here is the relevant information for the colormap:
R G B
0 <= map_data < 0.001 204 204 204
0.001 <= map_data < 0.005 153 153 153
0.005 <= map_data < 0.01 255 255 178
0.01 <= map_data < 0.05 254 204 92
0.05 <= map_data < 0.1 253 141 60
0.1 <= map_data < 0.25 240 59 32
0.25 <= map_data < 0.5 189 0 38
0.5 <= map_data < 1 0 0 0
Cross-posted at MATLAB answers.
MATLAB only has built-in support for linear colormaps. Therefore for nonlinear mappings like this one, you need to transform the values of map_data so that the changes in color are evenly spaced. For a discrete colormap like this one, integer indices are ideal, and you can get them easily using histc:
ranges = [0 0.001 0.005 0.01 0.05 0.1 0.25 0.5 1];
[~,ind] = histc(map_data,ranges);
Use the indices in ind in lieu of the values in map_data as your color data, and then all you need is to apply the specified colors as a colormap. Where you need to label the true map_data values on your colorbar, manually relabel the YTickLabel of the corresponding colorbar.
I don't have the mapping toolbox to demonstrate this with geoshow, but displaying as a straightforward image works as follows:
image(ind)
axis equal tight
set(gca,'YDir','normal')
colormap([204 204 204
153 153 153
255 255 178
254 204 92
253 141 60
240 59 32
189 0 38
0 0 0]/255);
h = colorbar;
h.YTickLabel = edges(h.YTick)*100;
Which results in the following:
Will had a great idea to use histc(), but I had to edit his code to make it work for me. Here's what I ended up with.
my_colormap = [204 204 204
153 153 153
255 255 178
254 204 92
253 141 60
240 59 32
189 0 38
0 0 0]/255 ;
binEdges = [0 0.001 0.005 0.01 0.05 0.1 0.25 0.5 1] ;
labels = textscan(num2str(binEdges*100),'%s') ;
labels = labels{1} ;
labels{length(labels)} = [labels{length(labels)} '%'] ;
[~,indices] = histc(map_data,binEdges);
indices(isnan(map_data)) = NaN ;
indices(isinf(map_data)) = NaN ;
figure ;
pcolor(indices-1) % Instead of image(), to display NaN values as white
shading flat
axis equal tight
colormap(gca,my_colormap); % gca as first argument prevents
% colormap from changing for all
% subsequent plots
h = colorbar;
caxis([0 length(binEdges)-1])
h.YTickLabel = labels ;

Matlab, Image compression

i am unsure about what this is asking me to do in matlab? what does it mean to encode? what format should the answer be? can anyone help me to work it out please?
Encode the 8x8 image patch and print out the results
I have got an 8X8 image
symbols=[0 20 50 99];
p=[32 8 16 8];
p = p/sum(p);
[dict, avglen] = huffmandict(symbols, p);
A = ...
[99 99 99 99 99 99 99 99 ...
20 20 20 20 20 20 20 20 ...
0 0 0 0 0 0 0 0 ...
0 0 50 50 50 50 0 0 ...
0 0 50 50 50 50 0 0 ...
0 0 50 50 50 50 0 0 ...
0 0 50 50 50 50 0 0 ...
0 0 0 0 0 0 0 0];
comp=huffmanenco(A,dict);
ratio=(8*8*8)/length(comp)
Do you understand the principle of Huffman coding?
To put it simply, it is an algorithm used to compress data (like images in your case). This means that the input of the algorithm is an image and the output is a numeric code that is smaller in size than the input: hence the compression.
The principle of Huffman coding is (roughly) to replace symbols in the original data (in your case the value of each pixel of the image) by a numeric code that is attributed according to the probability of the symbol. The most probable (i.e. the most common) symbol will be replaced by shorter codes in order to realize a compression of the data.
To solve your problem, Matlab has two functions in the Communications Toolbox: huffmandict and huffmanenco.
huffmandict: this function build a dictionary that is used to translate symbols from the original data to their numeric Huffman codewords. To build this dictionary, huffmandict needs the list of symbols used in the data and their probability of appearance which is the number of time they are used divided by the total number of symbols in your data.
huffmanenco: this function is used to translate your original data by using the dictionary built by huffmandict. Each symbol in the original data is translated to a numeric Huffman code. To measure the gain in size of this compression method, you can compute the compression ration, which is the ratio between the number of bits used to describe your original data and the number of bits of the Huffman corresponding code. In your case, infering from your computation of the compression ratio, you have an 8 by 8 image using 8 bits integer to describe each pixel, and the Huffman corresponding code uses length(comp) bits.
With all this in mind, you could read your code in this way:
% Original image
A = ...
[99 99 99 99 99 99 99 99 ...
20 20 20 20 20 20 20 20 ...
0 0 0 0 0 0 0 0 ...
0 0 50 50 50 50 0 0 ...
0 0 50 50 50 50 0 0 ...
0 0 50 50 50 50 0 0 ...
0 0 50 50 50 50 0 0 ...
0 0 0 0 0 0 0 0];
% First step: extract the symbols used in the original image
% and their probability (number of occurences / number of total symbols)
symbols=[0 20 50 99];
p=[32 8 16 8];
p=p/sum(p);
% To do this you could also use the following which automatically extracts
% the symbols and their probability
[symbols,p]=hist(A,unique(A));
p=p/sum(p);
% Second step: build the Huffman dictionary
[dict,avglen]=huffmandict(symbols,p);
% Third step: encode your original image with the dictionary you just built
comp=huffmanenco(A,dict);
% Finally you can compute the compression ratio
ratio=(8*8*8)/length(comp)