shape context matching technique - matlab

I'm trying to implement shape context matching algorithm which is
Calculate the distance of a point to all other points.
Normalize the distance by mean distance.
Create logarithmic distance scale for normalized distances.
Create distance histogram: Iterate for each scale incrementing bins when
bins with higher numbers describe points closer together.
Calculate angle between all points.
Bin angles which is slightly different than distance.
Matching - Cost Matrix: Calculate cost of matching each point to every
other point.
Matching - Additional Cost Terms:
Surrounding Texture Difference,
Tangent Angle Difference.
Matching: Find pairing of points that leads to least total cost according
to equation 3
I'm now in step 3, and I don't know how to calculate log distance scale
Example:
if we have coordinates in shape as:
0.2000 0.5000
0.4000 0.5000
0.3000 0.4000
0.1500 0.3000
0.3000 0.2000
0.4500 0.3000
step(1): Euclidean distance from each point to all others:
0 0.2000 0.1414 0.2062 0.3162 0.3202
0.2000 0 0.1414 0.3202 0.3162 0.2062
0.1414 0.1414 0 0.1803 0.2000 0.1803
0.2062 0.3202 0.1803 0 0.1803 0.3000
0.3162 0.3162 0.2000 0.1803 0 0.1803
0.3202 0.2062 0.1803 0.3000 0.1803 0
step(2):Normalized distances between each point:
0 1.0623 0.7511 1.0949 1.6796 1.7004
1.0623 0 0.7511 1.7004 1.6796 1.0949
0.7511 0.75110 0.9575 1.0623 0.9575
1.0949 1.7004 0.9575 0 0.9575 1.5934
1.6796 1.6796 1.0623 0.9575 0 0.9575
1.7004 1.0949 0.9575 1.5934 0.9575 0
I don't know how to create log distance scale where
The log distance scale for normalized distances (closer = more discriminate):
0.1250 0.2500 0.5000 1.0000 2.0000
Any one help me?

I have no background in shape context, and here's my thinking:
The teacher wants to measure the distance in a way that fits the need by shape context. To achieve this,
(step 3) First build a scale (aka a ruler). The scale has 5 bins, namely 0~0.1250, 0.1250~0.2500, 0.2500~0.5000, 0.5000~1.0000, 1.0000~2.0000. The maximum range should cover the maximum value in your data of normalized distance (1.7004 here). This scale is increasing logarithmically (I mean "exponentially"). I still have no idea about "closer = more discriminate".
(step 4) throw each data value into different bins, using the scale. The teacher uses iteration method, which works; but essentially you just need to find some way to categorize the values.
I think you can also achieve it in this way:
>> x = rand(1,10)*2;ceil(log2(ceil(x/.125)))+1,x
ans =
2 1 5 5 5 3 5 4 1 4
x =
0.1517 0.1079 1.0616 1.5583 1.8680 0.2598 1.1376 0.9388 0.0238 0.6742
So you are finding logarithm of distance to base 0.125.

Related

MATLAB fitcsvm svm boundary equation does not separate data

I am trying to classify binary data using fitcsvm, but when I plot the boundry equation, it does not sit close to the data.
Here is the code that I used to generate the model
Theme
%creating inputs for the model
xTable = [responseData_Intensity.Intensity responseData_Intensity.ActiveForce_kg_];
y = responseData_Intensity.FeltSVM;
%-------------------------------------------------------SVM MODEL
SVMModel = fitcsvm(xTable,y);
%------------------------------------------PLOTTING THE MODEL WITH DATA
figureSVM = figure;
hold on
figTitle = strcat(participantList(participantNumber),'-',parameter,'-Maximal Margin Line');
title(figTitle);
in = responseData_Intensity.Intensity; fr = responseData_Intensity.ActiveForce_Kg_;
gscatter(in,fr,responseData_Intensity.FeltSVM,'rb');
syms x
eqn = slope*x+yIntercept == 0;
xIntercept = double(solve(eqn)); % X values where y=0
xlabel('Inensity Tested');
ylabel('Force (kg)');
plot(in(SVMModel.IsSupportVector), fr(SVMModel.IsSupportVector), 'ko', 'MarkerSize',10);
plot(in, -SVMModel.Beta(1)/SVMModel.Beta(2)*in - (SVMModel.Bias)/SVMModel.Beta(2))
legend('Not Felt','Felt','Support Vector','Classifier');
These are the values for
xTable and y
xTable =
0.5000 0.5500
0.4000 0.6167
0.3000 0.4000
0.2000 0.3500
0.1000 0.6833
0.2000 0.6333
0.1000 0.4833
0 0.6500
0.5000 0.6167
0.4000 0.5333
0.3000 0.7333
0.2000 0.7000
0.1000 0.7000
0.2000 0.6833
0.1000 0.7833
0.1000 0.6500
0.2000 0.6333
0.1000 0.8167
0 1.1333
0 0.8500
y =
1
1
1
1
-1
1
-1
-1
1
1
1
1
-1
1
1
-1
1
-1
1
1
and the resulting plot
which seems off because it is so far removed from the data and the support vectors. The zoomed in data is here:
From all the other example I've seen the line should divide the data in between the two identifiers? I may be getting some things mixed up, so any help would be very much appreciated!
Figured out the answer, I needed to normalize the data, once that is done the boundary equation separatest the data nicely!

