optimize Octave code for Zhang Suen thinning algorithm - vectorization

I would like to know if it is possible to vectorize (cf page 599 of this doc) operations that need a whole matrix scan, but with a lot of conditions to check concerning neighbours pixels. The goal is to make it faster, because the code is working when I use a for loop with 10 iterations, but I tried using a while loop, and it never ends. It might also be me screwing the stop condition, but I think the operations could still be faster. The operations I want to optimize are described here.
Here is the code that I want to optimize:
while (stopCond>0)
stopCond = 0;
ap1 = 0;
bp1 = 0;
tabPixel = [];
for x=2:NL-1
for y= 2:NC-1
p1 = imgSeuil(x,y); %current pixel
p2 = imgSeuil(x-1, y); %pixel neighbours
p3 = imgSeuil(x-1, y+1);
p4 = imgSeuil(x, y+1);
p5 = imgSeuil(x+1, y+1);
p6 = imgSeuil(x+1, y);
p7 = imgSeuil(x+1, y-1);
p8 = imgSeuil(x, y-1);
p9 = imgSeuil(x-1, y-1);
tabNeighbour = [p2, p3, p4, p5, p6, p7, p8, p9];
tmpTabl = diff([tabNeighbour, p2]);
tmpTabl = max(tmpTabl, 0);
ap1 = sum(tmpTabl);
bp1 = sum(tabNeighbour);
%%%--------Can I vectorize ops with below conditions--------
if((p1==1)&&(bp1>=2)&&(bp1<=6)&&(ap1==1)&&
((p2==0)||(p4==0)||(p6==0))&&
((p4==0)||(p6==0)||(p8==0)))
%%%adding indexes of current pxl matching these conditions to then change their value when loop is over
tabPixel = [tabPixel, [x; y]];
stopCond += 1;
endif
endfor
endfor
for i=2:columns(tabPixel)
imgSeuil(tabPixel(1, i), tabPixel(2, i)) = 0;
endfor
I also read that using bolean indexing is encouraged, and I would like to know if those changes would significantly improve exec time.
Here is the whole code if you want to run it :
clear all;
close all;
img=imread("/home/redouane/Documents/L3/S6/TIA/TD/ED_3_6_originale.png");
imshow(img);
colorbar();
sizeImg = size(img);
NL=sizeImg(1,1);
NC=sizeImg(1,2);
tab=zeros(2,256); %tab de niveaux de gris
tab(1,1:256)=0:255;
%remplissage tab niveaux de gris
%et affichage de l'histogramme
for y=1:NL
for x= 1:NC
val=img(y,x);
tab(2,val+1)=tab(2,val+1)+1;
end
end
ticktab=zeros(1,25);
for i=1:25
ticktab(1, i)=10*i;
end
figure(2);
plot(tab(1, 1:256),tab(2, 1:256));
set(gca,'XTick',ticktab(1, 1:25));
xlim([0, 255]);
%seuillage de l'img
figure(3);
imgSeuil=img;
for y=1:NL
for x= 1:NC
val=imgSeuil(y,x);
if(val<30)
imgSeuil(y,x)=0;
else
imgSeuil(y,x)=255;
end
end
end
imgSeuil=~imgSeuil;%inversion pour lignes blanches
imshow(imgSeuil);
%squelettisation: cf Zhang Suen algorithm sur rosetta code
%%%--------------
stopCond = 1;
while (stopCond>0)
stopCond = 0;
ap1 = 0;
bp1 = 0;
tabPixel = [];
for x=2:NL-1
for y= 2:NC-1
p1 = imgSeuil(x,y); %les voisins du pixel
p2 = imgSeuil(x-1, y);
p3 = imgSeuil(x-1, y+1);
p4 = imgSeuil(x, y+1);
p5 = imgSeuil(x+1, y+1);
p6 = imgSeuil(x+1, y);
p7 = imgSeuil(x+1, y-1);
p8 = imgSeuil(x, y-1);
p9 = imgSeuil(x-1, y-1);
tabNeighbour = [p2, p3, p4, p5, p6, p7, p8, p9];
tmpTabl = diff([tabNeighbour, p2]);
tmpTabl = max(tmpTabl, 0);
ap1 = sum(tmpTabl);
bp1 = sum(tabNeighbour);
if((p1==1)&&(bp1>=2)&&(bp1<=6)&&(ap1==1)&&
((p2==0)||(p4==0)||(p6==0))&&
((p4==0)||(p6==0)||(p8==0)))
tabPixel = [tabPixel, [x; y]];
stopCond += 1;
endif
endfor
endfor
for i=2:columns(tabPixel)
imgSeuil(tabPixel(1, i), tabPixel(2, i)) = 0;
endfor
ap1 = 0;
bp1 = 0;
tabPixel = [];
for x=2:NL-1
for y= 2:NC-1
p1 = imgSeuil(x,y);
p2 = imgSeuil(x-1, y);
p3 = imgSeuil(x-1, y+1);
p4 = imgSeuil(x, y+1);
p5 = imgSeuil(x+1, y+1);
p6 = imgSeuil(x+1, y);
p7 = imgSeuil(x+1, y-1);
p8 = imgSeuil(x, y-1);
p9 = imgSeuil(x-1, y-1);
tabNeighbour = [p2, p3, p4, p5, p6, p7, p8, p9];
ap1 = sum(diff([tabNeighbour, p2]));
bp1=sum(tabNeighbour);
if((p1==1)&&(bp1>=2)&&(bp1<=6)&&(ap1==1)&&
((p2==0)||(p4==0)||(p8==0))&&
((p2==0)||(p6==0)||(p8==0)))
tabPixel=[tabPixel, x; y];
stopCond += 1;
endif
endfor
endfor
for i=1:columns(tabPixel)
imgSeuil(tabPixel(1, i), tabPixel(2, i))=0;
endfor
endwhile
figure(4);
imshow(imgSeuil);
%%%-------------
##tabSquel=zeros(1,10);
##hold on;
##for y=2:NL-1
## for x= 2:NC-1
## % on utilise ces valeurs pour ne pas acceder aux bords de l'image
## %Pixel1 (P1) correspond à imgSeuil(y,x), c'est le pixel du milieu et on etudie ses voisins
## A=0;%nombre de transi de 0 à 1
## B=0;%nombre de voisins
##
## tabSquel(1,2)=imgSeuil(y,x);%p1
## tabSquel(1,2)=imgSeuil(y-1,x);%p2
## tabSquel(1,3)=imgSeuil(y-1,x+1);%p3
## tabSquel(1,4)=imgSeuil(y,x+1);%p4
## tabSquel(1,5)=imgSeuil(y+1,x+1);%p5
## tabSquel(1,6)=imgSeuil(y+1,x);%p6
## tabSquel(1,7)=imgSeuil(y+1,x-1);%p7
## tabSquel(1,8)=imgSeuil(y,x-1);%p8
## tabSquel(1,9)=imgSeuil(y-1,x-1);%p9
## tabSquel(1,10)=imgSeuil(y-1,x);
##
##
##sum = (0.5*(abs(tabSquel(1,6)-tabSquel(1,1)) + abs(tabSquel(1,7)-tabSquel(1,6)) + abs(tabSquel(1,8)-tabSquel(1,7)) + abs(tabSquel(1,9)-tabSquel(1,8)) + abs(tabSquel(1,2)-tabSquel(1,9)) + abs(tabSquel(1,3)-tabSquel(1,2)) + abs(tabSquel(1,4)-tabSquel(1,3)) + abs(tabSquel(1,5)-tabSquel(1,4))));
## if(sum==3)
## plot(y,x, "ro-");
## end
## end
##end
%imshow(imgSeuil);

