Separate Double Moon Classification with A Line in Matlab - matlab

I have some Matlab code lines for drawing Double Moon Classification:
function data=dm(r,w,ts,d)
clear all; close all;
if nargin<4, w=6;end
if nargin<3, r=10;end
if nargin<2, d=-4;end
if nargin < 1, ts=1000; end
ts1=10*ts;
done=0; tmp1=[];
while ~done,
tmp=[2*(r+w/2)*(rand(ts1,1)-0.5) (r+w/2)*rand(ts1,1)];
tmp(:,3)=sqrt(tmp(:,1).*tmp(:,1)+tmp(:,2).*tmp(:,2));
idx=find([tmp(:,3)>r-w/2] & [tmp(:,3)<r+w/2]);
tmp1=[tmp1;tmp(idx,1:2)];
if length(idx)>= ts,
done=1;
end
end
data=[tmp1(1:ts,:) zeros(ts,1);
[tmp1(1:ts,1)+r -tmp1(1:ts,2)-d ones(ts,1)]];
plot(data(1:ts,1),data(1:ts,2),'.r',data(ts+1:end,1),data(ts+1:end,2),'.b');
title(['Perceptron with the double-moon set at distance d = ' num2str(d)]),
axis([-r-w/2 2*r+w/2 -r-w/2-d r+w/2])
save dm r w ts d data;
Results:
My question is how to put a line into the Double Moon Classification so that can separate both classification in Matlab code?

I have made a simulation of your problem and wrote a pragmatic solution based on the steps
generates a grid of points fine enough(step size as small as
possible)
find which of these points are in the space between both points
groups
find which points have an equal distance to both groups
plot points
The main part (without my data generation code and the plot I did) of the code is
PBlues = data(1:ts,:);
PReds = data(ts+1:end,:);
Xs = linspace( min(data(:,1)), max(data(:,1)), 100);
Ys = linspace( min(data(:,2)), max(data(:,2)), 100);
[Xs,Ys] = meshgrid( Xs, Ys);
%% compute point relative distance to each point set (ble and red)
bCouldbeInbetween = false(size(Xs));
minDistsb = zeros(size(Xs));
minDistsr = zeros(size(Xs));
for p=1:numel(Xs)
distb = sqrt( (Xs(p)- PBlues(:,1)).^2+(Ys(p)- PBlues(:,2)).^2);
distr = sqrt( (Xs(p)- PReds(:,1)).^2+(Ys(p)- PReds(:,2)).^2);
minDistsb(p) = min(distb);
minDistsr(p) = min(distr);
i = find(distb == minDistsb(p));
j = find(distr == minDistsr(p));
bCouldbeInbetween(p) = (sign(PBlues(i,1)-Xs(p)) ~= sign(PReds(j,1)-Xs(p))) || ...
(sign(PBlues(i,2)-Ys(p)) ~= sign(PReds(j,2)-Ys(p)));
if bCouldbeInbetween(p)
end
end
% point distance difference to each point set
DistDiffs = abs(minDistsb - minDistsr);
% point with equal distance using proportional decision strategy
bCandidates = DistDiffs./ max(minDistsb,minDistsr) < 0.05;
medianLine = [Xs(bCandidates),Ys(bCandidates)];
[~,I] = sort(medianLine(:,1));
medianLine(:,1) = medianLine(I,1);
medianLine(:,2) = medianLine(I,2);
I hope this helps
I have just made a submission which can be downloaded here: https://de.mathworks.com/matlabcentral/fileexchange/66618-linebetweentwopointsgroups-exchange--

Related

Summarize all intersection points by clockwise direction

