Saving an image after using range display - matlab

I am using kmeans clustering to segment an image. My function returns values between 1-3 with the same size as the input image, then I am using imshow(L, []); to display the image but I cannot find a way which would save the image exactly the same as displayed on the screen

You can use mat2gray to map the values in your matrix L to values between 0 (black) and 1 (white), similar as what imshow(L, []) does. Then use imwrite to save the image.
L = 1 + (3-1).*rand(500); % 500-by-500 image with values between 1 and 3
figure(1); clf;
imshow(L, [])
Img = mat2gray(L);
figure(2); clf;
imshow(Img)
imwrite(Img, 'yourimage.png')

Related

Read Index RGB File and convert to Grey Scale Image - What is double, thinning and Inverted Images Format

I am trying to read GIF file and display in below following format -
Grey Scale
Resized
Double Image
Thinning
Inverted
Below is my code to do the same (incomplete):
clear all;
close all;
clc;
%Various preprocessing of Images
checkimage=imread('CheckSign/sign.gif');
checkimage_resize=imresize(checkimage,[512, 512]);
checkimage_grey=rgb2gray(checkimage_resize);
[m n p] = size(checkimage_grey)
for i=1:n
for j=1:m
if(checkimage_grey(i,j) ~= 0)
bimage(i,j) = 1;
else
bimage(i,j) = 0;
end
end
end
subplot (2,3,1),imshow(checkimage),title('Original Image');
subplot (2,3,2),imshow(checkimage_resize),title('Resized Image');
subplot (2,3,3),imshow(checkimage_grey),title('Grey Scale Image');
subplot (2,3,4),imshow(bimage),title('Binary Image');
But I get the below error:
Error using rgb2gray>parse_inputs (line 81)
MAP must be a m x 3 array.
Error in rgb2gray (line 35)
X = parse_inputs(varargin{:});
Error in preprocessing (line 8)
checkimage_grey=rgb2gray(checkimage_resize);
On viewing the image in imtool I see a pixel info as:
Pixel (X,Y) index [R,G,B]
<213>
R 0.80
G 0.80
B 1.00
Now I am not sure how to read this kind of index file and convert to grey scale one?
Also how do I change the image in concern to double, thinning and Inverted Imagesformat?
If I not wrong is inverted image as 1 - bimage?
For indexed images you need to read the index as well as the colorap
[ind map] = imread( 'CheckSign/sign.gif' );
Once you have all the information you need you can use ind2rgb to convert the index map into RGB image
checkimage_rgb = ind2rgb( ind, map );
You do not need a nested for-loop to "invert" the colors, it's enough
bimage = checkimage_grey ~= 0;
inverted = 1 - bimage;

MATLAB Auto Crop

I am trying to automatically crop the image below to a bounding box. The background will always be the same colour. I have tried the answers at
Find the edges of image and crop it in MATLAB
and various applications and examples on Mathworks' file exchange but I get stuck at getting a proper boundingbox.
I was thinking to convert the image to black and white, converting it to binary and removing everything that's closer to white than black, but I'm not sure how to go about it.
Here's a nice way
img = im2double(imread('http://i.stack.imgur.com/ZuiEt.jpg')); % read image and convert it to double in range [0..1]
b = sum( (1-img).^2, 3 ); % check how far each pixel from "white"
% display
figure; imshow( b > .5 ); title('non background pixels');
% use regionprops to get the bounding box
st = regionprops( double( b > .5 ), 'BoundingBox' ); % convert to double to avoid bwlabel of logical input
rect = st.BoundingBox; % get the bounding box
% display
figure; imshow( img );
hold on; rectangle('Position', rect );
Following Jak's request, here's the second line explained
after converting img to double type (using im2double), the image is stored in memory as h-by-w-by-3 matrix of type double. Each pixel has 3 values between 0 and 1 (not 255!), representing its RGB values 0 being dark and 1 being bright.
Thus (1-img).^2 checks, for each pixel and each channel (RGB) how far it is from 1 - bright. The darker the pixel - the larger this distance.
Next, we sum the distance per channel to a single value per pixel using sum( . ,3 ) command leaving us with h-by-w 2D matrix of distances of each pixels from white.
Finally, assuming background is bright white we select all pixels that are significantly far from birght b > .5. This threshold is not perfect, but it captures well the boundary of the object.
Following the answer of Shai, I present a way to circumvent regionprops (image processing toolbox) just based on find on the black-white image.
% load
img = im2double(imread('http://i.stack.imgur.com/ZuiEt.jpg'));
% black-white image by threshold on check how far each pixel from "white"
bw = sum((1-img).^2, 3) > .5;
% show bw image
figure; imshow(bw); title('bw image');
% get bounding box (first row, first column, number rows, number columns)
[row, col] = find(bw);
bounding_box = [min(row), min(col), max(row) - min(row) + 1, max(col) - min(col) + 1];
% display with rectangle
rect = bounding_box([2,1,4,3]); % rectangle wants x,y,w,h we have rows, columns, ... need to convert
figure; imshow(img); hold on; rectangle('Position', rect);
to crop an image
first create boundry box where you want to crop.
crp = imcrop(original_image_name,boundry_box);
I have done this in my assignment. This really works!!!!!!