I decided to try out the idea of generating a lookup table for each of the 256 possible neighbor combinations. Given a kernel:
encoding_kernel =
1 128 64
2 0 32
4 8 16
we can use filter2 to encode each neighborhood of 8 pixels to an integer in the range 0..255.
Now we just need to determine which bit combinations satisfy the conditions. You'll notice that P1 is multiplied by 0 in the kernel. We'll just use the thresholded image directly to get the value of P1. I've only coded the LUT for Step 1 in the algorithm, but Step 2 is virtually identical.
% generate Step 1 lookup table for encoded neighborhood of P1
%
% encoding_kernel
% 1 128 64
% 2 0 32
% 4 8 16
LUT_Step1 = ones(256, 1);
% generate binary values for keys 0..255
% pixel ordering is: [P2 P3 P4 P5 P6 P7 P8 P9]
binary_keys = dec2bin(0:255, 8)-'0'; % -'0' makes the array numeric
% LUT = LUT AND (2 <= B(P1) <= 6)
B_P1 = sum(binary_keys, 2);
LUT_Step1 = LUT_Step1 & (2 <= B_P1) & (B_P1 <= 6);
% Generate A(P1) by finding the transitions from 0 to 1
% which corresponds to a value of 1 in the diff
A_P1 = sum(diff([binary_keys, binary_keys(:,1)], [], 2) == 1, 2) == 1;
LUT_Step1 = LUT_Step1 & (A_P1 == 1);
% At least one of P2 and P4 and P6 is white (0)
LUT_Step1 = LUT_Step1 & ~all(binary_keys(:,[1,3,5]), 2);
% At least one of P4 and P6 and P8 is white (0)
LUT_Step1 = LUT_Step1 & ~all(binary_keys(:,[3,5,7]), 2);
I haven't manually verified all of the values in the LUT, but from a spot check it seems to be correct. On my machine, a 3GHz Core i5, generating the table took about 0.7-0.8 msec. You could, of course, hardcode the resulting table in your script if you wished.
Once you have the lookup table and the kernel, checking the conditions is pretty easy. Just encode the current image, and then look up the encoded value in the table and if it's 1, then the image should be 0 at that location. (We don't really need to make sure that the image is 1 (black) before applying the other conditions, because changing 0 to 0 doesn't change the outcome.)
clear all;
close all;
% generate the lookup table
zs_lookup_table;
img=imread("https://i.stack.imgur.com/ejNSg.png");
imshow(img);
colorbar();
% threshold img
figure(2)
imgSeuil = img < 30;
imshow(imgSeuil);
encoding_kernel = [
1 128 64
2 0 32
4 8 16
];
% use "valid" in filter2 to ensure each pixel has 8 neighbors
% valid region of image is 1 pixel smaller on each side,
% so we'll need to adjust when we recalculate imgSeuil
encoded_img = filter2(encoding_kernel, imgSeuil, "valid");
% use lookup table to determine which pixels satisfy conditions 1-4
conds1_4 = false(size(imgSeuil));
conds1_4(2:end-1, 2:end-1) = LUT_Step1(encoded_img+1); % convert range to 1..256
imgSeuil(conds1_4) = 0; % no need to explicitly check for pixel == 1
figure(3)
imshow(imgSeuil);
The timings for each pass through Step 1 varied a bit more then generating the table, probably because I updated the image between iterations and there were fewer pixels changing in later iterations. Each pass took between 0.7 and 1.7 msec. Again, I didn't code Step 2 and I didn't check for changes between iterations, but adding it all together you should be able to reach equilibrium in well under a second.