This a program that I have, I already asked before for how to find the intersection on my image with a circle, and somebody has an answer it (thank you) and I have another problem...
a = imread('001_4.bmp');
I2 = imcrop(a,[90 5 93 180]);
[i,j]=size(I2);
x_hist=sum(I2,1);
y_hist=(sum(I2,2))';
x=1:j ; y=1:i;
centx=sum(x.*x_hist)/sum(x_hist);
centy=sum(y.*y_hist)/sum(y_hist);
BW = edge(I2,'Canny',0.5);
bw2 = imcomplement(BW);
circle = int32([centx,centy,40]);%<<----------
shapeInserter = vision.ShapeInserter('Fill',false);
release(shapeInserter);
set(shapeInserter,'Shape','Circles');
% construct binary image of circle only
bwCircle = step(shapeInserter,true(size(bw2)),circle);
% find the indexes of the intersection between the binary image and the circle
[i, j] = find ((bw2 | bwCircle) == 0);
figure
imshow(bw2 & bwCircle) % plot the combination of both images
hold on
plot(j, i, 'r*') % plot the intersection points
K = step(shapeInserter,bw2,circle);
[n,m]=size(i);
d=0;
k=1;
while (k < n)
d = d + sqrt((i(k+1)-i(k)).^2 + (j(k+1)-j(k)).^2);
k = k+1;
end
Q: How can I calculate all the existing intersection values(red *) in a clockwise direction?
Not sure, but I think that your teacher meant something different from the answer given in the previous question, because
CW direction can be a hint, not a additional problem
I've seen no clue that the circle should be drawn; for small radius circles are blocky and simple bw_circle & bw_edges may not work. For details please see "Steve on image processing" blog, "Intersecting curves that don't intersect"[1]
May be your teacher is rather old and wants Pascal-stile answer.
If my assumptions are correct the code below should be right
img = zeros(7,7); %just sample image, edges == 1
img(:,4) = 1; img(sub2ind(size(img),1:7,1:7)) = 1;
ccx = 4; % Please notice: x is for columns, y is for rows
ccy = 3;
rad = 2;
theta = [(pi/2):-0.01:(-3*pi/2)];
% while plotting it will appear CCW, for visual CW and de-facto CCW use
% 0:0.01:2*pi
cx = rad * cos(theta) + ccx; % gives slightly different data as for
cy = rad * sin(theta) + ccy; % (x-xc)^2 + (y-yc)^2 == rad^2 [2]
ccoord=[cy;cx]'; % Once again: x is for columns, y is for rows
[ccoord, rem_idx, ~] =unique(round(ccoord),'rows');
cx = ccoord(:,2);
cy = ccoord(:,1);
circ = zeros(size(img)); circ(sub2ind(size(img),cy,cx))=1;
cross_sum = 0;
figure, imshow(img | circ,'initialmagnification',5000)
hold on,
h = [];
for un_ang = 1:length(cx),
tmp_val= img(cy(un_ang),cx(un_ang));
if tmp_val == 1 %the point belongs to edge of interest
cross_sum = cross_sum + tmp_val;
h = plot(cx(un_ang),cy(un_ang),'ro');
pause,
set(h,'marker','x')
end
end
hold off
[1] https://blogs.mathworks.com/steve/2016/04/12/intersecting-curves-that-dont-intersect/
[2] http://matlab.wikia.com/wiki/FAQ#How_do_I_create_a_circle.3F

Find control points from B-Spline curve through set of data points in matlab

