Is it possible in Matlab to plot not matching SURFPoints? - matlab

I am trying to find the difference between two images, using Matlab. The classic built in function that Matlab provides for this is because the two images don't have the same dimensions (The objects in the images are the same, but in the second image other objects are introduced).
And i thought i could use SURF Features to accomplish this.
Here's the code:
source = imread('source.png');
target = imread('target.png');
source = rgb2gray(source);
target = rgb2gray(target);
sourcePoints=detectSURFFeatures(source,'MetricThreshold',100.0,'NumOctaves',1,'NumScaleLevels',6);
targetPoints=detectSURFFeatures(target,'MetricThreshold',100.0,'NumOctaves',1,'NumScaleLevels',6);
%figure; imshow(source);
%hold on;
%plot(sourcePoints.selectStrongest(10000));
[sourceFeatures, sourcePoints]=extractFeatures(source,sourcePoints,'SURFSize',64);
[targetFeatures,targetPoints]=extractFeatures(target,targetPoints,'SURFSize',64);
boxPairs = matchFeatures(sourceFeatures, targetFeatures);
matchedSourcePoints = sourcePoints(boxPairs(:, 1), :);
matchedTargetPoints = targetPoints(boxPairs(:, 2), :);
figure;
showMatchedFeatures(source, target, matchedSourcePoints, matchedTargetPoints, 'montage');
display(matchedSourcePoints);
display(matchedTargetPoints);
The problem is that from what i know you have functions that only display matched SURF Points, and i would need to plot on the target image only the points that didn't match with the points in the source image.
The resulting "matchedTargetPoints" and the "targetPoints" variables are arrays of SURFPoints objects, so the find function doesn't work, subtracting or making array operations on them don't work.
I also tried to loop through "targetPoints" and check for every one if the point exists, but the script takes forever, so this also doesn't work.
Does anyone have any idea how this might be accomplished?
Any response is appreciated.
Thank you.

You can get the (x,y) locations of the points stored in an M-by-2 matrix by using the Location property of the SURFPoints object. Then you can get the unmatched points using logical indexing:
targetPointsLoc = targetPoints.Location;
unmatchedIdx = true(size(targetPoitnsLoc, 1), 1);
unmatchedIdx(boxPairs(:, 2)) = false;
unmatchedTargetPoints = targetPointsLoc(unmatchedIdx, :);
Now you can use plot to display the unmatched points.
Out of curiosity, why do you care about the unmatched points?

Related

Why is the resultant of my improfile function returning with a mirrored graph in MATLAB?

I am currently running improfile on MATLAB with a line going through the center of the picture below:
After doing so, I'm plotting the resultant using the code below:
xi = [1 size(d_Img,2) size(d_Img,2) 1];
yi = [ceil(size(d_Img,1)/2), ceil(size(d_Img,1)/2), ceil(size(d_Img,1)/2 ),ceil(size(d_Img,1)/2)];
c_d = improfile(d_Img,xi,yi);
c_c = improfile(c_Img,xi,yi);
c_d = c_d';
c_c = c_c';
size_c = size(c_d);
n = 1:size_c(2);
plot(n,c_d);
And here is the plot:
Why are the curves mirroring each other? I am asking to gain a better understanding of what exactly improfile seems to be achieving in MATLAB.
improfile computes something like a "path integral", it gives you the image intensity values around a user specified path. For example, if you use:
improfile(img,[1 1],[1 size(img,2)]);
It gives the same as img(:,1). This is because the path you are using in improfile is from (1,1) to (1,size(img,2)) , meaning the first row. However you could definitely add more complicated paths.
In your case you are going trow a path defined by 4 points. The points are, if I substitute your equation by the resultant numbers:
(1,79)->(134,79)->(134,79)->(1,79). Thus, looking at this, it is obvious that your result should be mirrored, because you are integrating over a line the way there, and back!
Sidenote:
you can do plot(c_d); and forget about that n

Exporting data in zoomed in region of MATLAB plot to workspace

