How to plot this in matlab? - matlab

I have following code
xr=randi([1 150],1,20)
z=numel(xr);
N=10; %Window length
gAll=zeros(1,z-N+1);
for n=0:z-N;
x=xr(1+n:N+n)
d=max(x);
m=numel(x);
y=zeros(d,1);
p=zeros(d,d);
for k=1:m-1
y(x(k))=y(x(k))+1;
p(x(k),x(k+1))=p(x(k),x(k+1))+1;
end
p=bsxfun(#rdivide,p,y);
p(isnan(p)) = 0;
j=prod(p(p~=0));
[~,~,idx] = unique(x);
q=prod(hist(idx,1:max(idx))/numel(x));
s=log(j);
l=log(q);
g=s+l
gAll(n+1)=g;
end
plot(gAll)
I want a plot such a that for threshold line of gAll =-22, graph above threshold line should be in red color and graph below threshold line should in blue, but graph should in continuous joint with these two different colors, how to do it.

You can mask areas of the graph by setting values to NaN. I would create a high resolution interpolant of the data gAll, then create two coppies, ones with gAll>-22 masked and one with gAll<-22 masked and plot them on the same axes.
You could make gAll_HR a high resolution version of your vector gAll on x_HR with interp1(x, gAll, x_HR), then replace values with NaN using logical indexing:
gAll_low = gAll_HR;
gAll_low(gAll_HR>=-22) = NaN;
gAll_high = gAll_HR;
gAll_high(gAll_HR<-22) = NaN;
plot(x_HR, gAll_low, 'b-', x_HR, gAll_high, 'r-')

Related

Change Colorbar Scheme

I read in an image in MATLAB and display it using imagesc. I then set the colormap to grey.
On top of this image, I plot points with the jet colour scheme. How do I then display the jet colorbar, to correspond to the colours of the points plotted on top of the original image? I tried redefining the colorbar after all of the plots, but this changes the original grey scale image back to colours, which isn't desired.
Code:
%Create Figure with handle.
h5=figure('units','normalized','outerposition',[0 0 1 1]);
whitebg(h5,[0 0 0]);
subplot(2,5,1);
k=1;
for i=16:25
subplot(2,5,k);
imagesc(squeeze(ana(:,:,i)));
title(['Z=',num2str(i)]);
colormap gray
axis equal
k=k+1;
colorbar
end
%Adapt colour values so that they are between 0 and 1. We want to scale
%both data sets equally, so we find the smallest value across Ix and Iy. We
%also find what will be the new largest value across Ix and Iy, after we
%add the magnitude of the smallest value to make all numbers greater than
%or equal to 0.
absolutemin=min(min(Ix(:,1)),min(Iy(:,1)));
absolutemax=max(abs(absolutemin)+(max(Ix(:,1))),abs(absolutemin)+max(Iy(:,1)));
%Add the smallest value, and divide by the largest maximum value for both Ix
%and Iy.
ixcolours=uint8(((Ix(:,1)+abs(absolutemin))/absolutemax).*255)+1;
iycolours=uint8(((Iy(:,1)+abs(absolutemin))/absolutemax).*255)+1;
mycolours=jet(256);
o=1;
for k=16:25; %For all 3D slices
for i=1:471; %and for all x and y seed slices
if k==seed_locs(i,3);
subplot(2,5,o);
hold all%go to the corresponding z subplot
plot(seed_locs(i,1),seed_locs(i,2),'MarkerFaceColor',mycolours(ixcolours(i),:),'MarkerEdgeColor',mycolours(ixcolours(i),:),'MarkerSize',10,'Marker','s') %plot the x and y seedlocs
%hold on
end
end
for i=1:486;
if k==test_locs(i,3);
subplot(2,5,o);
hold all
plot(test_locs(i,1),test_locs(i,2),'MarkerFaceColor',mycolours(iycolours(i),:),'MarkerEdgeColor',mycolours(iycolours(i),:),'MarkerSize',10,'Marker','s') %plot the x and y seedlocs
% hold on
end
end
o=o+1; %go to the next z subplot
end
colormap jet
colorbar
I think the following example can help you to improve your code. You firstly need to define two colormaps:
colormap([cool(64);gray(64)]);
Then let's say we have two different sets of datapoints to plot:
[X,Y,Z] = peaks(25);
h(1) = surf(X,Y,Z);hold on
h(2) = pcolor(X,Y,Z);
So the data is defined with two different handles. Now we need to make the CData using the minimum and maximum values.
cmin = min(Z(:));
cmax = max(Z(:));
C1 = min(64,round((64-1)*(Z-cmin)/(cmax-cmin))+1); % CData for the first datapoints
C2 = 64+C1; % CData for the second datapoints
Now we update the CDatas for each object.
set(h(1),'CData',C1);
set(h(2),'CData',C2);
Now you can set the CLim property of axes:
caxis([min(C1(:)) max(C2(:))])
colorbar;

Surface plot with highligheted cut

I would like to plot a 3D surface using the Matlab surf function. The whole surface should be in gray scale, then I need to highlight a specific cut of the surface using a different color.
I thought this code would've worked but it doesn't.
Mat = randi(100); % Matrix to be plotted in gray scale
ind_highlight = 10; % Row of the matrix to be highlighted
Mat2 = Mat;
Mat2([1:ind_highlight-1, ind_highlight+1:end] ,:) = NaN;
figure
surf(X,Y,Mat)
colormap gray
hold on
% Highlight the ind_highlight row
surf(X,Y,Mat2)
colormap hsv
Any help would be highly appreciated!
It seems there is no way to use different colormap to obtain the desired effect since the colormap "belongs" to the figure.
I've found a possible solution which does not use colormap.
It is based on the specifying the color matrix in the call to surf, one for the whole matrix, one for the section to be highlighted, then superimposing the second one to the first one.
Unfortunately, I've not been able to set the first ad gray.
I've used the peaks matrix instead of your "randi" in order to have a more smooth surface to work with and inserted the script in a for loop to highlight different section of the matrix
% Mat = randi(100,100,100); % Matrix to be plotted in gray scale
% Alternative definition of the Matrix to be displayed
n_pt=50;
Mat=peaks(n_pt);
% Generate meshgrid
x=1:n_pt;
y=1:n_pt;
[X,Y]=meshgrid(x,y);
ind_highlight_2 = 5; % Number of rows of the matrix to be highlighted
% Generate two set of color matrix
% The first on for the whole surf
% The second one for the section to be highlighted
a=randi(2,n_pt,n_pt);
b=randi(10,n_pt,n_pt);
for i=1:n_pt-ind_highlight_2
ind_highlight_1 = i; % Starting row of the matrix to be highlighted
Mat2 = Mat;
% Modified set of data (in the original just one row was left
% Mat2([1:ind_highlight-1, ind_highlight+1:end] ,:) = NaN
Mat2(ind_highlight_1:ind_highlight_1+ind_highlight_2,:) = NaN;
COL=a;
COL(ind_highlight_1:ind_highlight_1+ind_highlight_2,:)=b(ind_highlight_1:ind_highlight_1+ind_highlight_2,:);
% Plot the surf specifying the color
s_h=surf(X,Y,Mat,COL);
shading interp
% view([0 90])
% f_name=['jpg_name_' num2str(i)]
% print('-djpeg75',f_name)
pause(.1);
end
Hope this helps.

Calculate the pixel distance to three defined pixel in matlab

I want to classify pixels of one tiff image according to pixel's RGB colour. The input is an image and three predefined colours for water(r0,g0,b0), forest(r1,g1,b1) and building(r2,g2,c2). The classification is based on the distance between image pixel and these three colors. If a pixel is closet to the water, the pixel is water and changed it the water RGB. The distance is calculated as (one sample) sqrt((x-r0)^2+(y-g0)^2+(z0-b0)^2)
The sample implementation is:
a=imread(..);
[row col dim] = size(a); % dim =3
for i=1:row
for j=1:col
dis1=sqrtCal(a(i,j,:)-water)
dis2=sqrtCal(a(i,j,:)-forest)
dis3=sqrtCal(a(i,j,:)-build)
a(i,j,:) = water;
if dis2< dis1
dis1 = dis2
a(i,j,:) = forest
end
dis3=sqrt(a(i,j,:)-build)
if dis3<dis1
a(i,j,:) = build
end
end
end
This implementation should work. The problem is that the two for loops is not a good choice.
So is there any good alternatives in the Matlab? The
D = pdist(X,distance)
Seems not appliable for my case.
I think this does what you want. The number of reference colors is arbitrary (3 in your example). Each reference color is defined as a row of the matrix ref_colors. Let MxN denote the number of pixels in the original image. Thus the original image is an MxNx3 array.
result_index is an MxN array which for each original pixel contains the index of the closest reference color.
result is a MxNx3 array in which each pixel has been assigned the RBG values of the closest reference color.
im = rand(10,12,3); %// example image
ref_colors = [ .1 .1 .8; ... %// water
.3 .9 .2; ... %// forest
.6 .6 .6 ]; %// build: example reference colors
dist = sum(bsxfun(#minus, im, permute(ref_colors, [3 4 2 1])).^2, 3);
%// 4D array containing the distance from each pixel to each reference color.
%// Dimensions are: 1st: pixel row, 2nd: pixel col, 3rd: not used,
%// 4th: index of reference color
[~, result_index] = min(dist, [], 4); %// compute arg min along 4th dimension
result = reshape(ref_colors(result_index,:), size(im,1), size(im,2), 3);
This one is another bsxfun based solution, but stays in 3D and could be more efficient -
%// Concatenate water, forest, build as a 2D array for easy processing
wfb = cat(2,water(:),forest(:),build(:))
%// Calculate square root of squared distances & indices corresponding to min vals
[~,idx] = min(sum(bsxfun(#minus,reshape(a,[],3),permute(wfb,[3 1 2])).^2,2),[],3)
%// Get the output with the minimum from the set of water, forest & build
a_out = reshape(wfb(:,idx).',size(a))
If you have the statistics toolbox installed, you can use this version based on knnsearch, that scales well for a large number of colors.
result_index = knnsearch(ref_colors, reshape(im,[],3));
result = reshape(ref_colors(result_index,:), size(im));

Image Histogram Comparison

I was trying to do histogram image comparison between two RGB images which includes heads of the same persons and non-heads to see the correlation between them. The reason I am doing this is because after performing scanning using HOG to check whether the scanning window is a head or not, I am now trying to track the same head throughout consequent frames and also I want to remove some clear false positives.
I currently tried both RGB and HSV histogram comparison and used Euclidean Distance to check the difference between the histograms. The following is the code I wrote:
%RGB histogram comparison
%clear all;
img1 = imread('testImages/samehead_1.png');
img2 = imread('testImages/samehead_2.png');
img1 = rgb2hsv(img1);
img2 = rgb2hsv(img2);
%% calculate number of bins = root(pixels);
[rows, cols] = size(img1);
no_of_pixels = rows * cols;
%no_of_bins = floor(sqrt(no_of_pixels));
no_of_bins = 256;
%% obtain Histogram for each colour
% -----1st Image---------
rHist1 = imhist(img1(:,:,1), no_of_bins);
gHist1 = imhist(img1(:,:,2), no_of_bins);
bHist1 = imhist(img1(:,:,3), no_of_bins);
hFig = figure;
hold on;
h(1) = stem(1:256, rHist1);
h(2) = stem(1:256 + 1/3, gHist1);
h(3) = stem(1:256 + 2/3, bHist1);
set(h, 'marker', 'none')
set(h(1), 'color', [1 0 0])
set(h(2), 'color', [0 1 0])
set(h(3), 'color', [0 0 1])
hold off;
% -----2nd Image---------
rHist2 = imhist(img2(:,:,1), no_of_bins);
gHist2 = imhist(img2(:,:,2), no_of_bins);
bHist2 = imhist(img2(:,:,3), no_of_bins);
hFig = figure;
hold on;
h(1) = stem(1:256, rHist2);
h(2) = stem(1:256 + 1/3, gHist2);
h(3) = stem(1:256 + 2/3, bHist2);
set(h, 'marker', 'none')
set(h(1), 'color', [1 0 0])
set(h(2), 'color', [0 1 0])
set(h(3), 'color', [0 0 1])
%% concatenate values of a histogram in 3D matrix
% -----1st Image---------
M1(:,1) = rHist1;
M1(:,2) = gHist1;
M1(:,3) = bHist1;
% -----2nd Image---------
M2(:,1) = rHist2;
M2(:,2) = gHist2;
M2(:,3) = bHist2;
%% normalise Histogram
% -----1st Image---------
M1 = M1./no_of_pixels;
% -----2nd Image---------
M2 = M2./no_of_pixels;
%% Calculate Euclidean distance between the two histograms
E_distance = sqrt(sum((M2-M1).^2));
The E_distance consists of an array containing 3 distances which refer to the red histogram difference, green and blue.
The Problem is:
When I compare the histogram of a non-head(eg. a bag) with that of a head..there is a clear difference in the error. So this is acceptable and can help me to remove the false positive.
However! When I am trying to check whether the two images are heads of the same person, this technique did not help at all as the head of another person gave a less Euclidean distance than that of the same person.
Can someone explain to me if I am doing this correctly, or maybe any guidance of what I should do?
PS: I got the idea of the LAB histogram comparison from this paper (Affinity Measures section): People Looking at each other
Color histogram similarity may be used as a good clue for tracking by detection, but don't count on it to disambiguate all possible matches between people-people and people-non-people.
According to your code, there is one thing you can do to improve the comparison: currently, you are working with per-channel histograms. This is not discriminative enough because you do not know when R-G-B components co-occur (e.g. you know how many times the red channel is in range 64-96 and how many times the blue is in range 32-64, but not when these occur simultaneously). To rectify this, you must work with 3D histograms, counting the co-occurrence of colors). For a discretization of 8 bins per channel, your histograms will have 8^3=512 bins.
Other suggestions for improvement:
Weighted assignment to neighboring bins according to interpolation weights. This eliminates the discontinuities introduced by bin quantization
Hierarchical splitting of detection window into cells (1 cell, 4 cells, 16 cells, etc), each with its own histogram, where the histograms of different levels and cells are concatenated. This allows catching local color details, like the color of a shirt, or even more local, a shirt pocket/sleeve.
Working with the Earth Mover's Distance (EMD) instead of the Euclidean metric for comparing histograms. This reduces color quantization effects (differences in histograms are weighted by color-space distance instead of equal weights), and allows for some error in the localization of cells within the detection window.
Use other cues for tracking. You'll be surprised how much the similarity between the HoG descriptors of your detections helps disambiguate matches!

How do I create an image matrix with a line drawn in it in MATLAB?

I want to plot a line from one well-defined point to another and then turn it into an image matrix to use a Gaussian filter on it for smoothing. For this I use the functions line and getframe to plot a line and capture the figure window in an image, but getframe is very slow and not very reliable. I noticed that it does not capture anything when the computer is locked and I got an out of memory error after 170 executions.
My questions are:
Is there a substitute to getframe that I can use?
Is there a way to create the image matrix and draw the line directly in it?
Here is a minimal code sample:
figure1=line([30 35] ,[200 60]);
F= getframe;
hsize=40; sigma=20;
h = fspecial('gaussian',hsize,sigma);
filteredImg = imfilter(double(F.cdata), h,256);
imshow(uint8(filteredImg));
[update]
High-Performance Mark's idea with linspace looks very promising, but how do I access the matrix coordinates calculated with linspace? I tried the following code, but it does not work as I think it should. I assume it is a very simple and basic MATLAB thing, but I just can not wrap my head around it:
matrix=zeros(200,60);
diagonal=round([linspace(30,200,numSteps); linspace(35,60,numSteps)]);
matrix(diagonal(1,:), diagonal(2,:))=1;
imshow(matrix);
Here's one example of drawing a line directly into a matrix. First, we'll create a matrix of zeros for an empty image:
mat = zeros(250, 250, 'uint8'); % A 250-by-250 matrix of type uint8
Then, let's say we want to draw a line running from (30, 35) to (200, 60). We'll first compute how many pixels long the line will have to be:
x = [30 200]; % x coordinates (running along matrix columns)
y = [35 60]; % y coordinates (running along matrix rows)
nPoints = max(abs(diff(x)), abs(diff(y)))+1; % Number of points in line
Next, we compute row and column indices for the line pixels using linspace, convert them from subscripted indices to linear indices using sub2ind, then use them to modify mat:
rIndex = round(linspace(y(1), y(2), nPoints)); % Row indices
cIndex = round(linspace(x(1), x(2), nPoints)); % Column indices
index = sub2ind(size(mat), rIndex, cIndex); % Linear indices
mat(index) = 255; % Set the line pixels to the max value of 255 for uint8 types
You can then visualize the line and the filtered version with the following:
subplot(1, 2, 1);
image(mat); % Show original line image
colormap(gray); % Change colormap
title('Line');
subplot(1, 2, 2);
h = fspecial('gaussian', 20, 10); % Create filter
filteredImg = imfilter(mat, h); % Filter image
image(filteredImg); % Show filtered line image
title('Filtered line');
If you have Computer Vision System toolbox there is a ShapeInserter object available. This can be used to draw lines, circles, rectangles and polygons on the image.
mat = zeros(250,250,'uint8');
shapeInserter = vision.ShapeInserter('Shape', 'Lines', 'BorderColor', 'White');
y = step(shapeInserter, mat, int32([30 60 180 210]));
imshow(y);
http://www.mathworks.com/help/vision/ref/vision.shapeinserterclass.html
You can check my answer here. It is robust way to achieve what you are asking for. Advantage of my approach is that it doesn't need additional parameters to control density of the line drawn.
Something like this:
[linspace(30,200,numSteps); linspace(35,60,numSteps)]
Does that work for you ?
Mark