I'm using data set with 200 data points that is used to draw B-Spline curve and I want to extract the 100 original control points from this curve to use it in one algorithm to solve one problem. The result of control points it's too small compared with the value of the data points of B-Spline curve so I don't know if I make something wrong in the following code or not I need help to know that because I must used these control points to complete my study in one algorithm
link of set of data points:
https://drive.google.com/open?id=0B_2BUqaJptbqUkRWLWdmbmpQakk
Code :
% read data set
dataset = importdata("path of data set here");
x = dataset(:,1);
y = dataset(:,2);
for i=1:200
controlpoints(i,1) = x(i);
controlpoints(i,2) = y(i);
controlpoints(i,3) = 0;
end
% Create Q with some points from originla matrix controlpoints ( I take only 103 points)
counter =1;
for i=1:200
if (i==11) || (i==20) || (i==198)
Q(counter,:) = F(i,:);
counter = counter +1;
end
if ne(mod(i,2),0)
Q(counter,:) = F(i,:);
counter = counter+1;
end
end
I used Centripetal method to find control points from curve like the following picture
Complete my code:
% 2- Create Centripetal Nodes array from Q
CP(1) = 0;
CP(103) =1;
for i=2:102
sum = 0;
for j=2:102
sum = sum + sqrt(sqrt((Q(j,1)-Q(j-1,1))^2+(Q(j,2)-Q(j-1,2))^2));
end
CP(i) = CP(i-1) + (sqrt(sqrt((Q(i,1)-Q(i-1,1))^2+(Q(i,2)-Q(i-1,2))^2))/sum);
end
p=3; % degree
% 3- Create U_K array from CP array
for i=1:103
U_K(i) = CP(i);
end
To calculate control points we must follow this equation P=Qx(R') --> R' is inverse of R matrix so we must find R matrix then fins P(control points matrix) by the above equation. The following scenario is used to find R matrix
and to calculate N in B-Spline we must use these recursive function
Complete my code :
% 5- Calculate R_i_p matrix
for a=1:100
for b=1:100
R_i_p(a,b) = NCalculate(b,p,U_K(a),U_K);
end
end
% 6- Find inverse of R_i_p matrix
R_i_p_invers = inv(R_i_p);
% 7- Find Control points ( 100 points because we have curve with 3 degree )
for i=1:100
for k=1:100
PX(i) = R_inv(i,k) * Q(k,1);
PY(i) = R_inv(i,k) * Q(k,2);
end
end
PX2 = transpose(PX);
PY2 = transpose(PY);
P = horzcat(PX2,PY2); % The final control points you can see the values is very small compared with the original data points vlaues
My Recursive Function to find the previous R matrix:
function z = NCalculate(j,k,u,U)
if (k == 1 )
if ( (u > U(j)) && (u <= U(j+1)) )
z = 1;
else
z = 0;
end
else
z = (u-U(j)/U(j+k-1)-U(j)* NCalculate(j,k-1,u,U) ) + (U(j+k)-u/U(j+k)-U(j+1) * NCalculate(j+1,k-1,u,U));
end
end
Really I need to this help so much , I tried in this problem from one week :(
Updated:
Figure 1 for the main B-spline Curve , Figure 2 for the result control points after applied reverse engineering on this curve so the value is so far and so small compared with the original data points value
Updated(2):
I made some updates on my code but the problem now in the inverse of R matrix it gives me infinite value at all time
% 2- Create Centripetal Nodes array from Q
CP(1) = 0;
CP(100) =1;
sum = 0;
for i=2:100
sum = sum + sqrt(sqrt((Q(i,1)-Q(i-1,1))^2+(Q(i,2)-Q(i-1,2))^2));
end
for i=2:99
CP(i) = CP(i-1) + (sqrt(sqrt((Q(i,1)-Q(i-1,1))^2+(Q(i,2)-Q(i-1,2))^2))/sum);
end
% 3- Create U_K array from CP array
for i=1:100
U_K(i) = CP(i);
end
p=3;
% create Knot vector
% The first elements
for i=1:p+1
U(i) = 0;
end
% The last elements
for i=100:99+p+1
U(i) = 1;
end
% The remain elements
for j=2:96
sum = 0;
for i=j:(j+p-1)
sum = sum + U_K(i);
end
U(j+p) = (1/p)* sum;
end
% 5- Calculate R_i_p matrix
for a=1:100
for b=1:100
R_i_p(a,b) = NCalculate(b,p,U_K(a),U);
end
end
R_i_p_invers = inv(R_i_p);
% 7- Find Control points ( 100 points )
for i=1:100
for k=1:100
if isinf(R_inv(i,k))
R_inv(i,k) = 0;
end
PX(i) = R_inv(i,k) * Q(k,1);
PY(i) = R_inv(i,k) * Q(k,2);
end
end
PX2 = transpose(PX);
PY2 = transpose(PY);
P = horzcat(PX2,PY2);
Note: I updated my NCalculate recursive function to give me 0 if the result is NaN (not a number )
function z = NCalculate(j,k,u,U)
if (k == 1 )
if ( (u >= U(j)) && (u < U(j+1)) )
z = 1;
else
z = 0;
end
else
z = (u-U(j)/U(j+k-1)-U(j)* NCalculate(j,k-1,u,U) ) + (U(j+k)-u/U(j+k)-U(j+1) * NCalculate(j+1,k-1,u,U));
end
if isnan(z)
z =0;
end
end
I think there are a few dubious issues in your approach:
First of all, if you try to create a b-spline curve interpolating 103 input points (and no other boundary conditions are imposed), the b-spline curve will have 103 control points regardless what degree the b-spline curve is.
The U_K array is the parameter assigned to each input point. They are not the same as the knot sequence ti used by the Cox DeBoor recursive formula. If the b-spline curve is of degree 3, you shall have (103+3+1) knot values in the knot sequence. You can create the knot values in the following way:
0) Denote the parameters as p[i], where i = 0 to (n-1), p[0]=0.0 and n is number of points.
1) Create the knot values as
knot[0] = (p[1]+p[2]+p[3])/D (where D is degree)
knot[1] = (p[2]+p[3]+p[4])/D
knot[2] = (p[3]+p[4]+p[5])/D
......
These are the interior knot values. You should notice that p[0] and p[n-1] will not be used in this step. You will have (n-D-1) interior knots.
2) Now, add p[0] to the front of the knot values (D+1) times and add p[n-1] to the end of the knot values (D+1) times and you are done. At the end, you will have (N+D+1) knots in total.

