LAB image classification using matlab - algorithm

I am trying to implement this algorithm, but I am a little confused about the classification of L, A and B . the algorithm outline is as follows:
Convert the RGB image to a LAB image.
Compute the mean values of the pixels in L, A and B planes of the image
separately.
If mean (A) + mean (B) ≤ 256
3.1. Classify the pixels with a value in L ≤(mean(L) – standard deviation
(L)/3) as shadow pixels and others as non-shadow pixels.
Else classify the pixels with lower values in both L and B planes as shadow
pixels and others as non-shadow pixels.
I am very much confused about how to classify L as a shadow pixel and others as non shadow pixels.
This is the code which has the algorithm implemented:
clear;
I = imread('flower.jpg');
rgb = imresize(I,[256,256]);
mlab = makecform('srgb2lab');
lab = applycform(rgb,mlab);
S_bin = im2bw(rgb);
S = S_bin + (S_bin == 0);
NS = S;
for i=1:255
for j=1:255
A = lab(j,i,2);
B = lab(j,i,3);
L = lab(j,i,1);
Lmean = mean(mean(L));
Amean = mean2(mean2(A));
Bmean = mean2(mean2(B));
if (Amean + Bmean) <= 256
Lstd = std2(L);
std = (Lmean-(Lstd/3));
Lmean = mean(mean(L));
if L <= std
S(j,i,1) = L;
S(j,i,2) = L;
S(j,i,3) = L;
else
S = lab;
end
else
if L < B
S(j,i,1) = L;
S(j,i,2) = L;
S(j,i,3) = L;
else
S(j,i,1) = B;
S(j,i,2) = B;
S(j,i,3) = B;
end
end
end
end
S = lab2rgb(S);
S=uint8(round(S*255));
figure(3);imshow(S);

