Contour matrices in MATLAB - matlab

How can I get contour matrix for a binary image in MATLAB?

See this tutorial Luke Fletcher
In general it says:
%Load the image into im_rgb with
im_rgb = imread('tetx.tiff');
%convert to type double
im_rgb = double(im_rgb);
%convert to grey-scale
im_grey = (im_rgb(:,:,1)+im_rgb(:,:,2)+im_rgb(:,:,3))/3;
%or you can use rgb2gray which gives a slightly different result since it converts
%to a luminance rather than an intensity image, you'll learn about this
%in the lecture on colour imaging.
%convert from [0,255] to [0,1]
im_grey = im_grey/255;
%to view an image use either imshow(im) or imagesc(im), note the difference.
%You can use imagesc and then set the axis for an image with
axis image;
%Axis labelling can be turned on and off by
axis on;
axis off;
etc...

Related

Matlab overlay imagesc on binary image

I am trying to overlay an imagesc image on top of a binary image. I searched for it online, but no luck. Below is my code:
figure;
imshow(BW4);
hold on
imagesc(image2,'AlphaData',0.5); axis equal; axis tight; axis off;
myColorMap = jet(256);
myColorMap(1,:) = 0;
colormap(myColorMap); colorbar;
hold off
The output what I am getting looks like below image on right, instead of the jet colormap lines on top of white color. Can someone help me to fix this issue? I appreciate your time and effort.
Thanks,
Binary image
Jet image
Result what I am getting which I do not want
So we first read your bw data a and create some jet image b which is some nxm matrix of intensities:
a=rgb2gray(imread('fFIG2.png'));
a=a==max(a(:));
a=a>0; % now it is binary
% make jet data with 0 being it's minimal value
b=(imresize(peaks(100),size(a))).*a ;
b=b.*(b>0);
Now we normalize the data in b between 0 and 1 and make an RGB array out of it. The we'll create a mask and assign white to it...
cmap=[0,0,0;jet(255)]; % set the colormap to be always black and jet
% normalize from nxm matrix to nxmx3 rgb values
c=b;
c=round( ((c-min(c(:)) )/(max(c(:))-min(c(:))))*(length(cmap)-1)+1);
im=reshape(cmap(c(:),:),[size(c),3]);
% get the mask for all pixels that are in a but are zero in b
bw2=repmat( (a>0 & b==0),[1 1 3]);
im(bw2)=1; % assign this pixels with rgb=white
imagesc(im)

How can I convert an RGB histogram into a color spectrum?

