How make endpoints of bwboundaries consistent in Matlab? - matlab

I have an image with 2 edges
if I then plot the boundary of the edges with the code below:
imshow(I); hold on; [B,L,N] = bwboundaries(I);
for k=1:length(B),
boundary = B{k};
BL=size(boundary);
plot(boundary(1,2), boundary(1,1), '*g','MarkerSize',15);
for j=1:10:BL(1)
plot(boundary(j,2), boundary(j,1), '.r','MarkerSize',5);
end
end
As seen in the image above, the starting point (the green star) for the left edge is at the left side of the image, which is what I expected. However, the starting point for the right edge is towards the middle
Apparently this is because bwboundaries deals with tracing objects in clockwise direction, whereas the 2nd edge needs to be traced counterclockwise for it to begin and end on the right boundary of the image
How can Matlab be able to take the positions from bwboundaries and correctly determine the endpoints for the edge on the right?

Not a complete answer to your problem, but an idea I came up with. You can check all points of a boundary for their "closeness" to an image border, and then find minimum/maximum (x, y) values, that'll describe those "ends" you're interested in.
B = bwboundaries(img);
% Threshold for "closeness" to an image border.
thrNear = 5;
for k = 1:numel(B)
b = B{k};
nearTop = b(:, 1) < thrNear;
nearBottom = b(:, 1) > (size(img, 1) - thrNear);
nearLeft = b(:, 2) < thrNear;
nearRight = b(:, 2) > (size(img, 2) - thrNear);
closeToTop = b(nearTop, :)
closeToBottom = b(nearBottom, :)
closeToLeft = b(nearLeft, :)
closeToRight = b(nearRight, :)
end
For example, for the right shape in your original image, you get:
closeToTop = [](0x2)
closeToBottom = [](0x2)
closeToLeft = [](0x2)
closeToRight =
79 283
79 284
79 285
79 286
79 287
80 287
81 287
81 286
81 285
81 284
81 283
215 283
215 284
215 285
215 286
215 287
216 287
217 287
217 286
217 285
217 284
217 283
Now, go for the maximum x value(s) (287), and find appropriate (non-neighbouring) y values (79-81 vs. 215-217). Repeat that for each image border.
I hope, you get my idea. To be honest, I don't want to implement that entirely, but don't hesitate to ask, if my description is not precise enough.

Related

How to improve the distance calculation on two separated datasets in matlab?