Related

How does Roblox's math.noise() deal with negative inputs?

While messing around with noise outside of Roblox, I realized Perlin/Simplex Noise does not like negative inputs. Remembering Roblox has a noise function, I tried there, and found out negative numbers do work nicely for Roblox's math.noise(). Does anybody know how they made this work, or how to get negative numbers to work for Perlin/Simplex noise in general?
The Simplex Noise I am using (copied from here but changed to have the bitwise and operation):
local function bit_and(a, b) --bitwise and operation
local p, c = 1, 0
while a > 0 and b > 0 do
local ra, rb = a%2, b%2
if (ra + rb) > 1 then
c = c + p
end
a = (a - ra) / 2
b = (b - rb) / 2
p = p * 2
end
return c
end
-- 2D simplex noise
local grad3 = {
{1,1,0},{-1,1,0},{1,-1,0},{-1,-1,0},
{1,0,1},{-1,0,1},{1,0,-1},{-1,0,-1},
{0,1,1},{0,-1,1},{0,1,-1},{0,-1,-1}
}
local p = {151,160,137,91,90,15,
131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,
190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,
88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166,
77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,
102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196,
135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123,
5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,
223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9,
129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228,
251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107,
49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,
138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180}
local perm = {}
for i=0,511 do
perm[i+1] = p[bit_and(i, 255) + 1]
end
local function dot(g, ...)
local v = {...}
local sum = 0
for i=1,#v do
sum = sum + v[i] * g[i]
end
return sum
end
local noise = {}
function noise.produce(xin, yin)
local n0, n1, n2 -- Noise contributions from the three corners
-- Skew the input space to determine which simplex cell we're in
local F2 = 0.5*(math.sqrt(3.0)-1.0)
local s = (xin+yin)*F2; -- Hairy factor for 2D
local i = math.floor(xin+s)
local j = math.floor(yin+s)
local G2 = (3.0-math.sqrt(3.0))/6.0
local t = (i+j)*G2
local X0 = i-t -- Unskew the cell origin back to (x,y) space
local Y0 = j-t
local x0 = xin-X0 -- The x,y distances from the cell origin
local y0 = yin-Y0
-- For the 2D case, the simplex shape is an equilateral triangle.
-- Determine which simplex we are in.
local i1, j1 -- Offsets for second (middle) corner of simplex in (i,j) coords
if x0 > y0 then
i1 = 1
j1 = 0 -- lower triangle, XY order: (0,0)->(1,0)->(1,1)
else
i1 = 0
j1 = 1
end-- upper triangle, YX order: (0,0)->(0,1)->(1,1)
-- A step of (1,0) in (i,j) means a step of (1-c,-c) in (x,y), and
-- a step of (0,1) in (i,j) means a step of (-c,1-c) in (x,y), where
-- c = (3-sqrt(3))/6
local x1 = x0 - i1 + G2 -- Offsets for middle corner in (x,y) unskewed coords
local y1 = y0 - j1 + G2
local x2 = x0 - 1 + 2 * G2 -- Offsets for last corner in (x,y) unskewed coords
local y2 = y0 - 1 + 2 * G2
-- Work out the hashed gradient indices of the three simplex corners
local ii = bit_and(i, 255)
local jj = bit_and(j, 255)
local gi0 = perm[ii + perm[jj+1]+1] % 12
local gi1 = perm[ii + i1 + perm[jj + j1+1]+1] % 12
local gi2 = perm[ii + 1 + perm[jj + 1+1]+1] % 12
-- Calculate the contribution from the three corners
local t0 = 0.5 - x0 * x0 - y0 * y0
if t0 < 0 then
n0 = 0.0
else
t0 = t0 * t0
n0 = t0 * t0 * dot(grad3[gi0+1], x0, y0) -- (x,y) of grad3 used for 2D gradient
end
local t1 = 0.5 - x1 * x1 - y1 * y1
if t1 < 0 then
n1 = 0.0
else
t1 = t1 * t1
n1 = t1 * t1 * dot(grad3[gi1+1], x1, y1)
end
local t2 = 0.5 - x2 * x2 - y2 * y2
if t2 < 0 then
n2 = 0.0
else
t2 = t2 * t2
n2 = t2 * t2 * dot(grad3[gi2+1], x2, y2)
end
-- Add contributions from each corner to get the final noise value.
-- The result is scaled to return values in the interval [-1,1].
return 70.0 * (n0 + n1 + n2)
end
return noise
The Lua programming language version that Roblox uses, LuaU (or Luau), is actually open-source since November of 2021. You can find it here. The math library can be found in this file called lmathlib.cpp and it contains the math.noise function along with internal functions to calculate it, perlin (main function), grad, lerp, and fade. It's a quite complicated thing I can't explain myself, but I have converted it into Lua here.