I have 4-5 subplots of timeseries data and scatter plots in a MATLAB figure whose x axes are linked. The data is quite long and I've zoomed into a small portion of the figure.Now I want to export just the data contained in this zoomed in portion to work-space as variables. Is it possible?
For example, the following is the plot for the full dataset.
The following is the zoomed in portion,
Now I want to export all the variables or time-section of the variables corresponding to the above zoomed in portion to workspace.
Building off of Ratbert's comment, let's set up a sample plot to play around with.
x = 1:10;
h.myfig = figure();
h.myaxes = axes('Parent', h.myfig);
h.myplot = plot(x);
I'm going to assume you have MATLAB R2014b or newer, which is where MATLAB switched graphics handles to objects. If you have an older version you can swap all of my dot notations with get and set calls, where appropriate.
Now with this initial plot, if we enter h.myaxes.XLim or get(h.myaxes, 'XLim'), we return:
ans =
1 10
Now if we zoom in arbitrarily and make the same call, we get something different. In my case:
ans =
3.7892 7.0657
Now it's up to you how you want to use this information to window your data. A very basic method would be to use find to get the indices of the closest data points to these limits.
For example:
newlimits = h.myaxes.XLim;
newminidx = find(x >= floor(newlimits(1)), 1);
newmaxidx = find(x >= ceil(newlimits(2)), 1);
newmin = x(newminidx);
newmax = x(newmaxidx);
Returns [newmin, newmax] of:
ans =
3 8
I used floor and ceil here because I know my data is integers, your criteria may be different but the process is the same. Hopefully this is enough to get you started.

Matlab figures - remove filling from gaussian distributions

I am emulating a NAND Flash mlc and I am using hist() to display the results which are 4 gaussian distributions.
The problem is that I am trying to display 8 distributions at once one the same figure and they overlap. So, I want to find a way to remove the filling inside the gaussian distributions and only keep the outline. Is there a way to do this? I have found that maybe "basic fitting" option in Matlab can do this but it is "grey" and I cannot select it on this figure.
--
Well I tried adding a simple a picture which can explain everything but I could not due to my reputation.
I am working in FPGA(ZedBoard) in order to create the emulation but that has nothing to do with the question I am asking.
So, I get an input file with single-precision values out of ZedBoard, which then I insert in Matlab and get the figure I am talking about.
I would not think that my code in Matlab could help in any way that is why I did not put it.
Although, I should have mentioned that the eight distributions have almost the exact same characteristics so they appear almost on the same place. This is why I am looking a way to display them properly.
These "hists" below have to appear on the same figure without overlapping on each other. Normally, when Matlab is displaying gaussian distributions with "hist" uses a blue filling which I want to remove and only leave the outlining of the distribution if possible. I hope I have given a better view of my problem with this added.
fid1 = fopen('soft_without.txt');
A = textscan(fid1,'%s');
B = char(A{1});
fclose (fid1);
output = typecast(uint32(hex2dec(B)),'single');
hist(output,1000);
fid2 = fopen('soft_with.txt');
A = textscan(fid2,'%s');
B = char(A{1});
fclose (fid2);
output1 = typecast(uint32(hex2dec(B)),'single');
hist(output1,1000);
Let's first put all the data into one dataset, rather than having a bunch of different variables:
filenames = ls('*.txt'); % or whatever you do to make up your list of files
data = zeros(1000, 8); %preallocate
% going to use first file to set location of bins so they're all the same
fid = fopen(filenames(1,:))
A = textscan(fid,'%s');
B = char(A{1});
fclose(fid);
output = typecast(uint32(hex2dec(B)),'single');
[x, bins] = hist(output,1000);
data(:,1) = x;
% set rest to same bins
for n = 2:8
fid = fopen(filenames(n,:))
A = textscan(fid,'%s');
B = char(A{1});
fclose(fid);
output = typecast(uint32(hex2dec(B)),'single');
x = hist(output,bins);
data(:,n) = x;
end
bar(bins,data);
This will plot your eight sets as eight different (side by side) bars. Another route would be to plot the over the top of each other but set different edge colors and no face color (possibly also experiment with changing width).
colors = jet(8); % eight colors from the jet colormap
figure; hold on;
for n = 1:8
bar(bins,data(:,n),'facecolor','none','edgecolor', colors(n,:));
end

Meshgrid / Surface clipping