First of all: L, A and B are scalars. Just one single value. Taking means or standard deviations therefore will not work.
Assign L, A and B first, then take means, standard deviations etc, then built you image in a second loop:
I = imread('flower.jpg');
rgb = imresize(I,[256,256]);
mlab = makecform('srgb2lab');
lab = applycform(rgb,mlab);
S_bin = im2bw(rgb);
S = S_bin + (S_bin == 0);
NS = S;
L = squeeze(lab(:,:,1);
A = squeeze(lab(:,:,2);
B = squeeze(lab(:,:,3);
Lmean = mean(L(:));
Amean = mean(A(:));
Bmean = mean(B(:));
Lstd = std(L(:));
Astd = std(A(:));
Bstd = std(B(:));
if (Amean + Bmean) <= 256
if L<=(Lmean-(Lstd/3));
tmp = L<=(Lmean-(Lstd/3));
S(:,:,1) = zeros(size(L))+L(tmp);
S(:,:,2) = zeros(size(L))+L(tmp);
S(:,:,3) = zeros(size(L))+L(tmp);
else
S = lab;
end
tmp=L<B;
S(:,:,1) = zeros(size(L))+L(tmp);
S(:,:,1) = zeros(size(L))+L(tmp);
S(:,:,1) = zeros(size(L))+L(tmp);
tmp=L=>B;
S(:,:,1) = zeros(size(B))+B(tmp);
S(:,:,1) = zeros(size(B))+B(tmp);
S(:,:,1) = zeros(size(B))+B(tmp);
end
S = lab2rgb(S);
S=uint8(round(S*255));
figure(3);imshow(S);
This way you will just get a one colour pane, either coloured according to L or B, but since you had that before in your code I left it here.

Related

Matalb code Error in Selecting Disc view of Waves

I am getting an error when I run this code for disc waves. The code is attached.
The Error is in line 137 and 292. Please help in resolving issue.
function waves
% WAVES Wave equation in one and two space dimensions.
% The two-dimensional domains include a pi-by-pi square, a unit disc,
% a three-quarter circular sector and the L-shaped union of three squares.
% The eigenfunctions of the square are sin(m*x)*sin(n*y). With polar
% coordinates, the eigenfunctions of the disc and the sector involve Bessel
% functions. The eigenfunctions of the L-shaped domain also involve
% Bessel functions and are computed by the MATLAB function membranetx.m.
% 2-D eigenvalues and eigenfunctions
m = 11; % Determines number of grid points
speed = 1;
bvals = [1; 0; 0; 0; 0];
t = 0;
while bvals(5) == 0
% Initialize figure
shg
clf reset
set(gcf,'doublebuffer','on','menubar','none','tag','', ...
'numbertitle','off','name','Waves','colormap',hot(64));
for k= 1:5
b(k) = uicontrol('style','toggle','value',bvals(k), ...
'units','normal','position',[.15*k .01 .14 .05]);
end
set(b(1),'style','pop','string', ...
{'1-d','square','disc','sector'})
set(b(2),'string','modes/wave')
set(b(3),'string','slower')
set(b(4),'string','faster')
set(b(5),'string','close')
if bvals(3)==1
speed = speed/sqrt(2);
set(b(3),'value',0);
end
if bvals(4)==1
speed = speed*sqrt(2);
set(b(4),'value',0);
end
bvals = cell2mat(get(b,'value'));
region = bvals(1);
modes = bvals(2)==0;
if region == 1
% 1-D
x = (0:4*m)/(4*m)*pi;
orange = [1 1/3 0];
gray = get(gcf,'color');
if modes
% 1-D modes
for k = 1:4
subplot(2,2,k)
h(k) = plot(x,zeros(size(x)));
axis([0 pi -3/2 3/2])
set(h(k),'color',orange,'linewidth',3)
set(gca,'color',gray','xtick',[],'ytick',[])
end
delta = 0.005*speed;
bvs = bvals;
while all(bvs == bvals)
t = t + delta;
for k = 1:4
u = sin(k*t)*sin(k*x);
set(h(k),'ydata',u)
end
drawnow
bvs = cell2mat(get(b,'value'));
end
else
% 1-D wave
h = plot(x,zeros(size(x)));
axis([0 pi -9/4 9/4])
set(h,'color',orange,'linewidth',3)
set(gca,'color',gray','xtick',[],'ytick',[])
delta = 0.005*speed;
a = 1./(1:4);
bvs = bvals;
while all(bvs == bvals)
t = t + delta;
u = zeros(size(x));
for k = 1:4
u = u + a(k)*sin(k*t)*sin(k*x);
end
set(h,'ydata',u)
drawnow
bvs = cell2mat(get(b,'value'));
end
end
elseif region <= 5
switch region
case 2
% Square
x = (0:2*m)/(2*m)*pi;
y = x';
lambda = zeros(4,1);
V = cell(4,1);
k = 0;
for i = 1:2
for j = 1:2
k = k+1;
lambda(k) = i^2 + j^2;
V{k} = sin(i*y)*sin(j*x);
end
end
ax = [0 pi 0 pi -1.75 1.75];
case 3
% Disc, mu = zeros of J_0(r) and J_1(r)
mu = [bjzeros(0,2) bjzeros(1,2)];
[r,theta] = meshgrid((0:m)/m,(-m:m)/m*pi);
x = r.*cos(theta);
y = r.*sin(theta);
V = cell(4,1);
k = 0;
for j = 0:1
for i = 1:2
k = k+1;
if j == 0
V{k} = besselj(0,mu(k)*r);
else
V{k} = besselj(j,mu(k)*r).*sin(j*theta);
end
V{k} = V{k}/max(max(abs(V{k})));
end
end
lambda = mu.^2;
ax = [-1 1 -1 1 -1.75 1.75];
case 4
% Circular sector , mu = zeros of J_(2/3)(r) and J_(4/3)(r)
mu = [bjzeros(2/3,2) bjzeros(4/3,2)];
[r,theta] = meshgrid((0:m)/m,(3/4)*(0:2*m)/m*pi);
x = r.*cos(theta+pi);
y = r.*sin(theta+pi);
V = cell(4,1);
k = 0;
for j = 1:2
for i = 1:2
k = k+1;
alpha = 2*j/3;
V{k} = besselj(alpha,mu(k)*r).*sin(alpha*theta);
V{k} = V{k}/max(max(abs(V{k})));
end
end
lambda = mu.^2;
ax = [-1 1 -1 1 -1.75 1.75];
case 5\
% L-membrane
x = (-m:m)/m;
y = x';
lambda = zeros(4,1);
V = cell(4,1);
for k = 1:4
[L lambda(k)] = membranetx(k,m,9,9);
L(m+2:2*m+1,m+2:2*m+1) = NaN;
V{k} = rot90(L,-1);
end
ax = [-1 1 -1 1 -1.75 1.75];
end
if modes
% 2-D modes
p = [.02 .52 .02 .52];
q = [.52 .52 .02 .02];
for k = 1:4
axes('position',[p(k) q(k) .46 .46]);
h(k) = surf(x,y,zeros(size(V{k})));
axis(ax)
axis off
view(225,30);
caxis([-1.5 1]);
end
delta = .08*speed;
mu = sqrt(lambda(:));
bvs = bvals;
while all(bvs == bvals)
t = t + delta;
for k = 1:4
U = 1.5*sin(mu(k)*t)*V{k};
set(h(k),'zdata',U)
set(h(k),'cdata',U)
end
drawnow
bvs = cell2mat(get(b,'value'));
end
else
% 2-D wave
h = surf(x,y,zeros(size(V{1})));
axis(ax);
axis off
view(225,30);
caxis([-1.5 1]);
delta = .02*speed;
mu = sqrt(lambda(:));
a = 1.25./(1:4);
bvs = bvals;
while all(bvs == bvals)
t = t + delta;
U = zeros(size(V{1}));
for k = 1:4
U = U + a(k)*sin(mu(k)*t)*V{k};
end
set(h,'zdata',U)
set(h,'cdata',U)
drawnow
bvs = cell2mat(get(b,'value'));
end
end
elseif region == 6
figure
bizcard
set(b(1),'value',1)
end
% Retain uicontrol values
bvals = cell2mat(get(b,'value'));
end
close
% -------------------------------
function z = bjzeros(n,k)
% BJZEROS Zeros of the Bessel function.
% z = bjzeros(n,k) is the first k zeros of besselj(n,x)
% delta must be chosen so that the linear search can take
% steps as large as possible without skipping any zeros.
% delta is approx bjzero(0,2)-bjzero(0,1)
delta = .99*pi;
Jsubn = inline('besselj(n,x)''x','n');
a = n+1;
fa = besselj(n,a);
z = zeros(1,k);
j = 0;
while j < k
b = a + delta;
fb = besselj(n,b);
if sign(fb) ~= sign(fa)
j = j+1;
z(j) = fzerotx(Jsubn,[a b],n);
end
a = b;
fa = fb;
end

Color image pixel permutation not reversible

I performed color image permutation using 2D sine-map for RGB image. The code uses this map to perform pixel location permutation for each RGB channel in the image. Then, I used the same map with the same initial parameters to inverse the permutation. The problem is the code only perform correct inverse permutation for one channel only the other channels is not recovered. See the attached images of the permuted and the recovered image.
%% Image Encryption Demo - Encryption and Decryption
clear all
close all
clc
%% 1. Load plaintext images
% Image 1
I = imread('D:\1\1.jpg');
Ir = I(:,:,1);
Ig = I(:,:,2);
Ib = I(:,:,3);
K=1;
%% 2. Encryption
%[CI,K] = Logistic2D_ImageCipher(I,'encryption');
[CIb,K] = Logistic2D_ImageCipher(Ib,'encryption');
clearvars -except CIb Ir Ig Ib K I;
[CIr,K] = Logistic2D_ImageCipher(Ir,'encryption');
clearvars -except CIb CIr Ir Ig Ib K I;
[CIg,K] = Logistic2D_ImageCipher(Ig,'encryption');
clearvars -except CIb CIr CIg Ir Ig Ib K I;
CI = cat(3,CIr,CIg,CIb);
%% 3. Decryption
%DI = Logistic2D_ImageCipher(CI,'decryption',K);
DIb = Logistic2D_ImageCipher(CIb,'decryption',K);
clearvars -except CIb CIr CIg Ir Ig Ib K I DIb CI;
DIg = Logistic2D_ImageCipher(CIg,'decryption',K);
clearvars -except CIb CIr CIg Ir Ig Ib K I DIb DIg CI;
DIr = Logistic2D_ImageCipher(CIr,'decryption',K);
clearvars -except CIb CIr CIg Ir Ig Ib K I DIb DIg DIr CI;
DI = cat(3,DIr,DIg,DIb);
%% 4. Analaysis
% Histogram
%title('aaa');
figure,subplot(221),imshow(I,[]),subplot(222),imshow(CI,[])
subplot(223),imhist(I),subplot(224),imhist(CI)
title('aaa2');
figure,subplot(221),imshow(DI,[])
function varargout = Logistic2D_ImageCipher(P,para,K)
%% 1. Initialization
% 1.1. Genereate Random Key if K is not given
if ~exist('K','var') && strcmp(para,'encryption')
K = round(rand(1,256));
varOutN = 2;
elseif ~exist('K','var') && strcmp(para,'decryption')
error('Cannot Complete Decryption without Encryption Key')
else
varOutN = 1;
end
% 1.2. Translate K to map formats
transFrac = #(K,st,ed) sum(K(st:ed).*2.^(-(1:(ed-st+1))));
x0 = transFrac(K,1,52);
y0 = transFrac(K,53,104);
a=0.8;
b =0.3;
r = transFrac(K,105,156)*.08+1.11;
T = transFrac(K,157,208);
turb = blkproc(K(209:256),[1,8],#(x) bi2de(x));
MN = numel(P);
Logistic2D = #(x,y,a) [sin(pi*a*(y+3)*x*(1-x)), sin(pi*a*(x+3)*y*(1-y))];
format long eng
%% 2. Estimate cipher rounds
if max(P(:))>1
F = 256;
S = 4;
else
F = 2;
S = 32;
end
P = double(P);
iter = 1;
%iter = ceil(log2(numel(P))/log2(S));
%% 3. Image Cipher
C = double(P);
switch para
case 'encryption'
for i = 1:iter
tx0 = mod(log(turb(mod(i-1,6)+1)+i)*x0+T,1);
ty0 = mod(log(turb(mod(i-1,6)+1)+i)*y0+T,1);
xy = zeros(MN,2);
for n = 1:MN
if n == 1
xy(n,:) = (Logistic2D(tx0,ty0,a));
else
xy(n,:) = (Logistic2D(xy(n-1,1),xy(n-1,2),a));
end
end
R = cat(3,reshape(xy(:,1),size(P,1),size(P,2)),reshape(xy(:,2),size(P,1),size(P,2)));
C = LogisticPermutation(C,R,'encryption');
end
case 'decryption'
for i = iter:-1:1
tx0 = mod(log(turb(mod(i-1,6)+1)+i)*x0+T,1);
ty0 = mod(log(turb(mod(i-1,6)+1)+i)*y0+T,1);
xy = zeros(MN,2);
for n = 1:MN
if n == 1
xy(n,:) = (Logistic2D(tx0,ty0,a));
else
xy(n,:) = (Logistic2D(xy(n-1,1),xy(n-1,2),a));
end
end
R = cat(3,reshape(xy(:,1),size(P,1),size(P,2)),reshape(xy(:,2),size(P,1),size(P,2)));
C = LogisticPermutation(C,R,'decryption');
end
end
%% 4. Output
switch F
case 2
C = logical(C);
case 256
C = uint8(C);
end
switch varOutN
case 1
varargout{1} = C;
case 2
varargout{1} = C;
varargout{2} = K;
end
function C = LogisticPermutation(P,R,para)
C0 = zeros(size(P));
C = C0;
switch para
case 'encryption'
% 1. Shuffling within a Column
[v,Epix] = sort(R(:,:,1),1);
for i = 1:size(R,1)
C0(:,i) = P(Epix(:,i),i);
end
% 2. Shuffling within a Row
[v,Epiy] = sort(R(:,:,2),2);
for j = 1:size(R,2)
C(j,:) = C0(j,Epiy(j,:));
end
case 'decryption'
% 1. Shuffling within a Row
[v,Epiy] = sort(R(:,:,2),2);
for j = 1:size(R,2)
C0(j,Epiy(j,:)) = P(j,:);
end
% 2. Shuffling within a Column
[v,Epix] = sort(R(:,:,1),1);
for i = 1:size(R,1)
C(Epix(:,i),i) = C0(:,i);
end
end
It didn't work because you overwrote K in the encryption stage, and it was different for each channel, so the decryption only worked correctly for the last channel that created K. If you're using the MATLAB editor, you should pay attention to the mlint warnings (square at the top right that should be always be green) - you could say that this is what told me the answer to your problem.
Here's a fixed version of the first part of the script:
function q50823167
%% 1. Load plaintext images
% Image 1
I = imread(fullfile(matlabroot, 'examples', 'wavelet', 'mandrill.jpg'));
Ir = I(:,:,1);
Ig = I(:,:,2);
Ib = I(:,:,3);
%% 2. Encryption
%[CI,K] = Logistic2D_ImageCipher(I,'encryption');
[CIb,Kb] = Logistic2D_ImageCipher(Ib,'encryption');
[CIr,Kr] = Logistic2D_ImageCipher(Ir,'encryption');
[CIg,Kg] = Logistic2D_ImageCipher(Ig,'encryption');
CI = cat(3,CIr,CIg,CIb);
%% 3. Decryption
%DI = Logistic2D_ImageCipher(CI,'decryption',K);
DIb = Logistic2D_ImageCipher(CIb,'decryption',Kb);
DIg = Logistic2D_ImageCipher(CIg,'decryption',Kg);
DIr = Logistic2D_ImageCipher(CIr,'decryption',Kr);
DI = cat(3,DIr,DIg,DIb);
%% 4. Analaysis
% Histogram
%title('aaa');
figure,subplot(221),imshow(I,[]),subplot(222),imshow(CI,[])
subplot(223),imhist(I),subplot(224),imhist(CI)
title('aaa2');
figure,subplot(221),imshow(DI,[])
Note that you don't have to clear variables every time.

I want to correct this code for images, what change need to do..?

Currently i am recognzing a face, means i have to find a face which we have to test is in training database or not..! So, i have to decide yes or no..
Yes means find image, and no means print message that NO IMAGE IN DATABASE. I have a program, Currently this program is finding a correct image correctly, but even when there is no image, even it shows other image which not matches.. Actually it should print NO IMAGE IN DATABASE.
So, How to do..?
Here is a Test and training images data on this link.
http://www.fileconvoy.com/dfl.php?id=g6e59fe8105a6e6389994740914b7b2fc99eb3e445
My Program is in terms of different four .m files, and it is here,we have to run only first code.. and remaining 3 are functions, it is also given here..**
clear all
clc
close all
TrainDatabasePath = uigetdir('D:\Program Files\MATLAB\R2006a\work', 'Select training database path' );
TestDatabasePath = uigetdir('D:\Program Files\MATLAB\R2006a\work', 'Select test database path');
prompt = {'Enter test image name (a number between 1 to 10):'};
dlg_title = 'Input of PCA-Based Face Recognition System';
num_lines= 1;
def = {'1'};
TestImage = inputdlg(prompt,dlg_title,num_lines,def);
TestImage = strcat(TestDatabasePath,'\',char(TestImage),'.jpg');
im = imread(TestImage);
T = CreateDatabase(TrainDatabasePath);
[m, A, Eigenfaces] = EigenfaceCore(T);
OutputName = Recognition(TestImage, m, A, Eigenfaces);
SelectedImage = strcat(TrainDatabasePath,'\',OutputName);
SelectedImage = imread(SelectedImage);
imshow(im)
title('Test Image');
figure,imshow(SelectedImage);
title('Equivalent Image');
str = strcat('Matched image is : ',OutputName);
disp(str)
function T = CreateDatabase(TrainDatabasePath)
TrainFiles = dir(TrainDatabasePath);
Train_Number = 0;
for i = 1:size(TrainFiles,1)
if
not(strcmp(TrainFiles(i).name,'.')|strcmp(TrainFiles(i).name,'..')|strcmp(TrainFiles(i).name,'Thu mbs.db'))
Train_Number = Train_Number + 1; % Number of all images in the training database
end
end
T = [];
for i = 1 : Train_Number
str = int2str(i);
str = strcat('\',str,'.jpg');
str = strcat(TrainDatabasePath,str);
img = imread(str);
img = rgb2gray(img);
[irow icol] = size(img);
temp = reshape(img',irow*icol,1); % Reshaping 2D images into 1D image vectors
T = [T temp]; % 'T' grows after each turn
end
function [m, A, Eigenfaces] = EigenfaceCore(T)
m = mean(T,2); % Computing the average face image m = (1/P)*sum(Tj's) (j = 1 : P)
Train_Number = size(T,2);
A = [];
for i = 1 : Train_Number
temp = double(T(:,i)) - m;
Ai = Ti - m
A = [A temp]; % Merging all centered images
end
L = A'*A; % L is the surrogate of covariance matrix C=A*A'.
[V D] = eig(L); % Diagonal elements of D are the eigenvalues for both L=A'*A and C=A*A'.
L_eig_vec = [];
for i = 1 : size(V,2)
if( D(i,i)>1 )
L_eig_vec = [L_eig_vec V(:,i)];
end
end
Eigenfaces = A * L_eig_vec; % A: centered image vectors
function OutputName = Recognition(TestImage, m, A, Eigenfaces)
ProjectedImages = [];
Train_Number = size(Eigenfaces,2);
for i = 1 : Train_Number
temp = Eigenfaces'*A(:,i); % Projection of centered images into facespace
ProjectedImages = [ProjectedImages temp];
end
InputImage = imread(TestImage);
temp = InputImage(:,:,1);
[irow icol] = size(temp);
InImage = reshape(temp',irow*icol,1);
Difference = double(InImage)-m; % Centered test image
ProjectedTestImage = Eigenfaces'*Difference; % Test image feature vector
Euc_dist = [];
for i = 1 : Train_Number
q = ProjectedImages(:,i);
temp = ( norm( ProjectedTestImage - q ) )^2;
Euc_dist = [Euc_dist temp];
end
[Euc_dist_min , Recognized_index] = min(Euc_dist);
OutputName = strcat(int2str(Recognized_index),'.jpg');
So, how to generate error massege when no image matches..?
At the moment, your application appears to find the most similar image (you appear to be using Euclidean distance as you measure of similarity), and return it. There doesn't seem to be any concept of whether the image "matches" or not.
Define a threshold on similarity, and then determine whether your most similar image meets that threshold. If it does, return it, otherwise display an error message.

Fast computation of warp matrices

For a fixed and given tform, the imwarp command in the Image Processing Toolbox
B = imwarp(A,tform)
is linear with respect to A, meaning there exists some sparse matrix W, depending on tform but independent of A, such that the above can be equivalently implemented
B(:)=W*A(:)
for all A of fixed known dimensions [n,n]. My question is whether there are fast/efficient options for computing W. The matrix form is necessary when I need the transpose operation W.'*B(:), or if I need to do W\B(:) or similar linear algebraic things which I can't do directly through imwarp alone.
I know that it is possible to compute W column-by-column by doing
E=zeros(n);
W=spalloc(n^2,n^2,4*n^2);
for i=1:n^2
E(i)=1;
tmp=imwarp(E,tform);
E(i)=0;
W(:,i)=tmp(:);
end
but this is brute force and slow.
The routine FUNC2MAT is somewhat more optimal in that it uses the loop to compute/gather the sparse entry data I,J,S of each column W(:,i). Then, after the loop, it uses this to construct the overall sparse matrix. It also offers the option of using a PARFOR loop. However, this is still slower than I would like.
Can anyone suggest more speed-optimal alternatives?
EDIT:
For those uncomfortable with my claim that imwarp(A,tform) is linear w.r.t. A, I include the demo script below, which tests that the superposition property is satisfied for random input images and tform data. It can be run repeatedly to see that the nonlinearityError is always small, and easily attributable to floating point noise.
tform=affine2d(rand(3,2));
%tform=projective2d(rand(3));
fun=#(A) imwarp(A,tform,'cubic');
I1=rand(100); I2=rand(100);
c1=rand; c2=rand;
LHS=fun(c1*I1+c2*I2); %left hand side
RHS=c1*fun(I1)+c2*fun(I2); %right hand side
linearityError = norm(LHS(:)-RHS(:),'inf')
That's actually pretty simple:
W = sparse(B(:)/A(:));
Note that W is not unique, but this operation probably produces the most sparse result. Another way to calculate it would be
W = sparse( B(:) * pinv(A(:)) );
but that results in a much less sparse (yet still valid) result.
I constructed the warping matrix using the optical flow fields [u,v] and it is working well for my application
% this function computes the warping matrix
% M x N is the size of the image
function [ Fw ] = generateFwi( u,v,M,N )
Fw = zeros(M*N, M*N);
k =1;
for i=1:M
for j= 1:N
newcoord(1) = i+u(i,j);
newcoord(2) = j+v(i,j);
newi = newcoord(1);
newj = newcoord(2);
if newi >0 && newj >0
newi1x = floor(newi);
newi1y = floor(newj);
newi2x = floor(newi);
newi2y = ceil(newj);
newi3x = ceil(newi); % four nearest points to the given point
newi3y = floor(newj);
newi4x = ceil(newi);
newi4y = ceil(newj);
x1 = [newi,newj;newi1x,newi1y];
x2 = [newi,newj;newi2x,newi2y];
x3 = [newi,newj;newi3x,newi3y];
x4 = [newi,newj;newi4x,newi4y];
w1 = pdist(x1,'euclidean');
w2 = pdist(x2,'euclidean');
w3 = pdist(x3,'euclidean');
w4 = pdist(x4,'euclidean');
if ceil(newi) == floor(newi) && ceil(newj)==floor(newj) % both the new coordinates are integers
Fw(k,(newi1x-1)*N+newi1y) = 1;
else if ceil(newi) == floor(newi) % one of the new coordinates is an integer
w = w1+w2;
w1new = w1/w;
w2new = w2/w;
W = w1new*w2new;
y1coord = (newi1x-1)*N+newi1y;
y2coord = (newi2x-1)*N+newi2y;
if y1coord <= M*N && y2coord <=M*N
Fw(k,y1coord) = W/w2new;
Fw(k,y2coord) = W/w1new;
end
else if ceil(newj) == floor(newj) % one of the new coordinates is an integer
w = w1+w3;
w1 = w1/w;
w3 = w3/w;
W = w1*w3;
y1coord = (newi1x-1)*N+newi1y;
y2coord = (newi3x-1)*N+newi3y;
if y1coord <= M*N && y2coord <=M*N
Fw(k,y1coord) = W/w3;
Fw(k,y2coord) = W/w1;
end
else % both the new coordinates are not integers
w = w1+w2+w3+w4;
w1 = w1/w;
w2 = w2/w;
w3 = w3/w;
w4 = w4/w;
W = w1*w2*w3 + w2*w3*w4 + w3*w4*w1 + w4*w1*w2;
y1coord = (newi1x-1)*N+newi1y;
y2coord = (newi2x-1)*N+newi2y;
y3coord = (newi3x-1)*N+newi3y;
y4coord = (newi4x-1)*N+newi4y;
if y1coord <= M*N && y2coord <= M*N && y3coord <= M*N && y4coord <= M*N
Fw(k,y1coord) = w2*w3*w4/W;
Fw(k,y2coord) = w3*w4*w1/W;
Fw(k,y3coord) = w4*w1*w2/W;
Fw(k,y4coord) = w1*w2*w3/W;
end
end
end
end
else
Fw(k,k) = 1;
end
k=k+1;
end
end
end

Understanding and Implementing Thinning Algorithm in MATLAB

I am trying to implement my own Thinning Algorithm in Matlab to understand the thinning algorithm. I am following http://fourier.eng.hmc.edu/e161/lectures/morphology/node2.html and implementing my own code, but the result is incorrect.
Here is my code:
%for the sake of simplicity, the outermost pixels are ignored.
for x = 2:1:511
for y = 2:1:511
% if this pixel is not black, then, proceed in.
if (frame2(y,x) > 0)
% the pos(1 to 8) here are for the surrounding pixels.
pos(1) = frame2(y-1,x-1);
pos(2) = frame2(y, x-1);
pos(3) = frame2(y+1, x+1);
pos(4) = frame2(y+1, x);
pos(5) = frame2(y+1, x-1);
pos(6) = frame2(y, x-1);
pos(7) = frame2(y-1, x-1);
pos(8) = frame2(y-1, x);
nonZeroNeighbor = 0;
transitSequence = 0;
change = 0;
for n = 1:1:8
% for N(P1)
if (pos(n) >= 1)
nonZeroNeighbor = nonZeroNeighbor + 1;
end
% for S(P1)
if (n > 1)
if (pos(n) ~= change)
change = pos(n);
transitSequence = transitSequence + 1;
end
else
change = pos(n);
end
end
% also for S(P1)
if ((nonZeroNeighbor > 1 && nonZeroNeighbor < 7) || transitSequence >= 2)
markMatrix(y,x) = 1;
fprintf(1, '(%d,%d) nonzero: %d transit: %d\n', y,x, nonZeroNeighbor, transitSequence);
else %this else here is for the reverse.
end
end
end
end
for x = 2:1:511
for y = 2:1:511
if (markMatrix(y,x) > 0)
frame2(y,x) = 0;
end
end
end
savePath = [path header number2 '.bmp'];
imwrite(frame2, savePath, 'bmp'); %output image here, replacing the original
From the site above, it states the function S(P1) as:
"S(P1): number of 0 to 1 (or 1 to 0) transitions in the sequence (P2, P3, ..., P9)"
For this part, my codes are below "% for S(P1)" and "% also for S(P1)" comments. Am I implementing this function correctly? The output image I got is simply blank. Nothing at all.
For the correct output, I am aware that there is a logical problem. Regarding the site, it states:
When part of the shape is only 2-pixel wide, all pixels are boundary points and will be marked and then deleted.
This problem is to be ignored for now.
I've had a go at the problem and think I managed to get the algorithm to work. I've made several small edits along the way (please see the code below for details), but also found two fundamental problems with your initial implementation.
Firstly, you assumed all would be done in the first pass of step 1 and 2, but really you need to let the algorithm work away at the image for some time. This is typical for iterative morphological steps 'eating' away at the image. This is the reason for the added while loop.
Secondly, your way of calculating S() was wrong; it counted both steps from 0 to 1 and 1 to 0, counting twice when it shouldn't and it didn't take care of the symmetry around P(2) and P(9).
My code:
%Preliminary setups
close all; clear all;
set(0,'DefaultFigureWindowStyle','Docked')
%Read image
frame2 = imread('q1.jpg');
%Code for spesific images
%frame2(:,200:end) = [];
%frame2 = rgb2gray(frame2);
%Make binary
frame2(frame2 < 128) = 1;
frame2(frame2 >= 128) = 0;
%Get sizes and set up mark
[Yn Xn] = size(frame2);
markMatrix = zeros(Yn,Xn);
%First visualization
figure();imagesc(frame2);colormap(gray)
%%
%While loop control
cc = 0;
changed = 1;
while changed && cc < 50;
changed = 0;
cc = cc + 1;
markMatrix = zeros(Yn,Xn);
for x = 2:1:Xn-1
for y = 2:1:Yn-1
% if this pixel is not black, then, proceed in.
if (frame2(y,x) > 0)
% the pos(2 to 9) here are for the surrounding pixels.
pos(1) = frame2(y, x);
pos(2) = frame2(y-1, x);
pos(3) = frame2(y-1, x+1);
pos(4) = frame2(y, x+1);
pos(5) = frame2(y+1, x+1);
pos(6) = frame2(y+1, x);
pos(7) = frame2(y+1, x-1);
pos(8) = frame2(y, x-1);
pos(9) = frame2(y-1, x-1);
nonZeroNeighbor = 0;
transitSequence = 0;
change = pos(9);
for n = 2:1:9
%N()
nonZeroNeighbor = sum(pos(2:end));
%S()
if (double(pos(n)) - double(change)) < 0
transitSequence = transitSequence + 1;
end
change = pos(n);
end
%Test if pixel is to be removed
if ~( nonZeroNeighbor == 0 || nonZeroNeighbor == 1 ...
||nonZeroNeighbor == 7 || nonZeroNeighbor == 8 ...
||transitSequence >= 2)
markMatrix(y,x) = 1;
fprintf(1, '(%d,%d) nonzero: %d transit: %d\n', ...
y,x, nonZeroNeighbor, transitSequence);
end
end
end
end
%Mask out all pixels found to be deleted
frame2(markMatrix > 0) = 0;
%Check if anything has changed
if sum(markMatrix(:)) > 0;changed = 1;end
end
%Final visualization
figure();imagesc(frame2);colormap(gray)

Resources