How can I convert an RGB histogram of an image to create a histogram showing the combined colors along with correct color wavelength range?
Example code:
pkg load image
f=imread('/tmp/marbles.jpg');
f=uint8(f); %need to convert back to uint8 to show picture
%Split into RGB Channels
f_red = f(:,:,1);
f_green = f(:,:,2);
f_blue = f(:,:,3);
%Get histValues for each channel
[y_f_red, x] = imhist(f_red);
[y_f_green, x] = imhist(f_green);
[y_f_blue, x] = imhist(f_blue);
subplot (2,1,1); imshow(f);
subplot (2,1,2); plot(x, y_f_red, 'r', x, y_f_green, 'g', x, y_f_blue, 'b');
Example image along with separate RGB histogram the code produces:
I'm trying to get the histogram to look like the image below but have the colors go from red to blue:
Another image example:
PS: I'm using Octave 4.0 which is very similar to MATLAB.
There's a huge hurdle to converting between standard color representations (like RGB or HSV) and spectral wavelength: many colors can't be represented by a single wavelength of light. Colors such as magenta, pink, brown, or any grayscale color represent mixtures of different wavelengths. Generating an equivalent spectral wavelength is therefore a much more complicated endeavor (you may find some useful ideas and links here and here).
Creating histograms of the colors themselves may be a better way to go (illustrated in one of my other answers), but if you really want to relate color to wavelength in a simple fashion you can try the following...
A first step will be to convert RGB values to HSV values, then create a histogram of the hue channel. I'll adapt part of my answer from here to do that. The next step will be to map hues to wavelengths of light, using some rather gross approximations adapted from this answer:
rgbImage = imread('test_image.png'); % Load image
hsvImage = rgb2hsv(rgbImage); % Convert the image to HSV space
hPlane = 360.*hsvImage(:, :, 1); % Get the hue plane scaled from 0 to 360
binEdges = 0:270; % Edges of histogram bins
N = histc(hPlane(:), binEdges); % Bin the pixel hues from above
wavelength = 620-(170/270).*(0:269); % Approximate wavelength
hBar = bar(wavelength, N(1:end-1), 'histc'); % Plot the histogram
set(hBar, 'CData', 270:-1:1, ... % Change the color of the bars using
'CDataMapping', 'direct', ... % indexed color mapping (360 colors)
'EdgeColor', 'none'); % and remove edge coloring
colormap(hsv(360)); % Change to an HSV color map with 360 points
axis([450 620 0 max(N)]); % Change the axes limits
set(gca, 'Color', 'k'); % Change the axes background color
set(gcf, 'Pos', [50 400 560 200]); % Change the figure size
xlabel('Wavelength (nm)'); % Add an x label
ylabel('Bin counts'); % Add a y label
NOTE: For the above to work properly in Octave, it may be necessary to change the set(hBar, ... line to the following:
set(hBar, 'FaceColor', 'flat', 'EdgeColor', 'none');
set(get(hBar, 'Children'), 'CData', 270:-1:1, 'CDataMapping', 'direct');
And here's the histogram:
There is, however, one issue with this. If we instead use the code exactly as it is in my other answer to plot the histogram of all the hue values, we would get this:
Note that there is a big cluster of magenta, pink, and reddish pixels that gets excluded when we toss out part of the hue range to convert to wavelengths (they don't correspond to a single wavelength in the light spectrum). Incorporating these into the results would require a more complicated conversion from hue to wavelength.
you can not convert RGB to wavelength unless some physical properties of the image and light is met. Anyway you can fake this by inversing:
RGB values of visible spectrum
if you do not know how look at:
Reverse complex 2D lookup table
But the result will not be the same as physical wavelengths histogram ... For that you would need multi-band image acquisition either by rotating prism optics or by set of bandpass filters ...
PS. HSV is far from accurate ...
Btw. the easiest way to do this is create palette from the spectral colors and convert your input image to it (indexed colors) and then just create histogram sorted by wavelength (and or color index)...
Based on gnovices answer but with an image instead of bar (take 0.12s on my system):
rgbImage = imread ("17S9PUK.jpg");
hsvImage = rgb2hsv(rgbImage);
hPlane = 360 .* hsvImage(:, :, 1);
binEdges = 1:360;
N = histc (hPlane(:), binEdges);
cm = permute (hsv (360), [3 1 2]);
img = repmat (cm, max(N), 1);
row_index = max(N) - N';
sp = sparse (row_index(row_index>0), (1:360)(row_index>0), true);
mask = flipud (cumsum (sp));
img(repmat (logical(1 - full(mask)), [1 1 3])) = 0;
image (img)
set (gca, "ydir", "normal");
xlabel('hue');
ylabel('Bin counts');

How to draw box plot of the objects from regionprops?

I would like to plot the mean and percentile as shown in figure.I tried some code to plot box plot but I'm getting something different
I = propsSynthesizeImage;
imshow(I)
title('Synthetic Image')
% Create a Binary Image
% Segment the grayscale image by creating a binary image containing the objects in the image.
BW = I > 0;
imshow(BW)
title('Binary Image')
s = regionprops(BW, I, {'Centroid','PixelValues','BoundingBox'});
imshow(I);
numObj = numel(s);
title('Standard Deviation of Regions');
hold on
for k = 1 : numObj
s(k).StandardDeviation = std(double(s(k).PixelValues));
text(s(k).Centroid(1),s(k).Centroid(2), ...
sprintf('%2.1f', s(k).StandardDeviation), ...
'EdgeColor','b','Color','r');
end
figure
boxplot(1:numObj,[s.StandardDeviation])
xlabel('Region Label Number');
ylabel('Standard Deviation');
hold off
The boxplot visualizes a distribution. Currently, you're plotting scalars.
To plot the distribution (and have Matlab find median, quantiles, etc), plot
boxplot(1:numObj,{s.PixelValues})
Note that boxplot will not show standard deviations (instead, it shows the inter-quartile range), and that it may give misleading results if the underlying pixel values have a multi-modal distribution.

How to plot a 2D FFT in Matlab?

I am using fft2 to compute the Fourier Transform of a grayscale image in MATLAB.
What is the common way to plot the magnitude of the result?
Assuming that I is your input image and F is its Fourier Transform (i.e. F = fft2(I))
You can use this code:
F = fftshift(F); % Center FFT
F = abs(F); % Get the magnitude
F = log(F+1); % Use log, for perceptual scaling, and +1 since log(0) is undefined
F = mat2gray(F); % Use mat2gray to scale the image between 0 and 1
imshow(F,[]); % Display the result
Here is an example from my HOW TO Matlab page:
close all; clear all;
img = imread('lena.tif','tif');
imagesc(img)
img = fftshift(img(:,:,2));
F = fft2(img);
figure;
imagesc(100*log(1+abs(fftshift(F)))); colormap(gray);
title('magnitude spectrum');
figure;
imagesc(angle(F)); colormap(gray);
title('phase spectrum');
This gives the magnitude spectrum and phase spectrum of the image. I used a color image, but you can easily adjust it to use gray image as well.
ps. I just noticed that on Matlab 2012a the above image is no longer included. So, just replace the first line above with say
img = imread('ngc6543a.jpg');
and it will work. I used an older version of Matlab to make the above example and just copied it here.
On the scaling factor
When we plot the 2D Fourier transform magnitude, we need to scale the pixel values using log transform to expand the range of the dark pixels into the bright region so we can better see the transform. We use a c value in the equation
s = c log(1+r)
There is no known way to pre detrmine this scale that I know. Just need to
try different values to get on you like. I used 100 in the above example.

How to get image matrix from axes content

Is there a way to get the content of a contourf plot as an image matrix? I want rasterize only the content, not the axes, labels and the empty space of the entire figure.
My goal is to overlay a transparent, colored contour plot over a grayscale image and I don't see another way, since MATLAB has only one colormap per figure.
Try getframe and frame2im
Example from the frame2im documentation:
Create and capture an image using getframe and frame2im:
peaks %Make figure
f = getframe; %Capture screen shot
[im,map] = frame2im(f); %Return associated image data
if isempty(map) %Truecolor system
rgb = im;
else %Indexed system
rgb = ind2rgb(im,map); %Convert image data
end
Not a direct answer to the question, but this is how I think you could achieve your goal:
%# load in grayscale image
gray_im = rgb2gray(imread('peppers.png'));
%# converting n x m grey image to n x m x 3 rgb gray image
rgb_gray_im = cat( 3, gray_im, gray_im, gray_im );
%# displaying this image
imshow( rgb_gray_im );
%# plotting contourf on top with arbitrary colourmap
hold on
h = axes('position', [0.5, 0.5, 0.2, 0.2]);
z = peaks;
contourf(h, z, [min(z(:)), -6 : 8]);
Which gives the result:
The figure's colourmap is being used for the contourf plot. The background image is not relying on a colourmap, and is instead being displayed in truecolour - i.e. each pixel is being displayed as an RGB value defined in rgb_gray_im.
There are also other ways of getting around the MATLAB colourmap restrictions: see for example this blog post or these answers.