Convolutional neural network - How to get the feature maps? - artificial-intelligence

I read a few books and articles about Convolutional neural network, it seems I understand the concept but I don't know how to put it up like in image below:
(source: what-when-how.com)
from 28x28 normalized pixel INPUT we get 4 feature maps of size 24x24. but how to get them ? resizing the INPUT image ? or performing image transformations? but what kind of transformations? or cutting the input image into 4 pieces of size 24x24 by 4 corner? I don't understand the process, to me it seem they cut up or resize the image to smaller images at each step. please help thanks.

This is matlab help file for CONV2 function, which use in CNN Matlab (to get convolutional layers). Read it carefully and you will see your answer.
%CONV2 Two dimensional convolution.
% C = CONV2(A, B) performs the 2-D convolution of matrices A and B.
% If [ma,na] = size(A), [mb,nb] = size(B), and [mc,nc] = size(C), then
% mc = max([ma+mb-1,ma,mb]) and nc = max([na+nb-1,na,nb]).
%
% C = CONV2(H1, H2, A) convolves A first with the vector H1 along the
% rows and then with the vector H2 along the columns. If n1 = length(H1)
% and n2 = length(H2), then mc = max([ma+n1-1,ma,n1]) and
% nc = max([na+n2-1,na,n2]).
%
% C = CONV2(..., SHAPE) returns a subsection of the 2-D
% convolution with size specified by SHAPE:
% 'full' - (default) returns the full 2-D convolution,
% 'same' - returns the central part of the convolution
% that is the same size as A.
% 'valid' - returns only those parts of the convolution
% that are computed without the zero-padded edges.
% **size(C) = max([ma-max(0,mb-1),na-max(0,nb-1)],0).**

Related

Take numbers form two intervals in concentric spheres in Julia