Local Interest Point Detection using Difference of Gaussian in Matlab

I'm writing the code in Matlab to find interest point using DoG in the image.
Here is the main.m:
imTest1 = rgb2gray(imread('1.jpg'));
imTest1 = double(imTest1);
sigma = 0.6;
k = 5;
thresh = 3;
[x1,y1,r1] = DoG(k,sigma,thresh,imTest1);
%get the interest points and show it on the image with its scale
figure(1);
imshow(imTest1,[]), hold on, scatter(y1,x1,r1,'r');
And the function DoG is:
function [x,y,r] = DoG(k,sigma,thresh,imTest)
x = []; y = []; r = [];
%suppose 5 levels of gaussian blur
for i = 1:k
g{i} = fspecial('gaussian',size(imTest),i*sigma);
end
%so 4 levels of DoG
for i = 1:k-1
d{i} = imfilter(imTest,g{i+1}-g{i});
end
%compare the current pixel in the image to the surrounding pixels (26 points),if it is the maxima/minima, this pixel will be a interest point
for i = 2:k-2
for m = 2:size(imTest,1)-1
for n = 2:size(imTest,2)-1
id = 1;
compare = zeros(1,27);
for ii = i-1:i+1
for mm = m-1:m+1
for nn = n-1:n+1
compare(id) = d{ii}(mm,nn);
id = id+1;
end
end
end
compare_max = max(compare);
compare_min = min(compare);
if (compare_max == d{i}(m,n) || compare_min == d{i}(m,n))
if (compare_min < -thresh || compare_max > thresh)
x = [x;m];
y = [y;n];
r = [r;abs(d{i}(m,n))];
end
end
end
end
end
end
So there's a gaussian function and the sigma i set is 0.6. After running the code, I find the position is not correct and the scales looks almost the same for all interest points. I think my code should work but actually the result is not. Anybody know what's the problem?

Non overlapping randomly located circles