Pytorch, slicing tensor causes RuntimeError:: one of the variables needed for gradient computation has been modified by an inplace operation:

I wrote a RNN with LSTM cell with Pycharm. The peculiarity of this network is that the output of the RNN is fed into a integration opeartion, computed with Runge-kutta.
The integration takes some input and propagate that in time one step ahead. In order to do so I need to slice the feature tensor X along the batch dimension, and pass this to the Runge-kutta.
class MyLSTM(torch.nn.Module):
def __init__(self, ni, no, sampling_interval, nh=10, nlayers=1):
super(MyLSTM, self).__init__()
self.device = torch.device("cpu")
self.dtype = torch.float
self.ni = ni
self.no = no
self.nh = nh
self.nlayers = nlayers
self.lstms = torch.nn.ModuleList(
[torch.nn.LSTMCell(self.ni, self.nh)] + [torch.nn.LSTMCell(self.nh, self.nh) for i in range(nlayers - 1)])
self.out = torch.nn.Linear(self.nh, self.no)
self.do = torch.nn.Dropout(p=0.2)
self.actfn = torch.nn.Sigmoid()
self.sampling_interval = sampling_interval
self.scaler_states = None
# Options
# description of the whole block
def forward(self, x, h0, train=False, integrate_ode=True):
x0 = x.clone().requires_grad_(True)
hs = x # initiate hidden state
if h0 is None:
h = torch.zeros(hs.shape[0], self.nh, device=self.device)
c = torch.zeros(hs.shape[0], self.nh, device=self.device)
else:
(h, c) = h0
# LSTM cells
for i in range(self.nlayers):
h, c = self.lstms[i](hs, (h, c))
if train:
hs = self.do(h)
else:
hs = h
# Output layer
# y = self.actfn(self.out(hs))
y = self.out(hs)
if integrate_ode:
p = y
y = self.integrate(x0, p)
return y, (h, c)
def integrate(self, x0, p):
# RK4 steps per interval
M = 4
DT = self.sampling_interval / M
X = x0
# X = self.scaler_features.inverse_transform(x0)
for b in range(X.shape[0]):
xx = X[b, :]
for j in range(M):
k1 = self.ode(xx, p[b, :])
k2 = self.ode(xx + DT / 2 * k1, p[b, :])
k3 = self.ode(xx + DT / 2 * k2, p[b, :])
k4 = self.ode(xx + DT * k3, p[b, :])
xx = xx + DT / 6 * (k1 + 2 * k2 + 2 * k3 + k4)
X_all[b, :] = xx
return X_all
def ode(self, x0, y):
# Here I a dynamic model
I get this error:
RuntimeError: one of the variables needed for gradient computation has been modified by an inplace operation: [torch.FloatTensor []], which is output 0 of SelectBackward, is at version 64; expected version 63 instead. Hint: enable anomaly detection to find the operation that failed to compute its gradient, with torch.autograd.set_detect_anomaly(True).
the problem is in the operations xx = X[b, :] and p[b,:]. I know that because I choose batch dimension of 1, then I can replace the previous two equations with xx=X and p, and this works. How can split the tensor without loosing the gradient?
I had the same question, and after a lot of searching, I added .detach() function after "h" and "c" in the RNN cell.

