I am new to image processing and want to plot the color channels using surf to study the intensities in different color channels and their peaks or if they get cut off or saturated at any point. Can someone direct me as to where I can learn how to do this?
You can use the surf command directly to do just this. When you pass a 2D array to surf, it uses the values as the height (z) and uses 1:size(data, 2) for the x values and 1:size(data, 1) for the y values.
figure
hax = axes;
hold(hax, 'on');
rsurf = surf(img(:,:,1), 'FaceColor', 'r', 'FaceAlpha', 0.5, 'EdgeColor', 'none');
bsurf = surf(img(:,:,2), 'FaceColor', 'b', 'FaceAlpha', 0.5, 'EdgeColor', 'none');
gsurf = surf(img(:,:,3), 'FaceColor', 'g', 'FaceAlpha', 0.5, 'EdgeColor', 'none');
As an example
img = reshape(parula(16), [4 4 3]);
Related
I have an array of images and I need to plot them side by side, with each image having a different size. Although the actual image sizes are quite large, I would want to do something like imresize to plot the size that I want.
I have tried doing the subplot strategy like
subplot(1, 4, 1);
imshow(...);
subplot(1, 4, 2);
imshow(...);
subplot(1, 4, 3);
imshow(...);
subplot(1, 4, 4);
imshow(...);
But all the images show up as the same size. I want something like this
This for some reason seems non-trivial. Would really appreciate some help.
It's possible to make subplots of different sizes by specifying a multiple-element vector for the grid position argument p in the syntax subplot(m,n,p).
Your example can be constructed with the following:
subplot(4,10,[1:4 11:14 21:24 31:34]);
subplot(4,10,[5:7 15:17 25:27]);
subplot(4,10,[8:9 18:19]);
subplot(4,10,[10]);
You can add 4 axeses to the figure, and set the position of each axes:
I = imread('cameraman.tif');
scrsz = get(groot, 'ScreenSize'); %Get screen size
f = figure('Position', [scrsz(3)/10, scrsz(4)/5, scrsz(4)/2*2.4, scrsz(4)/2]); %Set figure position by screen size.
positionVector1 = [-0.25, 0.95-0.9, 0.9, 0.9]; %position vector for largest image.
positionVector2 = [0.23, 0.95-0.6, 0.6, 0.6];
positionVector3 = [0.555, 0.95-0.4, 0.4, 0.4];
positionVector4 = [0.775, 0.95-0.267, 0.267, 0.267]; %position vector for smallest image.
axes(f, 'Position', positionVector1);
imshow(I, 'border', 'tight');
axes(f, 'Position', positionVector2);
imshow(I, 'border', 'tight');
axes(f, 'Position', positionVector3);
imshow(I, 'border', 'tight');
axes(f, 'Position', positionVector4);
imshow(I, 'border', 'tight');
Setting the position manually is not the best solution.
There must be a way to compute the position of each axes.
Result:
So I want the RGB values of an image placed into an histogram and then that histogram will be compared to other image's histogram.
Currently this is the code:
if (size(cimg, 3) ~= 3)
error('rgbhist:numberOfSamples', 'Input image must be RGB.')
end
nBins = 256;
rHist = imhist(cimg(:,:,1), nBins);
gHist = imhist(cimg(:,:,2), nBins);
bHist = imhist(cimg(:,:,3), nBins);
hFig = figure;
%figure
subplot(1,2,1);imshow(cimg)
subplot(1,2,2);
hold on
h(1) = stem(1:256, rHist); %hold on
h(2) = stem(1:256 + 1/3, gHist, 'g');
h(3) = stem(1:256 + 2/3, bHist, 'b');
hold off
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])
axis square
The code outputs the image along with its RGB histogram value, how can I use that histogram to compare it with other histograms so that I could potentially classify the image as having nearly the same colors as that of another image?
You could use Kullback Leibler Divergence to calculate the distance between 2 histograms.
This is easy as you can treat the Histogram as a distribution.
Since the KL Divergence isn't symmetric one could compute it twice (Namely [X, Y] and [Y, X]) and take the average.
I know the hold on; command in octave allows me to plot multiple trajectories in the same figure. However, i recently came across the function 'comet'. It animates the state of a system over the time range defined by the user. I have only successfully used it for a simple code which shows the trajectory of a small body around a fixed massive body. How can I use 'comet' to animate the trajectories of 2 bodies over the same time range?
PS: If you need an example of how 'comet' works, here is the simple code i mentioned above:
function xdot = f(x,t)
G = 1.37;
M = 10^5;
[T,r] = cart2pol(x(1),x(2));
xdot(3) = -((G*M)/((x(1)^2) + (x(2)^2)))*cos(T);
xdot(4) = -((G*M)/((x(1)^2) + (x(2)^2)))*sin(T);
xdot(1) = x(3);
xdot(2) = x(4);
endfunction
X = lsode ("f", [1000,0,5,10],(t = linspace(0,1000,2000)'));
comet(X(:,1),X(:,2),0.01);
This basically plots the trajectory over time. You can copy paste to octave and see the animation.
Can anyone tell me how I can doe the same for a 2 body or multiple body system ?
You can't really use comet in that way. You'll have to do the 'animation' manually, but it's not hard. Plus, you get better customisability. Here's one approach.
X1 = lsode ("f", [1000, 0, 5, 10], (t = linspace(0,1000,2000)'));
X2 = lsode ("f", [500, 0, 4, 5 ], (t = linspace(0,1000,2000)'));
x_low = min ([X1(:, 1); X2(:, 1)]); x_high = max ([X1(:, 1); X2(:, 1)]);
y_low = min ([X1(:, 2); X2(:, 2)]); y_high = max ([X1(:, 2); X2(:, 2)]);
for n = 1 : size (X1, 1)
plot (X1(1:n, 1), X1(1:n, 2), ':', 'color', [0, 0.5, 1], 'linewidth', 2);
hold on;
plot (X1(n, 1), X1(n, 2), 'o', 'markerfacecolor', 'g', 'markeredgecolor', 'k', 'markersize', 10);
plot (X2(1:n, 1), X2(1:n, 2), ':', 'color', [1, 0.5, 0], 'linewidth', 2);
plot (X2(n, 1), X2(n, 2), 'o', 'markerfacecolor', 'm', 'markeredgecolor', 'k', 'markersize', 10);
hold off;
axis ([x_low, x_high, y_low, y_high]); % needed, otherwise first few plots will
% use automatic axis limits
drawnow; pause(0.01);
end
This is the most straightforward way, but its speed might not be as fast as 0.01, if the refresh rate is slower than the time it takes to produce the plot; you can make it even faster if you only plot once and change the data of each plot object at each step instead.
Also, this 'animation' is simply for visualising inside an octave session. If you want to produce a video file from this instead, you'll have to produce images and convert to a movie / gif format etc.
I am developing some routines in Octave and need to display an image, then plot a curve on top which will hopefully overlay some image features.
However, I cannot work out how to match the origin/scale of the image and the plot. For example, given a 1024x1024 pixel image I can do:
a=imread('image.png');
x=linspace(1,1024,100);
y=x;
imshow(a);
hold on;
plot(x,y);
But the line is not scaled to the image and does not start at a corner. (I know that the image and plot should have origins in different corners). When I examine the graphic coordinates from the cursor position, the image is clearly not at the origin, so I guess this is the basis of the problem.
Use image() instead of imshow() in this case
a = imread ('image.png');
x = linspace (1, 1024, 100);
y = x;
image (a);
hold on
plot (x, y);
axis square
You can plot functions over images this way:
Create an image called stuff.jpg like this, any size is possible but I made mine roughly 6x6 pixels so I could test:
You can plot functions over other functions this way:
octave> x = 0:1:5;
octave> plot(x, (3/2).^x, "linewidth", 2, "color", "blue");
octave> hold on
octave> plot(x, 2.^x, "linewidth", 2, "color", "red");
octave> plot(x, factorial(x), "linewidth", 2, "color", "green");
octave> plot(x, x.^3, "linewidth", 2, "color", "black");
octave>
For me it shows this:
Found that here, it has a walkthrough:
http://ericleschinski.com/c/algorithm_complexity_big_o_notation/
Which plots my power level given my age. It's already over nine thousand.
The problem with image is that it puts (0,0) (rather (min_x,min_y)) at upper-left while we usually expect (0,0) to be at bottom-left.
Also it only uses max and min values of the x and y vectors so doing y(end:-1:1) doesn't work.
im = imread('file.png'); %read the file
image([xmin xmax],[ymin ymax],im(end:-1:1,:,:)); %put the image on the screen upside down
axis('xy'); % flip the image by putting (0,0) at bottom left. Image now right side up
axis('square'); if you want to aspect ratio of the image to be 1:1
hold on;
plot([xmin xmax],[ymin ymax]) % this should draw a diagonal from bottom left to upper right.
% plot whatever you want to overlay
If I make a 4 pixel by 4 pixel image in Matlab using the image() command, it centers the tick marks in the middle of the pixels. I want the tick marks to be centered on the lower left corner of the pixel. Is there some way to do this?
You can specify x and y coordinates of the pixels and shift them by 0.5:
image([0.5,3.5],[0.5,3.5],magic(4))
I think this code will do what you want. It places tick marks only at the edges of the pixels:
A = ...; %# Your 4-by-4 matrix
image([0.5 3.5],[0.5 3.5],A); %# Pixel edges are at 0, 1, 2, 3, and 4
set(gca,'XTick',0:4,'YTick',0:4); %# Place tick marks at 0, 1, 2, 3, and 4
Try the following:
a = randi([0 255], [4 4]);
figure, imagesc(a), caxis([0 255])
b = zeros( size(a)+1 );
b(1:end-1,1:end-1) = a;
figure, pcolor(b), caxis([0 255]), axis ij
Note that I extended the matrix a because pcolor drops the last row/column.