How to improve the distance calculation on the 2 separated datasets?
This is the code:
X = [ 3.6 79
1.8 54
3.333 74
2.283 62
4.533 85
2.883 55
4.7 88
3.6 85
1.95 51
4.35 85
1.833 54
3.917 84
4.2 78
1.75 47
4.7 83
2.167 52
1.75 62
4.8 84
1.6 52
4.25 79
1.8 51
1.75 47
3.45 78
3.067 69
4.533 74
3.6 83
1.967 55
4.083 76
3.85 78
4.433 79
4.3 73
4.467 77
3.367 66
4.033 80
3.833 74
2.017 52
1.867 48
4.833 80
1.833 59
4.783 90 ]
clc;
close all;
figure;
h(1) = plot(X(:,1),X(:,2),'bx');
hold on;
X1 = X(1:3,:);
X2 = X(4:40,:);
h(2) = plot(X1(1:3,1), X1(1:3,2),'rs','MarkerSize',10);
k=5;
[D2 ind] = sort(squeeze(sqrt(sum(bsxfun(#minus,X2,permute(X1,[3 2 1])).^2,2))))
ind_closest = ind(1:k,:)
x_closest = X(ind_closest,:)
for j = 1:length(x_closest);
h(3) =plot(x_closest(j,1),x_closest(j,2),'ko','MarkerSize',10);
end
The output is shown as in the picture below:
The problem is, the code does not pick the closest data points of red squared data points. I also tried to use pdist2 function from statistical toolbox,the result yields similar with the bsxfun function that i applied in my code.
I'm not sure which part in the code need to improve so that i can pick the data points that closest to the target.
Really appreciate if anyone can help me to improve my code
If the closest point means closest to X, line 19 & line 20 should be replaced as
[D2 ind] = sort(squeeze(sqrt(sum(bsxfun(#minus,X,permute(X1,[3 2 1])).^2,2))))
ind_closest = ind(2:k+1,:)
If the closest point means closest to X2, then try this:
x_closest = X2(ind_closest,:)
In the meanwhile, I modified your code a little bit, since your h(3) could be optimized.
clc; clear; close all;
%load fisheriris
%X=meas(:,3:4);
load X
X=unique(X,'rows');
figure;
h(1) = plot(X(:,1),X(:,2),'bx');
hold on;
X1 = X([5 15 30],:);
h(2) = plot(X1(:,1), X1(:,2),'rs','MarkerSize',10);
[D2,ind] = sort(squeeze(sqrt(sum(bsxfun(#minus,X,permute(X1,[3 2 1])).^2,2))));
k=3;
ind_closest = unique(ind(2:k+1,:));
x_closest = X(ind_closest,:);
h(3) =plot(x_closest(:,1),x_closest(:,2),'ko','MarkerSize',10);
axis equal
It seems to be working fine.

Kalman Filter implementation for one dimensional vector

I am having an hard time figuring out something really stupid I think.
I want to refresh my kalman filter knowledge but I am not able to make it work.
In a simple case with
real states x:
x = [ 1000 750 563 422 316 237 178 133 100 75]';
and observations
z_array = [ 1056 943 469 235 433 230 116 136 -75 267]';
I get something really nice (estimated stands for FILTERED):
When instead I use another signal, more complex. I don't know why but it doesn't work (estimated stands for FILTERED).
The problem, I am quite sure is in how I choose the a and r in my code for the second case. But how can I change them?
Here is the short code I have written in MATLAB and I am getting lost (I am really ashamed because I should know how to do this!!).
close all
z_array = noisyMeas.signals.values;
x = meas.signals.values;
a = 0.75;
r= 200;
p=1;
% x = [ 1000 750 563 422 316 237 178 133 100 75]';
% z_array = [ 1056 943 469 235 433 230 116 136 -75 267]';
xhat_array = zeros(length(z_array),1);
xhat = z_array(1);
xhat_array(1) = xhat;
% Core of the Kalman Filter
for k=2:length(x)
z = z_array(k);
% Predict
xhat = a * xhat;
p = a * p * a;
% Update
g = p / (p + r);
xhat = xhat + g * (z - xhat);
p = (1 - g) * p;
xhat_array(k) = xhat;
end
% plotting
figure
hold on
plot(xhat_array,'r')
plot(x,'b');
plot(z_array,'g')
grid on
legend('estimated','notNoisy','Noisy')
Thanks in advance for your help.

Conditional coloring of histogram graph in MATLAB

I have a histogram that I want conditional coloring in it with this rule :
Values that are upper than 50 have red bars and values lower than 50 have blue bars.
Suppose that we have this input matrix:
X = [32 64 32 12 56 76 65 44 89 87 78 56 96 90 86 95 100 65];
I want default bins of MATLAB and applying this coloring on X-axes (bins). I'm using GUIDE to design my GUI and this histogram is an axes in my GUI.
This is our normal graph. Bars with upper values than 50 should be red and bars with lower values than 50 should be green (X-axes). Bars with upper values than 50 should be red and ?
I think this does what you want (as per comments). The bar around 50 is split into the two colors. This is done by using a patch to change the color of part of that bar.
%// Data:
X = [32 64 32 12 56 76 65 44 89 87 78 56 96 90 86 95 100 65]; %// data values
D = 50; %// where to divide into two colors
%// Histogram plot:
[y n] = hist(X); %// y: values; n: bin centers
ind = n>50; %// bin centers: greater or smaller than D?
bar(n(ind), y(ind), 1, 'r'); %// for greater: use red
hold on %// keep graph, Or use hold(your_axis_handle, 'on')
bar(n(~ind), y(~ind), 1, 'b'); %// for smaller: use blue
[~, nd] = min(abs(n-D)); %// locate bar around D: it needs the two colors
patch([(n(nd-1)+n(nd))/2 D D (n(nd-1)+n(nd))/2], [0 0 y(nd) y(nd)], 'b');
%// take care of that bar with a suitable patch
X = [32 64 32 12 56 76 65 44 89 87 78 56 96 90 86 95 100 65];
then you create an histogram, but you are only going to use this to get the numbers of bins, the numbers of elements and positions:
[N,XX]=hist(X);
close all
and finally here is the code where you use the Number of elements (N) and the position (XX) of the previous hist and color them
figure;
hold on;
width=8;
for i=1:length(N)
h = bar(XX(i), N(i),8);
if XX(i)>50
col = 'r';
else
col = 'b';
end
set(h, 'FaceColor', col)
end
here you can consider using more than one if and then you can set multiple colors
cheers
First sort X:
X = [32 64 32 12 56 76 65 44 89 87 78 56 96 90 86 95 100 65];
sorted_X = sort(X)
sorted_X :
sorted_X =
Columns 1 through 14
12 32 32 44 56 56 64 65 65 76 78 86 87 89
Columns 15 through 18
90 95 96 100
Then split the data based on 50:
idx1 = find(sorted_X<=50,1,'last');
A = sorted_X(1:idx1);
B = sorted_X(idx1+1:end);
Display it as two different histograms.
hist(A);
hold on;
hist(B);
h = findobj(gca,’Type’,’patch’);
display(h)
set(h(1),’FaceColor’,’g’,’EdgeColor’,’k’);
set(h(2),’FaceColor’,’r’,’EdgeColor’,’k’);

Matlab : How I can creat a polynomial generator Reed Solomon for QR Code

I have to make a matlab program, which should create a QR Code.
My problem is the Reed Solomon error correction
The user enters the word he wants. [...] I got a string of numbers I should be gone in a polynomial generator (Reed Solomon) (I found some sites that do this very well: http://www.pclviewer.com/rs2/calculator.html)
I would like it to happen: for example I input: 32 91 11 120 209 114 220 77 67 64 236 17 236
[Reed Solomon generator polynomial]
and I want to find out: 168 72 22 82 217 54 156 0 46 15 180 122 16
I found the functions rsenc comm.rsencoder gf ... But it is impossible to understand the operation of these functions. Functions are detailed: http://www.mathworks.fr/fr/help/comm...n.html#fp12225
I tried a code of this type :
n = 255; k = 13; % Codeword length and message length
m = 8; % Number of bits in each symbol
msg = [32 91 11 120 209 114 220 77 67 64 236 17 236]; % Message is a Galois array.
obj = comm.RSEncoder(n, k);
c1 = step(obj, msg(1,:)');
c = [c1].';
He produced a string of 255 while I want 13 output.
Thank you for your help.
I think that you are committing a mistake.
'n' is the length of final message with parity code.
'k' is the lenght of message (number of symbols)
I guess that this will help you:
clc, clear all;
M = 16; % Modulation Order || same that Max value, at your case: 256! 2^m
hEnc = comm.RSEncoder;
hEnc.CodewordLength = M - 1; % Max = M-1, Min = 4, Must be greater than MessageLenght
hEnc.MessageLength = 13; % Experiment change up and down value (using odd number)
hEnc.BitInput = false;
hEnc
t = hEnc.CodewordLength - hEnc.MessageLength;
frame = 2*hEnc.MessageLength; % multiple of MensagemLength
fprintf('\tError Detection (in Symbols): %d\n',t);
fprintf('\tError Correction: %.2f\n',t/2);
data = randi([0 M-1], frame, 1); % Create a frame with symbols range (0 to M-1)
encodedData = step(hEnc, data); % encod the frame

Contour plot coloured by clustering of points matlab

I have two vectors which are paired values
size(X)=1e4 x 1; size(Y)=1e4 x 1
Is it possible to plot a contour plot of some sort making the contours by the highest density of points? Ie highest clustering=red, and then gradient colour elsewhere?
If you need more clarification please ask.
Regards,
EXAMPLE DATA:
X=[53 58 62 56 72 63 65 57 52 56 52 70 54 54 59 58 71 66 55 56];
Y=[40 33 35 37 33 36 32 36 35 33 41 35 37 31 40 41 34 33 34 37 ];
scatter(X,Y,'ro');
Thank you for everyone's help. Also remembered we can use hist3:
x={0:0.38/4:0.38}; % # How many bins in x direction
y={0:0.65/7:0.65}; % # How many bins in y direction
ncount=hist3([X Y],'Edges',[x y]);
pcolor(ncount./sum(sum(ncount)));
colorbar
Anyone know why edges in hist3 have to be cells?
This is basically a question about estimating the probability density function generating your data and then visualizing it in a good and meaningful way I'd say. To that end, I would recommend using a more smooth estimate than the histogram, for instance Parzen windowing (a generalization of the histogram method).
In my code below, I have used your example dataset, and estimated the probability density in a grid set up by the range of your data. You here have 3 variables you need to adjust to use on your original data; Borders, Sigma and stepSize.
Border = 5;
Sigma = 5;
stepSize = 1;
X=[53 58 62 56 72 63 65 57 52 56 52 70 54 54 59 58 71 66 55 56];
Y=[40 33 35 37 33 36 32 36 35 33 41 35 37 31 40 41 34 33 34 37 ];
D = [X' Y'];
N = length(X);
Xrange = [min(X)-Border max(X)+Border];
Yrange = [min(Y)-Border max(Y)+Border];
%Setup coordinate grid
[XX YY] = meshgrid(Xrange(1):stepSize:Xrange(2), Yrange(1):stepSize:Yrange(2));
YY = flipud(YY);
%Parzen parameters and function handle
pf1 = #(C1,C2) (1/N)*(1/((2*pi)*Sigma^2)).*...
exp(-( (C1(1)-C2(1))^2+ (C1(2)-C2(2))^2)/(2*Sigma^2));
PPDF1 = zeros(size(XX));
%Populate coordinate surface
[R C] = size(PPDF1);
NN = length(D);
for c=1:C
for r=1:R
for d=1:N
PPDF1(r,c) = PPDF1(r,c) + ...
pf1([XX(1,c) YY(r,1)],[D(d,1) D(d,2)]);
end
end
end
%Normalize data
m1 = max(PPDF1(:));
PPDF1 = PPDF1 / m1;
%Set up visualization
set(0,'defaulttextinterpreter','latex','DefaultAxesFontSize',20)
fig = figure(1);clf
stem3(D(:,1),D(:,2),zeros(N,1),'b.');
hold on;
%Add PDF estimates to figure
s1 = surfc(XX,YY,PPDF1);shading interp;alpha(s1,'color');
sub1=gca;
view(2)
axis([Xrange(1) Xrange(2) Yrange(1) Yrange(2)])
Note, this visualization is actually 3-dimensional:
See this 4 minute video on the mathworks site:
http://blogs.mathworks.com/videos/2010/01/22/advanced-making-a-2d-or-3d-histogram-to-visualize-data-density/
I believe this should provide very close to exactly the functionality you require.
I would divide the area the plot covers into a grid and then count the number of points in each square of the grid. Here's an example of how that could be done.
% Get random data with high density
X=randn(1e4,1);
Y=randn(1e4,1);
Xmin=min(X);
Xmax=max(X);
Ymin=min(Y);
Ymax=max(Y);
% guess of grid size, could be divided into nx and ny
n=floor((length(X))^0.25);
% Create x and y-axis
x=linspace(Xmin,Xmax,n);
y=linspace(Ymin,Ymax,n);
dx=x(2)-x(1);
dy=y(2)-y(1);
griddata=zeros(n);
for i=1:length(X)
% Calculate which bin the point is positioned in
indexX=floor((X(i)-Xmin)/dx)+1;
indexY=floor((Y(i)-Ymin)/dy)+1;
griddata(indexX,indexY)=griddata(indexX,indexY)+1;
end
contourf(x,y,griddata)
Edit: The video in the answer by Marm0t uses the same technique but probably explains it in a better way.