Matlab figures - remove filling from gaussian distributions - matlab

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

Related

Encode each training image as a histogram of the number of times each vocabulary element shows up for Bag of Visual Words

I want to implement bag of visual words in MATLAB. I used SURF features to extract features from the images and k-means to cluster those features into k clusters. I now have k centroids and I want to know how many times each cluster is used by assigning each image feature to its closet neighbor. Finally, I'd like to create a histogram of this for each image.
I tried to use knnsearch function but it doesn't work in this case.
Here is my MATLAB code:
clc;
clear;
close all;
folder = 'CarData/TrainImages/cars';
filePattern = fullfile(folder, '*.pgm');
f=dir(filePattern);
files={f.name};
for k=1:numel(files)
fullFileName = fullfile(folder, files{k});
H = fspecial('log');
image=imfilter(imread(fullFileName),H);
temp = detectSURFFeatures(image);
[im_features, temp] = extractFeatures(image, temp);
features{k}= im_features;
end
features = vertcat(features{:});
image_feats = [];
[assignments,centers] = kmeans(double(features),500);
vocab = centers';
I have all images feature in features array and cluster center in centroid array
You're almost there. You don't even need to use knnsearch at all. The assignments variable tells you which input feature mapped to which cluster. assignments will give you a N x 1 vector where N is the total number of examples you have, or the total number of features in the input matrix features. Each value assignments(i) tells you which cluster the example i (or row i) of features it maps to. The cluster centroid dictated by assignments(i) would be given as centers(i, :).
Therefore given how you've called kmeans, it will be a N x 1 vector where each element is from 1 to 500 with 500 being the total number of clusters desired.
Let's do the simple case where we only have one image in your codebook. If this is the case, all you have to do is create a histogram of the assignments variable. The output histogram h will be a 500 x 1 vector with each element h(i) being the number of times an example used centroid i as its representation in your codebook.
Just use the histcounts function and make sure that you specify the bin ranges so that they coincide with each cluster ID. You must make sure that you account for the ending bin, as the bin ranges are exclusive on the right edge so just add an additional bin to the end.
Something like this will work:
h = histcounts(assignments, 1 : 501);
If you want something simpler and you don't want to worry about specifying the end bin, you can use accumarray to achieve the same result:
h = accumarray(assignments, 1);
The effect of accumarray we assign key-value pairs where the key is the centroid that the example mapped to and the value is simply 1 for all keys. accumarray will bin all values in assignments that share the same key and you do something with those values. The default behaviour of accumarray is to sum all values, which is effectively computing the histogram.
However, you want to do this for multiple images, not just a single image.
For Bag of Visual Words problems, we will certainly have more than one training image in our database. Therefore, you want to find the histogram of the features for each image. We can still use the above concept, but one thing I can suggest is you maintain a separate variable that tells you how many features were detected per image, then you can index into the assignments variable to help extract out the correct assigned centroid IDs, then build a histogram of those individually. We can build a 2D matrix where each row delineates the histogram of each image. Remember that in kmeans, each row tells you what cluster each example was assigned to independently of the other examples in your data. Using that, you would use kmeans on the entire training dataset, then be smart about how you're accessing the assignments variable to extract out the assigned clusters for each input image.
Therefore, modify your code so that it looks something like this:
clc;
clear;
close all;
folder = 'CarData/TrainImages/cars';
filePattern = fullfile(folder, '*.pgm');
f=dir(filePattern);
files={f.name};
num_features = zeros(numel(files), 1); % New - for keeping track of # of features per image
for k=1:numel(files)
fullFileName = fullfile(folder, files{k});
H = fspecial('log');
image=imfilter(imread(fullFileName),H);
temp = detectSURFFeatures(image);
[im_features, temp] = extractFeatures(image, temp);
num_features(k) = size(im_features, 1); % New - # of features per image
features{k}= im_features;
end
features = vertcat(features{:});
num_clusters = 500; % Added to make the code adaptive
[assignments,centers] = kmeans(double(features), num_clusters);
counter = 1; % Keeps track of where we need to slice in assignments
% Go through each image and find their histograms
features_hist = zeros(numel(files), num_clusters); % Records the per image histograms
for k = 1 : numel(files)
a = assignments(counter : counter + num_features(k) - 1); % Get the assignments
h = histcounts(a, 1 : num_clusters + 1);
% Or:
% h = accumarray(a, 1).'; % Transpose to make it a row
% Place in final output
features_hist(k, :) = h;
% Increment counter
counter = counter + num_features(k);
end
features_hist will now be a N x 500 matrix where each row is the histogram of each image you are seeking. The final job would be to use a supervised machine learning algorithm (SVM, Neural Networks, etc.) where the expected labels is the description of each image you have assigned to the image accompanied by the histogram of each image as the input features. The final result would be a learned model so that when you have a new image, calculate the SURF features, represent them in a histogram of features like we did above, then feed it into the classification model to give you the expected class or label that the image represents.
P.S. Deep Learning / CNNs do a much better job at this, but require much more time to train. If you're looking at performance wise, don't use Bag of Visual Words but this is something very quick to implement and it's known to perform moderately well but that of course depends on the kinds of images you want to classify.

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.

Is it possible in Matlab to plot not matching SURFPoints?

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?

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.