How to generate a 2D periodic pattern like below image from pseudorandom binary sequence?

I want to generate a 2 dimensional periodic pattern from a pseudorandom binary sequence like this one with the following context:
A periodic pattern satisfies the equations (1) and (2)
W(x + q0N0, y) = W(x, y); q0, N0 >1 (1)
W(x, y + q1N1) = W(x, y); q1, N1 > 1, (2)
where N0 and N1 determine the periodicity of repetitions and q0 and q1 a repetition number on the horizontal and vertical directions. Generation from pseudorandom values {−1, 1} produces a rectangular, binary valued pattern.
One way to achieve that would be to take a small pseudo-random 2D pattern (the sequence) and repeat it periodically so that neighboring tiles are always mirrored giving a sense of smooth continuity.
After you specified your requirements with W(x + q0N0, y) = W(x, y) and W(x, y + q1N1) = W(x, y); it becomes clear, that this is exactly (without the mirroring part) what you want.
You simply have to repeat a random pattern a certain number of times in both directions.
Example (similar to your image where the period length in the vertical direction is longer than in the horizontal direction)
Code (in Matlab)
% base pattern
N0 = 20;
N1 = 5;
base = rand([N0, N1]) > 0.5; % pseudo-random
% periodically repeating the pattern
Q0 = 5;
Q1 = 20;
pattern = zeros([N0*Q0,N1*Q1]);
for q0 = 1 : Q0
for q1 = 1 : Q1
pattern((q0-1)*N0+1:q0*N0, (q1-1)*N1+1:q1*N1) = base;
end
end
% save
imwrite(pattern, 'test.jpg');
% display
imagesc(pattern);
axis image;
colormap(gray);
The first lines just compute a random, binary pattern of a certain size N0 x N1
% base pattern
N0 = 20;
N1 = 5;
base = rand([N0, N1]) > 0.5; % pseudo-random
Then comes the definition of the number of repetitions of the pattern in each direction
Q0 = 5;
Q1 = 20;
Finally, in two nested but rather simple for loops, the base pattern is repeated
pattern = zeros([N0*Q0,N1*Q1]);
for q0 = 1 : Q0
for q1 = 1 : Q1
pattern((q0-1)*N0+1:q0*N0, (q1-1)*N1+1:q1*N1) = base;
end
end
The computation of the indices (where to place the base patterns) fulfills your requirement equations
(q0-1)*N0+1:q0*N0, (q1-1)*N1+1:q1*N1
Old Example (with mirroring)
Code (in Matlab)
% base pattern
N = 20;
base = rand(N) > 0.5; % pseudo-random
% multiplying the pattern
M = 4;
pattern = zeros(N*M);
for i = 1 : M
for j = 1 : M
b = base;
% mirroring the base
if mod(i, 2) == 1
flip(b, 2);
end
if mod(j, 2) == 1
flip(b, 1);
end
pattern((i-1)*N+1:i*N, (j-1)*N+1:j*N) = b;
end
end
% save
imwrite(pattern, 'test.jpg');
% display
imagesc(pattern);
axis image;
colormap(gray);
The patterns are flipped (mirrored) in one or two direction sometimes to simulates some kind of smoothness (symmetry) of the pattern.