I am working with some antarctic DEM data in Matlab. So, far I have been able to generate a nice looking mesh, with the following basic code:
load (Data.xyz)
X = Data(:,1);
Y = Data(:,2);
Z = Data(:,3);
xr = unique(X);
yr = unique(Y);
gz = zeros(length(yr),length(xr));
gz = griddata(X,Y,Z,xr,yr');
figure
mesh(xr,yr,gz);
hold on
contour3(xr,yr,gz,'k-');
hold off
Now I have a few questions, which I have not been able to answer despite being at it since past couple of days and looking at all forums and googling day and night. I hope you all experts might be able to suggest me something. My questions are:
The above code takes a lot of time. Agreed that the DEM for antarctica is large sized and slow response time for a code does not necessarily mean that its incorrect. However, I am totally unable to run this code on my laptop (2.5 GHz/4GB) - its so slow. I am wondering if there are other ways to generate mesh which are faster and more efficient.
The second issue is that the above "Data.xyz" contains DEM data from all antarctica. After generating a mesh, I want to clip it based on locations. Say, for e.g., I want to extract mesh data for area bound by x1,y1, x2,y2, x3, y3, and x4,y4. How do I go about doing that? I could not find a suitable function or tool or any user script anywhere which will allow me to do so. Is it possible to cut a mesh in matlab?
I am running Matlab 2012a, and I do not have access to mapping toolbox. Any suggestions???
1.I'd just like to clarify what it is you want your code to do. For the data X,Y,Z, I would assume these are points (X,Y) (not sampled on a grid) each associated with some elevation Z.
When you call
gz = griddata(X,Y,Z,xr,yr');
You are saying that every possible pair (xr(i),yr(j)) are the locations on your grid where you want to sample the surface to create your mesh. I could be wrong but I don't think this is what you want?
I think you would rather sample at equally spaced points, instead using something like...
xr = min(X):spacing:max(X);
yr = min(Y):spacing:max(Y);
gz = griddata(X,Y,Z,xr,yr'); % ' is for the transpose
mesh(xr,yr,gz);
Where spacing a reasonable number for the scale of your data. The way your code is now, you could be taking far more samples than you want, which could be why your code takes so long.
For 2. I think you could get a for loop to just add the points insde the region of interest to three new lists of X,Y,Z values. If your region is rectangular bounded by x_left,x_right and y_left,y_right ...
Xnew = []; Ynew = []; Znew = [];
for i = 1:length(X)
if ( x_left<X(i) )&&( X(i)<x_right )&&( y_left<Y(i) )&&( Y(i)<y_right )
Xew = [Xnew, X(i)];
Ynew = [Ynew, Y(i)];
Znew = [Znew, Z(i)];
end
end

Issue with reading data in text files and plotting a graph (Matlab)

I use the following code to collect data from two text files join them together and then plot them. For some reason, I appear to get two plots rather than 1, I am not sure why this is happening.
load MODES1.dat; % read data into the MODES1 matrix
x1 = MODES1(:,1); % copy first column of MODES1 into x1
y1 = MODES1(:,2); % and second column of MODES1 into y1
load MODES.dat; % read data into the MODES matrix
x = MODES(:,1); % copy first column of MODES into x
y = MODES(:,2); % and second column of MODES into y
% Joining the two sets of data
endx = [x1;x];
endy = [y1;y];
figure(1)
plot(endx,endy)
xlabel('Unique Threshold Strains','FontSize',12);
ylabel('Probabilities of occurrence','FontSize',12);
title('\it{Unique Values versus frequencies of occurrence}','FontSize',16);
Thanks
Your problem is quite a simple one. Matlab's plot command creates a point for each data point defined by the parameters and connects those points in the order they appeared in the first parameter. To get an idea of this behavior, try
x = [0;1;-1;2;-2;3;-3;4;-4;5];
plot(x,x.^2);
You won't get the quadratic function graph you might expect.
To fix this, you must sort you input arrays identically. Sorting one array is simple (sort(endx)), but you want to sort both in the same way. Matlab actually gives you a function to do this, but it only works on matrices, so you need to do some concatenating/seperating:
input = sortrows( [endx endy] );
endx = input(:,1);
endy = input(:,2);
This will sort the rows of the matrix built by putting endy right of endx with respect to the first column (endx). Now your inputs are correctly sorted and the resulting plot should only show one line. (More accurately, one line which does not at some point go back where it came from.)
Another way to achieve this, depending on you actual use case and data origin, would be to build the mean value of both parts of x, so instead of endx = [x1;x];, you'd build endx = mean([x1 x],2);.
Yet another way is to drop the line altogether and go with
plot(endx,endy,'.');
or
plot(endx,endy,'LineStyle','none');
But this is only useful if your data points are very close to each other.