I am trying to find points left side of the reference line. I have already stored the required points in a separate array and used both
'desearchn' and 'rangesearch' and 'knnsearch' matlab methods. They all works with 80% efficiency but if the "left side" points are further they tend to pick the "right side" points instead of the left side points from the reference line. My code and data are given below:
close all
load data.mat
%Convert Beg_Ex and Beg_In into realtime values
Beg_Ex1 = Time(Beg_Ex);
Beg_In1 = Time(Beg_In);
% Find the distance from Beg_Ex to Block1
Beg = Block1(:,1);
End_Cycle11 = dsearchn(Beg_Ex1',Beg);
End_Cycle1 = Beg_Ex1(End_Cycle11); % Expiration Cycle
% First Half Cycle - Pre Apnea
Start_Stop1 = [End_Cycle1' Beg];
% Find the distance from Beg_In to EndCycle1
End_Cycle22 = dsearchn(Beg_In1',End_Cycle1');
End_Cycle2 = Beg_In1(End_Cycle22); %Inspiration Cycle
% Second Half Cycle - Pre Apnea
Start_Stop2 = [End_Cycle2' End_Cycle1'];
plot(Time,Flow,'b');
hold on;
plot(Time(Beg_Ex),Flow(Beg_Ex),'ro','MarkerFaceColor','r','MarkerSize',10)
hold on;
plot(Time(Beg_In),Flow(Beg_In),'go','MarkerFaceColor','g','MarkerSize',10)
grid on
title('Flow')
xlabel('time [s]')
ylabel('flow [a.u.]')
% legend({'flow' 'begIn' 'begExp' })
vfill( Start_Stop1,'r','facealpha',.6,'edgecolor','k','linestyle',':');
hold on;
vfill( Start_Stop2,'y','facealpha',.6,'edgecolor','k','linestyle',':');
https://www.dropbox.com/s/c0ilkd3jkrzy0vq/data.mat?dl=0
I use vfill function for here
https://au.mathworks.com/matlabcentral/fileexchange/43090-hfill-and-vfill
As you can see in the image i am expected get yellow and red patches in the order but in few cases they are overlapped this is due to search points detected on the right side instead of the left side. Any help/suggestions are highly appreciated.
Related
So I want to smooth out Sharkfin signal at the point where it goes down and at the point where it goes up. As shown in the figure below, the Sharkfin waveform has sharp fall and rise at time 2 sec and 4 seconds:
Any idea on how to round of that area so that it is smooth in that section so that it looks something like this:
There are two separate things here - how do you detect a sharp transition, and how do you filter it.
Let's take these in turn.
A sharp transition is characterized by a large curvature - we can easily detect this by taking the diff of the input curve. Using the second parameter = 2 takes diff twice and results in something "like" the second derivative - but it's offset by one. So when we find points where the diff(sharkfin,2) is large, we need to offset by 1 to get the corner points.
Next, the smoothing itself. There are many techniques - I show a simple convolution with a box function. Doing this twice gives a smoothed version of the input. By picking the original "far from the discontinuity" and the filtered version "close to the discontinuity" we get exactly what you were asking for. If you wanted, you could "blend" the points - using a weighted version of filtered and unfiltered depending on how close you were to the corner points. I didn't show that explicitly but it should be easy to see how to expand the code I already wrote:
% generate a "shark fin" function:
fin = exp(-linspace(0,4,60));
shark = [fin (1-fin+fin(end))];
shark = repmat(shark, [1 3]);
D2 = diff(shark, 2);
roundMe = find(abs(D2)>0.1*max(D2))+1; % offset by 1 because second derivative
figure;
subplot(3,1,1)
plot(shark); title 'shark plot'
hold on;
plot(roundMe, shark(roundMe),'r*')
legend('input','corners found')
% take N points on either side of the sharp corners:
N = 3;
% boxplot filtered version of the curve
boxFilt = ones(1, 2*N+1)/(2*N+1);
smoothShark1 = convn(shark, boxFilt, 'same'); % box plot
% second filter - smoother
smoothShark2 = convn(smoothShark1, boxFilt, 'same');
% plot the filtered results:
subplot(3,1,2)
plot(shark)
hold on
plot(smoothShark1);
hold on
plot(smoothShark2);
xlim([114 126])
ylim([0.8,1.1])
legend('original','box','box x2')
title 'smoothed everywhere'
% Now apply filtering only to points near the discontinuity
smoothMe = zeros(size(shark));
smoothMe(roundMe)=1;
smoothMe = convn(smoothMe, boxFilt, 'same');
smoothMe(smoothMe>0)=1; % this finds N points on either side of the corner
subplot(3,1,3)
plot(shark)
finalPlot=shark;
hold on
smoothIndx = find(smoothMe);
finalPlot(smoothIndx)=smoothShark2(smoothIndx);
plot(finalPlot,'g')
plot(smoothIndx, finalPlot(smoothIndx), 'r*')
xlim([114 126])
ylim([0.8,1.1])
legend('original','smoothed','changed')
title 'smoothed only near discontinuity'
Output:
I have a fairly simple question. I am trying to segment an image using MATLAB. I have tried the imageSegmenter app, a toolbox with GUI. The tool seems to be working perfectly, especially when I use the "Flood Fill" option with almost any tolerance parameter.
Is there a function (not a tool) form of the flood fill? If yes, what is the name of the function? The documentation seems not be including this information.
The function grayconnected(I,row,column,tolerance) does, what the Flood-Fill-Tool in the imageSegmeter-Toolbox does: Initialize with a point [x,y] (column-/row-index in the image) and starting from there "flood" surrounding pixels within a given gray value range specified by the tolerance parameter (top-left in the Flood Fill GUI).
Actually you only need that one line (if you have your gray-valued img, an initialization point row,column and picked a tolerance, e.g. 12):
%>>> this is where the magic happens <<<%
segmentation = grayconnected(img, row, column, 12);
For convenience though see below a code snippet with visualization, where you may select your initialization. Input is a colored image (if it's already gray, skip rgb2gray). Output (a segmentation mask) corresponding to each point i is in segmentations(:,:,i). You may merge these single segmentation masks to one or assign them to different objects.
Note that this is really a very basic segmentation method, prone to noise and bad if you don't have a clear contrast (where a single threshold operation might already give you good results without initialization). You can use this initial segmentation to be refined, e.g. with active contours.
[img] = imread('test.jpg');
img = rgb2gray(img);
tolerance = 12; % default setting in imageSegmenter
%% >>>>>>>>>> GET INITIALIZATION POINTS <<<<<<<<<< %%
str = 'Click to select initialization points. Press ENTER to confirm.';
fig_sel = figure(); imshow(img);
title(str,'Color','b','FontSize',10);
fprintf(['\nNote: ' str '\n'...
'Pressing ENTER ends the selection without adding a final point.\n' ...
'Pressing BACKSPACE/DELETE removes the previously selected point.\n'] );
% select points in figure and close afterwards
[x, y] = getpts(fig_sel);
close(fig_sel);
%% >>>>>>>>>> PROCESS INITIALIZATION POINTS <<<<<<<<<< %%
if length(x) == 0
fprintf('\nError: No points specified. An initialization point is needed!');
else
segmentations = zeros([size(img) length(x)]);
fig_result = figure(); hold on;
for i = 1:length(x)
% confusing: y corresponds to row, x to column in img
column = ceil(x(i));
row = ceil(y(i));
%>>> this is where the magic happens <<<%
segmentations(:,:,i) = grayconnected(img,row,column,tolerance);
% show corresponding initialization point
subplot(1,2,1); imshow(img); hold on;
title('Active point (red)');
plot(x(i),y(i),'r.','MarkerSize',10); % active in red
plot(x(1:end ~= i),y(1:end ~= i),'b.','MarkerSize',5); % ... others in blue
hold off;
% ... with segmentation result
title('Segmentation result');
subplot(1,2,2); imshow(segmentations(:,:,i));
% click through results
waitforbuttonpress
end
close(fig_result);
end
I have a dataset the red line.
I'm trying to find the minimum points highlighted in yellow if I take the reflection/mirror image of a data set.
See example code / plot below I'm trying to find a way to find the minimum points highlighted in yellow of the reflection/mirror image of a dataset (the blue line) that is below the reflection line (the black line).
Please note this is just a simple dataset there will be much larger datasets around 100000+
PS: I'm using Octave 3.8.1 which is like matlab
clear all,clf, clc,tic
x1=[0.;2.04;4.08;6.12;8.16;10.2;12.24;14.28;16.32;18.36]
y1=[2;2.86;4;2;1;4;5;2;7;1]
x2=[0.;2.04;4.08;6.12;8.16;10.2;12.24;14.28;16.32;18.36]
y2=abs(y1-max(y1));
data1 = y2;
reflection_line=max(y1)/2
[pks3 idx3] = findpeaks(data1,"DoubleSided","MinPeakHeight",0.1);
line([min(x1) max(x1)], [reflection_line reflection_line]);
hold on;
plot(x1,reflection_line)
hold on;
plot(x1,y1,'-r',x2,y2,'-b')
I am not reflecting your original data, but rather find the local maxima of the original values, that are larger than your given line.
Using a DIY alternative to findpeaks:
A value is a local maximum, if it's larger than (or equal to) its predecessor and successor.
%% Setup
x1 = [0.;2.04;4.08;6.12;8.16;10.2;12.24;14.28;16.32;18.36];
y1 = [2;2.86;4;2;1;4;5;2;7;1];
reflection_line = max(y1)/2;
%% Sort by x value
[x1, I] = sort(x1);
y1 = y1(I);
%% Compute peaks
maxima = #(y) [true; y(2:end)>=y(1:end-1)] & ... % Value larger than predecessor
[y(1:end-1)>=y(2:end); true]; % Value larger than successor
maximaLargerThanLine = maxima(y1) & (y1>reflection_line);
%% Plotting
plot(x1,y1);
hold on;
plot(x1(maximaLargerThanLine),y1(maximaLargerThanLine),'rx');
line([min(x1) max(x1)], [reflection_line reflection_line]);
I have a cube in which I have something as a anomaly, consider it as a cube of zeros and I put a smaller cube of numbers in it using the following code:
anomaly = zeros(100,100,100);
for j = 40:60
for jj = 40:60
for jjj=40:60
anomaly(j,jj,jjj)=10;
end
end
end
I want to somehow view it in a 3D figure, for which I can see the anomaly it it. How can I do it?
Go for isosurface. With isosurface you will be able to extract the inclusion. If you also want to show the whole box, I recommend you to do the following: Create a small box (so it has few faces when converted to isosurface) and then scale it to the real size of the box. You can see this in the following code:
anomaly = zeros(100,100,100); % The anomaly
an2=zeros(100/10+2,100/10+2,100/10+2); % For plotting pourposes
an2(2:10,2:10,2:10)=1; % Create a 10x10x10 box
for j = 40:60
for jj = 40:60
for jjj=40:60
anomaly(j,jj,jjj)=10;
end
end
end
iso=isosurface(anomaly,5); % Extract surface of inclusion
iso2=isosurface(an2,0.5); % create a box
iso2.vertices=(iso2.vertices-1)*10; % offset( so its in 1-10 range)
% and scaling to be 100x100x100
patch(iso,'facecolor','r','edgecolor','none')
patch(iso2,'facecolor','none');
% this last ones are for having a nicer plot
camlight
axis off
axis equal
I have a set of points represented as a 2 row by n column matrix.
These points make up a connected boundary or edge. I require a function that traces this contour from a start point P1 and stop at an end point P2. It also needs to be able trace the contour in a clockwise or anti-clockwise direction. I was wondering if this can be achieved by using some of Matlab's functions.
I have tried to write my own function but this was riddled with bugs and I have also tried using bwtraceboundary and indexing however this has problematic results as the points within the matrix are not in the order that create the contour.
Thank you in advance for any help.
Btw, I have included a link to a plot of the set of points. It is half the outline of a hand.
The function would ideally trace the contour from ether the red star to the green triangle. Returning the points in order of traversal.
EDIT: This is perhaps a work around to a larger problem I am trying to solve but would it be possible to test if a point on the blue boundary edge is connected to the contour that is between either the red stars or green triangular points.
i.e. for a point on the blue boundary, if you were to trace the contour by hand from the left red asterixs to the green triangle the function would return true if the point is on the connected boundary between the two points and false otherwise.
alt text http://img717.imageshack.us/img717/9814/hand1.png
If the points are so close together, you should be able to do the trace by always looking for the next closest point in the list.
If the point were farther apart, the problem would not be solvable - imagine the five points where four are corners and one is in the center: what is the 'correct' way of tracing the line?
%%# create some points
npts = 100;
x = linspace(-1,1,100)'; %'
y = 1 - x.^2;
pts = [x,y];
%# shuffle the points
newOrder = randperm(npts);
pts = pts(newOrder,:);
%# find index of start, end point
startIdx = find(newOrder == 1);
endIdx = find(newOrder == npts);
%# this brings us to where you are - pts as a nx2 array
%# startIdx indicates the star, and endIdx indicates the triangle.
%# pre-assign output - traceIdx, which contains the ordered indices of the point on the trace
traceIdx = NaN(npts,1);
%# create distance matrix
distances = squareform(pdist(pts));
%# eliminate zero-distance along the diagonal, b/c we don't want points linking to themselves
distances(logical(eye(npts))) = NaN;
%# starting from startIdx: always find the closest next point, store in traceIdx,
%# check whether we've arrived at the end, and repeat if we haven't
done = false;
traceCt = 1;
traceIdx(1) = startIdx;
while ~done
%# find the index of the next, closest point
[dummy,newIdx] = min(distances(traceIdx(traceCt),:));
%# store new index and up the counter
traceCt = traceCt + 1;
traceIdx(traceCt) = newIdx;
%# check whether we're done
if newIdx == endIdx
done = true;
else
%# mask the backward distance so that there's no turning back
distances(newIdx,traceIdx(traceCt-1)) = NaN;
end %# if
end %# while ~done
%# remove NaNs
traceIdx(~isfinite(traceIdx)) = [];
%# plot result with a line connecting the dots to demonstrate that everything went well.
figure,
plot(pts(traceIdx,1),pts(traceIdx,2),'-o')
hold on,
plot(pts(startIdx,1),pts(startIdx,2),'*r')
plot(pts(endIdx,1),pts(endIdx,2),'>g')