How to solve logistic regression using gradient descent in octave?

I am learning Machine Learning course from coursera from Andrews Ng. I have written a code for logistic regression in octave. But, it is not working. Can someone help me?
I have taken the dataset from the following link:
Titanic survivors
Here is my code:
pkg load io;
[An, Tn, Ra, limits] = xlsread("~/ML/ML Practice/dataset/train_and_test2.csv", "Sheet2", "A2:H1000");
# As per CSV file we are reading columns from 1 to 7. 8-th column is Survived, which is what we are going to predict
X = [An(:, [1:7])];
Y = [An(:, 8)];
X = horzcat(ones(size(X,1), 1), X);
# Initializing theta values as zero for all
#theta = zeros(size(X,2),1);
theta = [-3;1;1;-3;1;1;1;1];
learningRate = -0.00021;
#learningRate = -0.00011;
# Step 1: Calculate Hypothesis
function g_z = estimateHypothesis(X, theta)
z = theta' * X';
z = z';
e_z = -1 * power(2.72, z);
denominator = 1.+e_z;
g_z = 1./denominator;
endfunction
# Step 2: Calculate Cost function
function cost = estimateCostFunction(hypothesis, Y)
log_1 = log(hypothesis);
log_2 = log(1.-hypothesis);
y1 = Y;
term_1 = y1.*log_1;
y2 = 1.-Y;
term_2 = y2.*log_2;
cost = term_1 + term_2;
cost = sum(cost);
# no.of.rows
m = size(Y, 1);
cost = -1 * (cost/m);
endfunction
# Step 3: Using gradient descent I am updating theta values
function updatedTheta = updateThetaValues(_X, _Y, _theta, _hypothesis, learningRate)
#s1 = _X * _theta;
#s2 = s1 - _Y;
#s3 = _X' * s2;
# no.of.rows
#m = size(_Y, 1);
#s4 = (learningRate * s3)/m;
#updatedTheta = _theta - s4;
s1 = _hypothesis - _Y;
s2 = s1 .* _X;
s3 = sum(s2);
# no.of.rows
m = size(_Y, 1);
s4 = (learningRate * s3)/m;
updatedTheta = _theta .- s4';
endfunction
costVector = [];
iterationVector = [];
for i = 1:1000
# Step 1
hypothesis = estimateHypothesis(X, theta);
#disp("hypothesis");
#disp(hypothesis);
# Step 2
cost = estimateCostFunction(hypothesis, Y);
costVector = vertcat(costVector, cost);
#disp("Cost");
#disp(cost);
# Step 3 - Updating theta values
theta = updateThetaValues(X, Y, theta, hypothesis, learningRate);
iterationVector = vertcat(iterationVector, i);
endfor
function plotGraph(iterationVector, costVector)
plot(iterationVector, costVector);
ylabel('Cost Function');
xlabel('Iteration');
endfunction
plotGraph(iterationVector, costVector);
This is the graph I am getting when I am plotting against no.of.iterations and cost function.
I am tired by adjusting theta values and learning rate. Can someone help me to solve this problem.
Thanks.
I have done a mathematical error. I should have used either power(2.72, -z) or exp(-z). Instead I have used as -1 * power(2.72, z). Now, I'm getting a proper curve.
Thanks.

Projective Transform - matlab code