I am trying to take numbers from two intervals in Julia. The problem is the following,
I am trying to create concentric spheres and I need to generate vectors of dimension equal to 15 filled with numbers taken from each circle. The code is:
rmax = 5
ra = fill(0.0,1,rmax)
for i=1:rmax-1
ra[:,i].=rad/i
ra[:,rmax].= 0
end
for i=1:3
ptset = Any[]
for j=1:200
yt= 0
yt= rand(Truncated(Normal(0, 1), -ra[i], ra[i] ))
if -ra[(i+1)] < yt <= -ra[i] || ra[(i+1)] <= yt < ra[i]
push!(ptset,yt)
if length(ptset) == 15
break
end
end
end
end
Here, I am trying to generate spheres with uniform random numbers inside of each one; In this case, yt is only part of the construction of the numbers inside the sphere.
I would like to generate points in a sphere with radius r0 (ra[:,4] for this case), then points distributed from the edge of the first sphere to the second one wit radius r1 (here ra[:,3]) and so on.
In order to do that, I try to take elements that fulfill one of the two conditions -ra[(i+1)] < yt <= -ra[i]
or ra[(i+1)] <= yt < ra[i], i.e. I would like to generate a vector with positive and negative numbers. I used the operator || but it seems to take only the positive part. I am new in Julia and I am not sure how to take the elements from both parts of the interval. Does anyone has a hit on how to do it?. Thanks in advance
I hope I understood you correctly. First, we need to be able to sample uniformly from an N-dimensional shell with radii r0 and r1:
using Random
using LinearAlgebra: normalize
struct Shell{N}
r0::Float64
r1::Float64
end
Base.eltype(::Type{<:Shell}) = Vector{Float64}
function Random.rand(rng::Random.AbstractRNG, d::Random.SamplerTrivial{Shell{N}}) where {N}
shell = d[]
Δ = shell.r1 - shell.r0
θ = normalize(randn(N)) # uniformly distributed N-dimensional direction of length 1
r = shell.r0 .* θ # scale to a point on the interior of the shell
return r .+ Δ .* θ .* .√rand(N) # add a uniformly random segment between r0 and r1
end
(See here for more info about hooking into Random. You could equally implement a new Distribution, but that's not really necessary.)
Most importantly, a truncated normal will not result in a uniform distribution, but neither will adding a uniform scaling into the right direction: see here for why the square root is necessary (and I hope I got it right; you should check the math once more).
Then we can just create a sequence of shell samples with nested radii:
rmax = 5
rad = 10.0
ra = range(0, rad, length=rmax)
ptset = [rand(Shell{2}(ra[i], ra[i+1]), 15) for i = 1:(rmax - 1)]
(This part I wasn't really sure about, but the point should be clear.)

scatter plot: tall arrays eating up all the memory

I am working on tone mapping operators in HDR. My question is very simple. I want to scatter plot large arrays on Matlab 2015Ra with computer specs core i5 20GB RAM. Only the scatter plot eats up the whole memory (around 92% of 20GB). I need some suggestion to plot tall arrays. I know Matlab 2018 has binscatter function but I have lower version. Thank you. Sample Code:
a=randn(21026304,1);
scatter(a,a);
Only this code eats up the all memory.
You can create a binscatter like function yourself with histcounts2!
Histcounts bins the data into an NxN array which you can then visualize with imshow... this is pretty memory-efficient as every bin only takes up a couple of bytes, regardless of the input size.
% Some (correlated) data
x = randn(1e6,1);
y = randn(1e6,1)+x;
% Count 32x32 bins
[N,ax,ay] = histcounts2(x,y,32);
% Some gradient
cmap = [linspace(1,0,16);
linspace(1,0.3,16);
linspace(1,0.5,16)].';
% Show the histogram
imshow(...
N,[],... % N contains the counts, [] indicated range min-max
'XData', ax, 'YData', ay, ... % Axis ticks
'InitialMagnification', 800,... % Enlarge 8x
'ColorMap', cmap... % The colormap
);
colorbar;
axis on;
title('bin-counts');

Trying to scale image size from 18x5 to 24x14 in MATLAB [duplicate]

I am trying to write my own function for scaling up an input image by using the Nearest-neighbor interpolation algorithm. The bad part is I am able to see how it works but cannot find the algorithm itself. I will be grateful for any help.
Here's what I tried for scaling up the input image by a factor of 2:
function output = nearest(input)
[x,y]=size(input);
output = repmat(uint8(0),x*2,y*2);
[newwidth,newheight]=size(output);
for i=1:y
for j=1:x
xloc = round ((j * (newwidth+1)) / (x+1));
yloc = round ((i * (newheight+1)) / (y+1));
output(xloc,yloc) = input(j,i);
end
end
Here is the output after Mark's suggestion
This answer is more explanatory than trying to be concise and efficient. I think gnovice's solution is best in that regard. In case you are trying to understand how it works, keep reading...
Now the problem with your code is that you are mapping locations from the input image to the output image, which is why you are getting the spotty output. Consider an example where input image is all white and output initialized to black, we get the following:
What you should be doing is the opposite (from output to input). To illustrate, consider the following notation:
1 c 1 scaleC*c
+-----------+ 1 +----------------------+ 1
| | | | | |
|----o | <=== | | |
| (ii,jj) | |--------o |
+-----------+ r | (i,j) |
inputImage | |
| |
+----------------------+ scaleR*r
ouputImage
Note: I am using matrix notation (row/col), so:
i ranges on [1,scaleR*r] , and j on [1,scaleC*c]
and ii on [1,r], jj on [1,c]
The idea is that for each location (i,j) in the output image, we want to map it to the "nearest" location in the input image coordinates. Since this is a simple mapping we use the formula that maps a given x to y (given all the other params):
x-minX y-minY
--------- = ---------
maxX-minX maxY-minY
in our case, x is the i/j coordinate and y is the ii/jj coordinate. Therefore substituting for each gives us:
jj = (j-1)*(c-1)/(scaleC*c-1) + 1
ii = (i-1)*(r-1)/(scaleR*r-1) + 1
Putting pieces together, we get the following code:
% read a sample image
inputI = imread('coins.png');
[r,c] = size(inputI);
scale = [2 2]; % you could scale each dimension differently
outputI = zeros(scale(1)*r,scale(2)*c, class(inputI));
for i=1:scale(1)*r
for j=1:scale(2)*c
% map from output image location to input image location
ii = round( (i-1)*(r-1)/(scale(1)*r-1)+1 );
jj = round( (j-1)*(c-1)/(scale(2)*c-1)+1 );
% assign value
outputI(i,j) = inputI(ii,jj);
end
end
figure(1), imshow(inputI)
figure(2), imshow(outputI)
A while back I went through the code of the imresize function in the MATLAB Image Processing Toolbox to create a simplified version for just nearest neighbor interpolation of images. Here's how it would be applied to your problem:
%# Initializations:
scale = [2 2]; %# The resolution scale factors: [rows columns]
oldSize = size(inputImage); %# Get the size of your image
newSize = max(floor(scale.*oldSize(1:2)),1); %# Compute the new image size
%# Compute an upsampled set of indices:
rowIndex = min(round(((1:newSize(1))-0.5)./scale(1)+0.5),oldSize(1));
colIndex = min(round(((1:newSize(2))-0.5)./scale(2)+0.5),oldSize(2));
%# Index old image to get new image:
outputImage = inputImage(rowIndex,colIndex,:);
Another option would be to use the built-in interp2 function, although you mentioned not wanting to use built-in functions in one of your comments.
EDIT: EXPLANATION
In case anyone is interested, I thought I'd explain how the solution above works...
newSize = max(floor(scale.*oldSize(1:2)),1);
First, to get the new row and column sizes the old row and column sizes are multiplied by the scale factor. This result is rounded down to the nearest integer with floor. If the scale factor is less than 1 you could end up with a weird case of one of the size values being 0, which is why the call to max is there to replace anything less than 1 with 1.
rowIndex = min(round(((1:newSize(1))-0.5)./scale(1)+0.5),oldSize(1));
colIndex = min(round(((1:newSize(2))-0.5)./scale(2)+0.5),oldSize(2));
Next, a new set of indices is computed for both the rows and columns. First, a set of indices for the upsampled image is computed: 1:newSize(...). Each image pixel is considered as having a given width, such that pixel 1 spans from 0 to 1, pixel 2 spans from 1 to 2, etc.. The "coordinate" of the pixel is thus treated as the center, which is why 0.5 is subtracted from the indices. These coordinates are then divided by the scale factor to give a set of pixel-center coordinates for the original image, which then have 0.5 added to them and are rounded off to get a set of integer indices for the original image. The call to min ensures that none of these indices are larger than the original image size oldSize(...).
outputImage = inputImage(rowIndex,colIndex,:);
Finally, the new upsampled image is created by simply indexing into the original image.
MATLAB has already done it for you. Use imresize:
output = imresize(input,size(input)*2,'nearest');
or if you want to scale both x & y equally,
output = imresize(input,2,'nearest');
You just need a more generalized formula for calculating xloc and yloc.
xloc = (j * (newwidth+1)) / (x+1);
yloc = (i * (newheight+1)) / (y+1);
This assumes your variables have enough range for the multiplication results.

MATLAB: vectorize filling of 3D-array

I would like to safe a certain amount of grayscale-images (->2D-arrays) as layers in a 3D-array.
Because it should be very fast for a realtime-application I would like to vectorize the following code, where m is the number of shifts:
for i=1:m
array(:,:,i)=imabsdiff(circshift(img1,[0 i-1]), img2);
end
nispio showed me a very advanced version, which you can see here:
I = speye(size(img1,2)); E = -1*I;
ii = toeplitz(1:m,[1,size(img1,2):-1:2]);
D = vertcat(repmat(I,1,m),E(:,ii));
data_c = shape(abs([double(img1),double(img2)]*D),size(data_r,1),size(data_r,2),m);
At the moment the results of both operations are not the same, maybe it shifts the image into the wrong direction. My knowledge is very limited, so I dont understand the code completely.
You could do this:
M = 16; N = 20; img1 = randi(255,M,N); % Create a random M x N image
ii = toeplitz(1:N,circshift(fliplr(1:N)',1)); % Create an indexing variable
% Create layers that are shifted copies of the image
array = reshape(img1(:,ii),M,N,N);
As long as your image dimensions don't change, you only ever need to create the ii variable once. After that, you can call the last line each time your image changes. I don't know for sure that this will give you a speed advantage over a for loop, but it is vectorized like you requested. :)
UPDATE
In light of the new information shared about the problem, this solution should give you an order of magnitudes increase in speed:
clear all;
% Set image sizes
M = 360; N = 500;
% Number of column shifts to test
ncols = 200;
% Create comparison matrix (see NOTE)
I = speye(N); E = -1*I;
ii = toeplitz([1:N],[1,N:-1:(N-ncols+2)]);
D = vertcat(repmat(I,1,ncols),E(:,ii));
% Generate some test images
img1 = randi(255,M,N);
img2 = randi(255,M,N);
% Compare images (vectorized)
data_c = reshape(abs([img2,img1]*D),M,N,ncols);
% Compare images (for loop)
array = zeros(M,N,ncols); % <-- Pre-allocate this array!
for i=1:ncols
array(:,:,i)=imabsdiff(circshift(img1,[0 i-1]),img2);
end
This uses matrix multiplication to do the comparisons instead of generating a whole bunch of shifted copies of the image.
NOTE: The matrix D should only be generated one time if your image size is not changing. Notice that the D matrix is completely independent of the images, so it would be wasteful to regenerate it every time. However, if the image size does change, you will need to update D.
Edit: I have updated the code to more closely match what you seem to be looking for. Then I throw the "original" for-loop implementation in to show that they give the same result. One thing worth noting about the vectorized version is that it has the potential to be very memory instensive. If ncols = N then the D matrix has N^3 elements. Even though D is sparse, things fall apart fast when you multiply D by the non-sparse images.
Also, notice that I pre-allocate array before the for loop. This is always good practice in Matlab, where practical, and it will almost invariably give you a large performance boost over the dynamic sizing.
If question is understood correctly, I think you need for loop
for v=1:1:20
array(:,:,v)=circshift(image,[0 v]);
end

Print images stored in cell array in matlab

Background:
I am programming SIFT in matlab. I have computed the Difference of Gaussians and have stored them in a 2D cell array. The images in column 2 are half the size of column 1 and so on.
Questions.
Now that I have all of the images stored in my 2D cell array I would like to print them all in one figure.
Im been browsing the web for quite a bit but I haven't seen anything that could help. If anyone could point me in the right direction or provide an example it would be greatly appriciated.
Cheers
If you want a really simple solution then just make a composite image and fill in the regions with the images in the gaussian pyramid. I've given an example code below the works for my case but needs to be adapted for yours.
Code:
% Get total width and height
width_total = 0;
height_total = 0;
for i = 0:3 % Cycle over scales - 4 total
width_total = width_total+size(obj.gaussianpyramid{i+1,1},2);
height_total = height_total+size(obj.gaussianpyramid{i+1,1},1);
end
% Form composite gaussian
compositegaussian = zeros(width_total,height_total);
ind_x = 0;
for i = 0:3 % Cycle over octaves - 4 total
for j = 0:4 % Cycle over scales - 5 total
ind_y = j*size(obj.gaussianpyramid{i+1,j+1},1);
compositegaussian(ind_y+1:ind_y+size(obj.gaussianpyramid{i+1,j+1},1),ind_x+1:ind_x+size(obj.gaussianpyramid{i+1,j+1},2)) = obj.gaussianpyramid{i+1,j+1};
end
ind_x = ind_x + size(obj.gaussianpyramid{i+1,1},2);
end
figure, imshow(compositegaussian,[]);
Output:
Lets generate random 5x2 cell array where the first columns contains 10x10 images and the second - 5x5 images:
c = cell(5,2);
for k=1:5
c{k,1} = uint8(255 * rand(10));
c{k,2} = uint8(255 * rand(5));
end
The following code illustrates them:
figure;
n = size(c, 1);
for k = 1 : n
subplot(n, 2, k * 2 - 1);
image(c{k,1});
subplot(n, 2, k * 2);
image(c{k,2});
end
If the images are upside down, use set(gca,'YDir','normal'); after each image() call.

Resources