Matlab "Scale Down" a Vector with Averages - matlab

Quite hard to explain what I am looking for, I have an image represented as a m by n matrix in Matlab and I am trying to scale it down to 4x4 the same way an image would be scaled (average the nearest values)
So for example
1 2 3 4 5 6 7 8
1 2 3 4 5 6 7 8
0 2 3 4 9 9 7 8
0 2 3 4 9 9 7 8
1 2 3 4 5 6 7 8
1 2 3 4 5 6 7 8
1 2 3 4 5 6 7 7
1 2 3 4 5 6 7 7
Would become
1.5 3.5 5.5 7.5
1.0 3.5 9.0 7.5
1.5 3.5 5.5 7.5
1.5 3.5 5.5 7.0

Looks like imresize gives something slightly different from what you expected. For your input data, the following will work:
A = filter2([1 1; 1 1] / 4, X, 'same')
A = A(1:2:end, 1:2:end);
EDIT: Actually, it's probably faster to do the following:
i = 1:2:size(A,1)-1;
j = 1:2:size(A,2)-1;
B = 0.25 * (A(i,j) + A(i+1,j) + A(i,j+1) + A(i+1,j+1));

Any reason why you can't use the imresize() function? It does exactly what you want..
I =
1 2 3 4 5 6 7 8
1 2 3 4 5 6 7 8
0 2 3 4 5 6 7 8
0 2 3 4 5 6 7 8
1 2 3 4 5 6 7 8
1 2 3 4 5 6 7 8
1 2 3 4 5 6 7 8
1 2 3 4 5 6 7 8
I2 = imresize(I,[4 4])
I2 =
1.4688 3.4919 5.5117 7.4922
1.0742 3.5289 5.5117 7.4922
1.4688 3.4919 5.5117 7.4922
1.5137 3.4877 5.5117 7.4922

If you don't have the imresize.m from the Image Processing Toolbox, you can see how octave does it here (it uses convolution).

Related

How to exchange group of rows of a matrix in MATLAB?