i can't use any toolbox function i need to build it from scratch.
% load images
img1 = readImage('roadSign.tif');
img2 = readImage('lena.tif');
% call the main function
mapIntoImage(img1,img2)
function [newImage] = mapIntoImage(imageA,imageB)
% Input: imageA, imageB - a grayscale image in the range [0..255].
%
% Output: newImage – imageA into which image B has been mapped.
%
showImage(imageA)
hold on
% Initially, the list of points is empty.
xy = [];
% Loop, picking up the points.
disp('Please enter corners of place to insert image in clockwise order.')
for j = 1:4
[xi,yi] = ginput(1);
%draw a yellow dot
plot(xi,yi,'yo')
xy(:,j) = [xi;yi];
end
% get x1 y1 cordinates - xy(:, 1)
imgRow = size(imageB,1);
imgCol = size(imageB,2);
[X,Y] = meshgrid(1:imgCol,1:imgRow);
imgBcords = [0 size(imageB, 1) size(imageB,1) 0 ;
0 0 size(imageB,2) size(imageB,2)];
coefs = findCoefficients(xy, imgBcords);
A = [coefs(1) coefs(2) coefs(5);coefs(3) coefs(4) coefs(6); coefs(7) coefs(8) 1];
temp = zeros(size(X,1), size(X,2), 3);
new = ones(256);
for i = 1:size(X,1)
for j = 1:size(X,2)
temp(i,j,:) =A*[X(i,j); Y(i,j); new(i,j)];
end
end
end
function [ result ] = findCoefficients( imageA, imageB )
% finds coefficients for inverse mapping algorithem
% takes 2 X 2d vectors each consists of 4 points x,y
% and returns the coef accroding to reverse mapping function
%
% x y 0 0 1 0 -xx' -yx'
% 0 0 x y 0 1 -xy' -yy'
% y' and x' are in the destenation picture;
A = [imageB(1,1) imageB(2,1) 0 0 1 0 -imageB(1,1)*imageA(1,1) -imageB(2,1)*imageA(1,1);
0 0 imageB(1,1) imageB(2,1) 0 1 -imageB(1,1)*imageA(2,1) -imageB(2,1)*imageA(2,1);
imageB(1,2) imageB(2,2) 0 0 1 0 -imageB(1,2)*imageA(1,2) -imageB(2,2)*imageA(1,2);
0 0 imageB(1,2) imageB(2,2) 0 1 -imageB(1,2)*imageA(2,2) -imageB(2,2)*imageA(2,2);
imageB(1,3) imageB(2,3) 0 0 1 0 -imageB(1,3)*imageA(1,3) -imageB(2,3)*imageA(1,3);
0 0 imageB(1,3) imageB(2,3) 0 1 -imageB(1,3)*imageA(2,3) -imageB(2,3)*imageA(2,3);
imageB(1,4) imageB(2,4) 0 0 1 0 -imageB(1,4)*imageA(1,4) -imageB(2,4)*imageA(1,4);
0 0 imageB(1,4) imageB(2,4) 0 1 -imageB(1,4)*imageA(2,4) -imageB(2,4)*imageA(2,4)];
B = [imageB(1,1); imageB(2,1); imageB(1,2); imageB(2,2); imageB(1,3); imageB(2,3); imageB(1,4); imageB(2,4)];
result = pinv(A)*B;
end
i want to build now the transform
[x' y' 1] = A*[X Y 1];
i have figured out that i would need to use repmat, but i can't seem to get to the real syntax without loops.
what's the most efficient way to do it?
A projective transform has the form of
$ x' = \frac {a_{11}x+a_{12}y+a_{13}}{a_{13}x+a_{23}y+a_{33}} \\
y' = \frac {a_{21}x+a_{22}y+a_{23}}{a_{13}x+a_{23}y+a_{33}}
$
Where the coefficients are defined up to some scale factor. One of the ways to ensure a constant scale factor is to set $a_{33}=1$. One easy way to think about it is to use the homogenous coordinates:
$ \left( \begin{array}{ccc} x'\\y'\\S\end{array} \right) =
\left( \begin{array}{ccc} a_{11} & a_{12} & a_{13}\\a_{21} & a_{22} & a_{23}\\ a_{31} & a_{32} & a_{33}\end{array} \right)
\left( \begin{array}{ccc} x\\y\\1\end{array} \right)
$
These coordinates are defined up to scale. That is,
$ \left( \begin{array}{ccc} x'/S\\y'/S\\1\end{array} \right) \equiv
\left( \begin{array}{ccc} x'\\y'\\S\end{array} \right)$
Thus, in your case you should do: (Assuming that x and y are column vectors, and A is the transpose of the matrix that I described above:
XY = A * [x y ones(size(x))];
XY(:,1) = XY(:,1)./XY(:,3);
XY(:,2) = XY(:,2)./XY(:,3);

Resources