I need to generate a fixed number of non-overlapping circles located randomly. I can display circles, in this case 20, located randomly with this piece of code,
for i =1:20
x=0 + (5+5)*rand(1)
y=0 + (5+5)*rand(1)
r=0.5
circle3(x,y,r)
hold on
end
however circles overlap and I would like to avoid this. This was achieved by previous users with Mathematica https://mathematica.stackexchange.com/questions/69649/generate-nonoverlapping-random-circles , but I am using MATLAB and I would like to stick to it.
For reproducibility, this is the function, circle3, I am using to draw the circles
function h = circle3(x,y,r)
d = r*2;
px = x-r;
py = y-r;
h = rectangle('Position',[px py d d],'Curvature',[1,1]);
daspect([1,1,1])
Thank you.
you can save a list of all the previously drawn circles. After
randomizing a new circle check that it doesn't intersects the previously drawn circles.
code example:
nCircles = 20;
circles = zeros(nCircles ,2);
r = 0.5;
for i=1:nCircles
%Flag which holds true whenever a new circle was found
newCircleFound = false;
%loop iteration which runs until finding a circle which doesnt intersect with previous ones
while ~newCircleFound
x = 0 + (5+5)*rand(1);
y = 0 + (5+5)*rand(1);
%calculates distances from previous drawn circles
prevCirclesY = circles(1:i-1,1);
prevCirclesX = circles(1:i-1,2);
distFromPrevCircles = ((prevCirclesX-x).^2+(prevCirclesY-y).^2).^0.5;
%if the distance is not to small - adds the new circle to the list
if i==1 || sum(distFromPrevCircles<=2*r)==0
newCircleFound = true;
circles(i,:) = [y x];
circle3(x,y,r)
end
end
hold on
end
*notice that if the amount of circles is too big relatively to the range in which the x and y coordinates are drawn from, the loop may run infinitely.
in order to avoid it - define this range accordingly (it can be defined as a function of nCircles).
If you're happy with brute-forcing, consider this solution:
N = 60; % number of circles
r = 0.5; % radius
newpt = #() rand([1,2]) * 10; % function to generate a new candidate point
xy = newpt(); % matrix to store XY coordinates
fails = 0; % to avoid looping forever
while size(xy,1) < N
% generate new point and test distance
pt = newpt();
if all(pdist2(xy, pt) > 2*r)
xy = [xy; pt]; % add it
fails = 0; % reset failure counter
else
% increase failure counter,
fails = fails + 1;
% give up if exceeded some threshold
if fails > 1000
error('this is taking too long...');
end
end
end
% plot
plot(xy(:,1), xy(:,2), 'x'), hold on
for i=1:size(xy,1)
circle3(xy(i,1), xy(i,2), r);
end
hold off
Slightly amended code #drorco to make sure exact number of circles I want are drawn
nCircles = 20;
circles = zeros(nCircles ,2);
r = 0.5;
c=0;
for i=1:nCircles
%Flag which holds true whenever a new circle was found
newCircleFound = false;
%loop iteration which runs until finding a circle which doesnt intersect with previous ones
while ~newCircleFound & c<=nCircles
x = 0 + (5+5)*rand(1);
y = 0 + (5+5)*rand(1);
%calculates distances from previous drawn circles
prevCirclesY = circles(1:i-1,1);
prevCirclesX = circles(1:i-1,2);
distFromPrevCircles = ((prevCirclesX-x).^2+(prevCirclesY-y).^2).^0.5;
%if the distance is not to small - adds the new circle to the list
if i==1 || sum(distFromPrevCircles<=2*r)==0
newCircleFound = true;
c=c+1
circles(i,:) = [y x];
circle3(x,y,r)
end
end
hold on
end
Although this is an old post, and because I faced the same problem before I would like to share my solution, which uses anonymous functions: https://github.com/davidnsousa/mcsd/blob/master/mcsd/cells.m . This code allows to create 1, 2 or 3-D cell environments from user-defined cell radii distributions. The purpose was to create a complex environment for monte-carlo simulations of diffusion in biological tissues: https://www.mathworks.com/matlabcentral/fileexchange/67903-davidnsousa-mcsd
A simpler but less flexible version of this code would be the simple case of a 2-D environment. The following creates a space distribution of N randomly positioned and non-overlapping circles with radius R and with minimum distance D from other cells. All packed in a square region of length S.
function C = cells(N, R, D, S)
C = #(x, y, r) 0;
for n=1:N
o = randi(S-R,1,2);
while C(o(1),o(2),2 * R + D) ~= 0
o = randi(S-R,1,2);
end
f = #(x, y) sqrt ((x - o(1)) ^ 2 + (y - o(2)) ^ 2);
c = #(x, y, r) f(x, y) .* (f(x, y) < r);
C = #(x, y, r) + C(x, y, r) + c(x, y, r);
end
C = #(x, y) + C(x, y, R);
end
where the return C is the combined anonymous functions of all circles. Although it is a brute force solution it is fast and elegant, I believe.