I have a matrix A ,and vector x as following (left side)
where S0, H0,...is row number of each block. I want to exchange these blocks such that S0 and S1; H0 and H1 are near together as right side. This is my code
S0=3;
H0=2;
N0=2;
S1=4;
H1=5;
N1=4;
Cols=5;
Rows=S0+H0+N0+S1+H1+N1;
A=randi(10,[ Rows Cols]);
x=randi(10,[Rows 1]);
%% Exchange two block
temp=A(S0+H0+1:S0+H0+N0,1:end);
A(S0+H0+1:S0+H0+H1,1:end)=A(S0+H0+N0+S1+1:S0+H0+N0+S1+H1,1:end);
A(S0+H0+N0+S1+1:S0+H0+N0+S1+H1,1:end)=temp;
%% How exchange x
The above code is not work. How can I fixed it in MATLAB? Thank in advance.
One approach with mat2cell and cell2mat -
grps = [S0,H0,N0,S1,H1,N1]
new_pattern = [1 4 2 5 3 6]
celldata_roworder = mat2cell((1:size(A,1))',grps); %//'
newx = cell2mat(celldata_roworder(new_pattern)).'; %//'
newA = A(newx,:)
Sample run -
Input :
A =
6 8 9 8 7
4 8 8 3 4
3 8 2 1 10
5 2 6 8 3
5 7 4 7 7
4 5 6 8 7
6 3 4 7 4
8 1 5 5 2
5 9 2 4 1
5 2 3 9 5
2 2 1 4 2
1 7 10 9 8
3 9 7 8 4
4 6 10 9 9
7 8 2 6 8
10 2 10 7 6
10 10 8 10 2
5 6 6 5 10
3 7 5 1 3
8 1 3 9 10
grps =
3 2 2 4 5 4
new_pattern =
1 4 2 5 3 6
Output:
newx =
1 2 3 8 9 10 11 4 5 12 ...
13 14 15 16 6 7 17 18 19 20
newA =
3 3 2 5 8
4 3 3 7 7
1 5 2 8 1
4 6 4 1 4
7 1 5 8 8
4 9 10 10 8
7 10 10 4 3
7 3 1 6 9
2 9 2 6 10
1 1 7 10 3
10 10 10 4 7
9 1 8 9 5
8 7 4 5 7
9 8 7 5 3
1 10 7 6 8
8 1 10 6 1
4 6 3 3 2
7 9 3 2 9
6 9 7 4 8
6 7 6 8 10
I assume you are using a 2-dimensional matrix with Row rows and Cols columns.
You can use the colon : as a second index to address a full row, e.g. for the third row:
A(3, :)
(equal to A(3, 1:end) but little bit clearer).
So you could split your matrix into lines and re-arrange them like this (putting back together the lines to a two-dimensional matrix):
A = [ A(3:4, :); A(1:2, :); A(5:end, :) ]
This moves rows 3 and 4 at the beginning, then old lines 1 and 2 and then all the rest. Does this help you?
Hint: you can use eye for experimenting.

How can I store a matrix in a row of another matrix? MATLAB

I have a 3D matrix and I want to store each 2D component of this in the row of another 2D matrix which has many rows as the 3rd dimension of the 3D matrix.
How can I do this?
With permute & reshape -
reshape(permute(A,[3 2 1]),size(A,3),[])
Sample run -
>> A
A(:,:,1) =
7 1 7 5
3 4 8 5
9 4 2 6
A(:,:,2) =
7 7 2 4
7 6 5 6
3 2 9 3
A(:,:,3) =
7 7 5 3
3 9 2 8
5 9 2 3
>> reshape(permute(A,[3 2 1]),size(A,3),[])
ans =
7 1 7 5 3 4 8 5 9 4 2 6
7 7 2 4 7 6 5 6 3 2 9 3
7 7 5 3 3 9 2 8 5 9 2 3
If you don't mind a little indexing madness...
You can build a linear index with the appropriate shape, which applied on the original array will give the desired result:
B = A(bsxfun(#plus, (1:L*M:L*M*N).', reshape(bsxfun(#plus, (0:L:L*M-1).', 0:L-1),1,[])));
Example:
>> A = randi(10,2,3,4)-1; %// example array; size 2x3x4
>> A
A(:,:,1) =
5 3 2
9 8 9
A(:,:,2) =
8 7 4
9 8 6
A(:,:,3) =
3 4 8
0 4 4
A(:,:,4) =
2 8 8
4 6 7
Result:
>> B
B =
5 3 2 9 8 9
8 7 4 9 8 6
3 4 8 0 4 4
2 8 8 4 6 7
That is easily done with MATLABs matrix unrolling syntax:
A=ones(N,M,O);
B=zeros(O,N*M);
for ii=1:size(A,3)
aux=A(:,:,ii); % aux is NxM
B(ii,:)=aux(:); % unroll!
end
(note I called O the thing you call N in your pictures)

Architecture of specific ANN in MATLAB

Can someone check did I guess correct number of neurons in input/hidden/output layer and overall params please.
My idea of this ANN:
Input neurons : 784 (28x28)
Hidden Layers : 1
Size of hidden layer(s) : 25
Activation function : Log-sigmoid
Training method : gradient descent
Data size : 400 + 200
There are 400 bmp images used for training of it, and 200 for checking (however only 1-50 get guessed with 100% rate and others 0% rate...)
clear all;
clc
for kk=1:400
pl=ones(28,28); %³õʼ»¯28*28¶þֵͼÏñΪȫ°×
m=strcat('b',int2str(kk),'.bmp'); %Á¬½Ó×Ö·ûµÃµ½Ñù±¾ÎļþÃû
x=imread(m,'bmp'); %¶ÁÈëÑб¾ÎļþͼÏñ
pl=im2bw(x,0.5); %°ÑÑù±¾Í¼Ïñת»¯Îª¶þֵͼ
for m=0:27 %ÐγÉÉñ¾­ÍøÂçÊäÈëÏòÁ¿
p(m*28+1:(m+1)*28,kk)=pl(1:28,m+1);
end
end
%ÊÖдÌåÑù±¾¶ÔÓ¦µÄÊý×Ö£¨´Ób1.bmpµ½b400.bmp ¹²400¸ö£©£º
t=[5 0 4 1 9 2 1 3 1 4 3 6 3 6 1 7 2 8 6 9 4 0 9 1 1 2 4 3 2 7 8 8 6 9 0 5 6 0 7......
6 1 8 7 9 3 9 8 5 9 3 3 0 7 4 9 8 0 9 4 1 4 4 6 0 4 5 6 1 0 0 1 7 1 6 3 0 2 1......
1 7 8 0 2 6 7 8 3 9 0 4 6 7 4 6 8 0 7 8 3 1 5 7 1 7 1 1 6 3 0 2 9 3 1 1 0 4 9......
2 0 0 2 0 2 7 1 8 6 4 1 6 3 4 1 9 1 3 3 9 5 4 7 7 4 2 8 5 8 6 0 3 4 6 1 9 9 6......
0 3 7 2 8 2 9 4 4 6 4 9 7 0 9 2 7 5 1 5 9 1 2 3 1 3 5 9 1 7 6 2 8 2 2 6 0 7 4......
9 7 8 3 2 1 1 8 3 6 1 0 3 1 0 0 1 1 2 7 3 0 4 6 5 2 6 4 7 1 8 9 9 3 0 7 1 0 2......
0 3 5 4 6 5 8 6 3 7 5 8 0 9 1 0 3 1 2 2 3 3 6 4 7 5 0 6 2 7 9 8 5 9 2 1 1 4 4......
5 6 4 1 2 5 3 9 3 9 0 5 9 6 5 7 4 1 3 4 0 4 8 0 4 3 6 8 7 6 0 9 7 5 7 2 1 1 6......
8 9 4 1 5 2 2 9 0 3 9 6 7 2 0 3 5 4 3 6 5 8 9 5 4 7 4 2 7 3 4 8 9 1 9 2 1 7 9......
1 8 7 4 1 3 1 1 0 2 3 9 4 9 2 1 6 8 4 7 7 4 4 9 2 5 7 2 4 4 2 1 9 2 2 8 7 6 9......
8 2 3 8 1 6 5 1 1 0];
%´´½¨BPÍøÂç
pr(1:784,1)=0;
pr(1:784,2)=1;
t1=clock; %¼Æʱ¿ªÊ¼
%ÉèÖÃѵÁ·²ÎÊý
net=newff(pr,[25 1],{'logsig','purelin'},'traingdx','learngdm');
net.trainParam.epochs=5000; %ÉèÖÃѵÁ·´ÎÊý
net.trainParam.goal=0.05; %ÉèÖÃÐÔÄܺ¯Êý
net.trainParam.show=10; %ÿ10ÏÔʾ
net.trainParam.Ir=0.05; %ÉèÖÃѧϰËÙÂÊ
net=train(net,p,t); %ѵÁ·BPÍøÂç
datat=etime(clock,t1) %¼ÆËãÉè¼ÆÍøÂçµÄʱ¼äΪ66.417s
%Éú³É²âÊÔÑù±¾
pt(1:784,1)=1;
pl=ones(28,28); %³õʼ»¯28*28¶þֵͼÏñÏñËØ
for kk=401:600
pl=ones(28,28); %³õʼ»¯28*28¶þֵͼÏñΪȫ°×
m=strcat('b',int2str(kk),'.bmp'); %Á¬½Ó×Ö·ûµÃµ½Ñù±¾ÎļþÃû
x=imread(m,'bmp'); %¶ÁÈëÑб¾ÎļþͼÏñ
pl=im2bw(x,0.5); %°ÑÑù±¾Í¼Ïñת»¯Îª¶þֵͼ
for m=0:27 %ÐγÉÉñ¾­ÍøÂçÊäÈëÏòÁ¿
pt(m*28+1:(m+1)*28,kk-400)=pl(1:28,m+1);
end
end
[a,Pf,Af]=sim(net,pt); %ÍøÂç·ÂÕæ
a=round(a) %Êä³öʶ±ð½á¹û
%²âÊÔÑù±¾¶ÔÓ¦µÄÊý×Ö£¨´Ób401.bmpµ½b600.bmp ¹²200¸ö£©£º
tl=[2 6 4 5 8 3 1 5 1 9 2 7 4 4 4 8 1 5 8 9 5 6 7 9 9 3 7 0 9......
0 6 6 2 3 9 0 7 5 4 8 0 9 4 1 1 8 7 1 2 6 1 0 3 0 1 1 8 2 0 3 9 4 0 5 0 6 1 7......
7 8 1 9 2 0 5 1 2 2 7 3 5 4 4 7 1 8 3 9 6 0 3 1 1 2 0 3 5 7 6 8 2 9 5 8 5 7 4......
1 1 3 1 7 5 5 5 2 5 8 2 0 9 7 7 5 0 9 0 0 8 9 2 4 8 1 6 1 6 5 1 8 3 4 0 5 5 8......
3 4 2 3 9 2 1 1 5 2 1 3 2 8 7 3 7 2 4 6 9 7 2 4 2 8 1 1 3 8 4 0 6 5 9 3 0 9 2......
4 7 1 1 9 4 2 6 1 8 9 0 6 6 7];
k=0;
for i=1:200
if a(i)==tl(i)
k=k+1;
end
end
rate=1.00*k/200; %¼ÆËã×îºóÕýÈ·ÂÊΪ0.495
I might be wrong, since you don't specify the number of output neurons and the number of patterns per class in your dataset. However, it seems that you have created only one output neuron for your network. In this case, the network assings ALL patterns to the same class, and the classification accuracy you get is equal to the a priori probability. If, for example, the first 50 patterns of your dataset belong to the same class, and the rest to different classes, a classifier with one output will assign all patterns to the first class, so you will get the first 50 right.
If this is the case, you should create a classifier with N outputs, where N is the number of classes in your dataset. In this case, the classifier will vote for each class, and the pattern will be assigned to the class with the maximum output. If for example you have 3 classes, and the output for a specific pattern is [0.2, 0.83, 0.6], the pattern will be assigned to the second class.
Moreover, converting to image to black-and-white is probably not the best way. It would be better to convert the image to grayscale (to preserve the histogram to some extent), and use some normalization to compensate for differences in lighting.
Finally, keep in mind that neural networks essentially detect similarity between input vectors. So, if you need to classify pictures, you need to find a representation such that similar images produce similar input vectors. Feeding the values of the pixels into the classifier is not a such representation. For example, if you turn the image upside down, the input vector changes completely, even though it still shows the same object. You don't want that. You want features that depend on the object shown, and not on lighting/angle etc. However, extracting such features is a different matter altogether (for example see some examples for image preprocessing and feature extraction from the OpenCV framework, the standard image processing and computer vision tool in C++/python)
If you are interested in neural networks and not image processing, it would be better to start with some standard classification problems from the UCI repository (eg. iris flower, wisconsin breast cancer) and practice with them until you produce good results and feel comfortable with the tools you are using.

Find and Exclude one Matrix from other

I'm working on MATLAB. I have the following matrices
A = [
1 2 3 4
5 6 7 8
1 5 2 3
6 7 8 9
1 3 6 2
6 3 1 6
9 7 4 7
];
B = [
1 5 2 3
6 7 8 9
];
I want to find A-B
so that the answer should be like,
ans = [
1 2 3 4
5 6 7 8
1 3 6 2
6 3 1 6
9 7 4 7
];
Use setdiff with the 'rows' and 'stable' options:
>> C = setdiff(A,B,'rows','stable')
C =
1 2 3 4
5 6 7 8
1 3 6 2
6 3 1 6
9 7 4 7
Use ismember to find the common rows and neglect those in the final output.
Code
out = A(~ismember(A,B,'rows'),:)
Output
out =
1 2 3 4
5 6 7 8
1 3 6 2
6 3 1 6
9 7 4 7
clear;
s=0;
A = [
1 2 3 4
5 6 7 8
1 5 2 3
6 7 8 9
1 3 6 2
6 3 1 6
9 7 4 7
];
B = [
1 5 2 3
6 7 8 9
];
for i=1:size(B)
s=s+(ismember(A, B(i,:), 'rows'))
end
A_B = A(s==0,:)
#Divakar or #chappjc's answers are the way to go.
But I can't help inviting bsxfun to the party:
C = A(~any(squeeze(all(bsxfun(#eq, A.', permute(B, [2 3 1])))).'),:);
And its friend pdist2 is coming too:
C = A(all(pdist2(A, B, 'hamming').'),:);

MATLAB: Filling a matrix with each column being the same

I am trying to create a matrix that is 3 x n, with each of the columns being the same. What's the easiest way of achieving it? Concatenation?
After
n=7
x=[1;2;3]
it's either
repmat(x,[1 n])
or
x(:,ones(1,n))
(Octave can be considered as an open source/free version of MATLAB)
octave-3.0.3:2> rowvec = [1:10]
rowvec =
1 2 3 4 5 6 7 8 9 10
octave-3.0.3:3> [rowvec; rowvec; rowvec]
ans =
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
Use repmat if the number of rows is large.
octave-3.0.3:7> repmat(rowvec, 10, 1)
ans =
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
Use multiplication with a 1 x 3 matrix of ones
eg, x * [1 1 1]
Edit:
In Octave:
octave-3.0.3.exe:1> x = [1;2;3;4]
x =
1
2
3
4
octave-3.0.3.exe:5> x * [1 1 1]
ans =
1 1 1
2 2 2
3 3 3
4 4 4