How to convert RGB images to grayscale in matlab without using rgb2gray

I'm currently using code:
i = imread('/usr/share/icons/matlab.png');
for k=1:1:m
for l=1:1:n
%a(k,l)=m*n;
a(k,l) = (.299*i(k,l,1))+(.587*i(k,l,2))+(.114*i(k,l,3));
end
end
imshow(a);
It shows only a white screen. Also the newly generated dimensions are n x m x 3 whereas it should be only m x n x 1.
If I use mat2gray it display the image like this
Since the image is a PNG, imread() is returning an integer image, with intensity values in the range [0 255] or equivalent, depending on the original bit depth. The conversion formula makes a a double image, which is expected to have intensities in the range [0 1]. Since all the pixel values in a are probably much greater than 1, they get clipped to 1 (white) by imshow().
The best option is to explicitly convert the image format before you start - this will take care of scaling things correctly:
i = imread('/usr/share/icons/matlab.png');
i = im2double(i);
a = .299*i(:,:,1) + .587*i(:,:,2) + .114*i(:,:,3); % no need for loops
imshow(a);
input=imread('test.jpg');
subplot(1,2,1), imshow(input), title('RGB Scale image');
[x,y,~] = size(input);
for i = 1:1:x
for j = 1:1:y
output(i,j) = 0.40*input(i,j,1) + 0.50*input(i,j,2) + 0.30*input(i,j,3);
end
end
subplot(1,2,2), imshow(output), title('Gray Scale image');

Difficulty with my self built histogram in MatLab

I am trying to implement a simple function that its the same with the default hist() by MatLab.
We have two same images with different brightness and we have to convert them to grayscale and then use the default function of MatLab hist() to get the histograms (so far so good!).
Then we have to implement the function hist my_hist() , and when i am trying to count the frequency of the intensity the results are not the same.
It seems that it sums-up the frequency of 254 & 255 to 254 and 255 is zero!I dont know what the problem is, any help would be appreciated.
here is the code for the command line:
%Read the images and convert them from rgb to grayscale
i=imread('pic1.jpg');
j=rgb2gray(i);
x=imread('pic2.jpg');
y=rgb2gray(x);
%Display the two images
figure
imshow(j)
figure
imshow(y)
%Display the histogram of the two images
[a,b] = hist(j(:),0:1:255);
figure
plot(b,a)
[c,d]=hist(y(:),0:1:255);
figure
plot(d,c)
%Call of the built-in function
my_hist('pic1.jpg','pic2.jpg')
And here is the code of the self built function:
function []= my_hist( x,y)
%Read the images and convert them from rgb to grayscale
pic1=imread(x);
i=rgb2gray(pic1);
pic2=imread(y);
j=rgb2gray(pic2);
%Initialize two vectors to be the axis for histogram
plotx=0:255;
ploty=zeros(1,256);
%Take the dimensions of the first image pic1
[m,n] = size(i);
%With 2 loops we go through the matrix of the image and count how many
%pixels have the same intensity
for k=1:m
for l=1:n
num=i(k,l)+1;
ploty(num)=ploty(num)+1;
end
end
%Display the histogram for the first image pic1
figure
plot(plotx,ploty);
%Initialize two vectors to be the axis for histogram
plotx2=0:255;
ploty2=zeros(1,256);
%Take the dimensions of the second image pic2
[m2,n2] = size(j);
%With 2 loops we go through the matrix of the image and count how many
%pixels have the same intensity
for o=1:m2
for p=1:n2
num2=j(o,p)+1;
ploty2(num2)=ploty2(num2)+1;
end
end
%Display the histogram for the second image pic2
figure
plot(plotx2,ploty2);
end
And here are the images pic1 and pic2.
This is a problem due to your image being of integer type uint8 which can only range from 0-255:
>> a= uint8(255)
a =
255
>> a=a+1
a =
255
Convert your data to say type uint16 with
j = uint16(j);
y = uint16(y);
and your problem should be gone:
>> a=uint16(a)
a =
255
>> a=a+1
a =
256

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.