Matlab figure keeps the history of the previous images

I am working on rotating image manually in Matlab. Each time I run my code with a different image the previous images which are rotated are shown in the Figure. I couldn't figure it out. Any help would be appreciable.
The code is here:
[screenshot]
im1 = imread('gradient.jpg');
[h, w, p] = size(im1);
theta = pi/12;
hh = round( h*cos(theta) + w*abs(sin(theta))); %Round to nearest integer
ww = round( w*cos(theta) + h*abs(sin(theta))); %Round to nearest integer
R = [cos(theta) -sin(theta); sin(theta) cos(theta)];
T = [w/2; h/2];
RT = [inv(R) T; 0 0 1];
for z = 1:p
for x = 1:ww
for y = 1:hh
% Using matrix multiplication
i = zeros(3,1);
i = RT*[x-ww/2; y-hh/2; 1];
%% Nearest Neighbour
i = round(i);
if i(1)>0 && i(2)>0 && i(1)<=w && i(2)<=h
im2(y,x,z) = im1(i(2),i(1),z);
end
end
end
end
x=1:ww;
y=1:hh;
[X, Y] = meshgrid(x,y); % Generate X and Y arrays for 3-D plots
orig_pos = [X(:)' ; Y(:)' ; ones(1,numel(X))]; % Number of elements in array or subscripted array expression
orig_pos_2 = [X(:)'-(ww/2) ; Y(:)'-(hh/2) ; ones(1,numel(X))];
new_pos = round(RT*orig_pos_2); % Round to nearest neighbour
% Check if new positions fall from map:
valid_pos = new_pos(1,:)>=1 & new_pos(1,:)<=w & new_pos(2,:)>=1 & new_pos(2,:)<=h;
orig_pos = orig_pos(:,valid_pos);
new_pos = new_pos(:,valid_pos);
siz = size(im1);
siz2 = size(im2);
% Expand the 2D indices to include the third dimension.
ind_orig_pos = sub2ind(siz2,orig_pos(2*ones(p,1),:),orig_pos(ones(p,1),:), (1:p)'*ones(1,length(orig_pos)));
ind_new_pos = sub2ind(siz, new_pos(2*ones(p,1),:), new_pos(ones(p,1),:), (1:p)'*ones(1,length(new_pos)));
im2(ind_orig_pos) = im1(ind_new_pos);
imshow(im2);
There is a problem with the initialization of im2, or rather, the lack of it. im2 is created in the section shown below:
if i(1)>0 && i(2)>0 && i(1)<=w && i(2)<=h
im2(y,x,z) = im1(i(2),i(1),z);
end
If im2 exists before this code is run and its width or height is larger than the image you are generating the new image will only overwrite the top left corner of your existing im2. Try initializing im2 by adding adding
im2 = zeros(hh, ww, p);
before
for z = 1:p
for x = 1:ww
for y = 1:hh
...
As a bonus it might make your code a little faster since Matlab won't have to resize im2 as it grows in the loop.