Distance Transform Behaviors Differently Between Matlab and OpenCV

I am currently translating code from Matlab to OpenCV but found the distance transform function behaviors differently between Matlab and OpenCV.
Take the simple matrix as an example
bw =
0 0 0 0 0
0 1 0 0 0
0 0 0 0 0
0 0 0 1 0
0 0 0 0 0
Matlab version distance transform assigns a number that is the distance between that pixel and the nearest nonzero pixel of BW, which makes sense and I got
1.4142 1.0000 1.4142 2.2361 3.1623
1.0000 0 1.0000 2.0000 2.2361
1.4142 1.0000 1.4142 1.0000 1.4142
2.2361 2.0000 1.0000 0 1.0000
3.1623 2.2361 1.4142 1.0000 1.4142
In OpenCV, I choose the DIST_L2 (the simple euclidean distance). it gives me
1.3692 0.9550 1.3692 2.3242 3.2792
0.9550 0 0.9550 1.9100 2.3242
1.3692 0.9550 1.3692 2.3242 1.3692
2.3242 1.9100 0.9550 0 0.9550
3.2792 2.3242 1.3692 0.9550 1.3692
I don't understand why and it doesn't make sense to me. I realized that OpenCV compute the pixel with nearest zero pixel, so I already inverted the input matrix.
maskSize – Size of the distance transform mask. It can be 3, 5, or CV_DIST_MASK_PRECISE (the latter option is only supported by the first function).
It looks like OpenCV version distance transform is doing some normalization using maskSize. Set it to 0 (Even the documentation didn't mention it) and it solves the issue.

Loglog plot with linear ticks on x-axis

So I have this data I'd like plotted on loglog scale, with linear values on the y-axis and the values in dB on the x axis and
loglog(EbN0,BER)
outputs a nice looking curve, but the problem is the axis ticks. It's fine on the y-axis, but the x axis only has one tick, at 10^0and no other ticks. Furthermore, that tick corresponds to the absolute value, not the dB value. Any convenient way to accomplish this?
(Note that both EbN0 and BER contain absolute values)
EDIT: I'll add my data and explain what I want a bit more.
EbN0 =
Columns 1 through 14
0.5000 1.0000 1.5000 2.0000 2.5000 3.0000 3.5000 4.0000 4.5000 5.0000 5.5000 6.0000 6.5000 7.0000
Columns 15 through 20
7.5000 8.0000 8.5000 9.0000 9.5000 10.0000
BER_TOT_ITER =
Columns 1 through 14
0.2928 0.2024 0.1183 0.0511 0.0164 0.0046 0.0010 0.0003 0.0001 0 0.0000 0.0000 0.0000 0
Columns 15 through 20
0 0 0 0 0 0
If I do plot(10*log10(EbN0),10*log10(BER_TOT_ITER)), I actually get exactly the graph I want and the dB values on the x axis, but now the y ticks are displayed in dB's instead of absolute values... so I just want to relabel the y ticks, NOT rescale the figure.
Relabeling the ticks is really the wrong approach here. You'd replace numerical values with strings and resizing etc. wouldn't work anymore.
Also your data does not fit to what you're actually looking at.
You should always try to transform your data first.
So besides loglog have a look at semilogx and semilogy, which allow you to have a single logarithmic axis.
To sum up, what you're looking for is:
semilogy(10*log10(EbN0), BER_TOT_ITER)

getting x,y coordinates from a plotted graph and get the intersection with an other graph

I'm some kind of new to matlab,so the question may be elementary. I try to get the [x,y] coordinates of the points on a plotted graph in matlab.
The graph is simple. I already had the coordinates of some points (xb,yb), and plotted the graph using line(xb, yb).
Now I need to find the coordinates of all the points on the plotted lines in order to get the intersection points of these lines with another defined graph.
the code which i used is:
line(Xb,Yb)
hold on
X=min(Xb):.001:max(Xb);
y=0.03;
plot(X,y);
The Xb and Yb are 1*38 arrays, and shape the boundary of a region in real problem which I'm studying. But I don't have all the x, Y of the points on the boundary. I need to the intersection coordinates of the boundary with horizontal line which is plotted by plot(X,y).
The Xb and Yb are:
Xb = [-0.0400 -0.0550 -0.0700 -0.0850 -0.1000 -0.1000 -0.1000 -0.1000 -0.1000 -0.1000 -0.0800 -0.0600 -0.0400 -0.0200 0 0.0200 0.0400 0.0600 0.0800 0.1000 0.1000 0.1000 0.1000 0.1000 0.1000 0.0850 0.0700 0.0550 0.0400 0.0380 0.0324 0.0235 0.0124 0 -0.0124 -0.0235 -0.0324 -0.0380 -0.0400 ];'
Yb = [0 0 0 0 0 0.0200 0.0400 0.0600 0.0800 0.1000 0.1000 0.1000 0.1000 0.1000 0.1000 0.1000 0.1000 0.1000 0.1000 0.1000 0.0800 0.0600 0.0400 0.0200 0 0 0 0 0 0.0124 0.0235 0.0324 0.0380 0.0400 0.0380 0.0324 0.0235 0.0124 0];'
thank you very much from your kind help.
If your functions are given as arrays x1,y1 and x2,y2, then you can find their crossing using their linear interpolators:
%dummy input
x1=[0 1 2 3];
y1=[1 4 2 0];
x2=[-1 3 4 5];
y2=[-1 2 5 3];
x0 = (max(min(x1),min(x2))+min(max(x1),max(x2)))/2;
fun1 = #(x) interp1(x1,y1,x,'linear');
fun2 = #(x) interp1(x2,y2,x,'linear');
difffun = #(x) fun1(x)-fun2(x);
crossing = fzero(difffun,x0);
where your x0 should be fairly close to the actual crossing point, I chose a point inside both of your intervals. The anonymous functions fun1 and fun2 create a callable function using interp1, which can only tell you the interpolant at specific x coordinates. If you have the Curve Fitting Toolbox, you can get a function in a single step using fit. Then difffun is a function given by the difference of the two input functions, the zero(s) of which will give you the crossing of the two functions. fzero will do just that: find a zero of a function from a given starting point.
You can run into troubles if the starting x0 is way off, and in case of multiple zeros you will only find one at a time. In your case, the interpolating functions are not too well-behaved, so choosing a right x0 (probably manually setting a value) is paramount.
Results with the dummy input above:
output:
crossing =
2.272727272727273

Assigning Different Colors to a Plot / Scatter

So I have a vector called C1_Vector that has been previously filled with different shades of 1 RGB color ([0 0.5 1]), blue. So there are many different vectors within the C1_Vector
ex:
C1_Vector = ([0 0.5 1], [0 0.45 0.98], [0 0.49 1.01], etc.)
I want to each one of my points, in s1, to correspond to a different color. This is what I've been playing around with, and struggling with. Can someone help me with this syntax?
plot(s1(1,:),s1(2,:),'.', 'color', C1_Vector );
where,
s1 =
3.0000 3.0000 3.0000 1.5000 1.5000 1.5000 0 -1.5000
1.5000 0 -1.5000 1.5000 0 -1.5000 0 3.0000
Using the scatter function makes it quite easy as long as you provide the same number of color vectors than element to plot.
Basically for each pair of points to display the function assign it the corresponding color in the color matrix provided, which is M x 3 where M is the number of points.
Therefore for the demo I added colors to C1_Vector so that it contains as many elements as s1.
C1_Vector = [0 0.5 1; 0 0.45 0.98; 0 0.49 1.01;1 0 1; rand(1,3); 0 1 0; 0 1 1;rand(1,3)];
s1 = [3.0000 3.0000 3.0000 1.5000 1.5000 1.5000 0 -1.5000;
1.5000 0 -1.5000 1.5000 0 -1.5000 0 3.0000];
scatter(s1(1,:),s1(2,:),[],C1_Vector,'filled')
grid on
Output:
Is that what you meant?