8-bit color image matrix representation - image

I have just started learning image processing by myself, and I am using MATLAB. I have been getting myself familiarized with basic image operations. When I read the below image(res: 225x300), which is supposed to be an 8-bit color image, I expected the resultant matrix to have 3 dimensions with one each for RGB. A simple web search about 8-bit color image led me to Wikipedia with the following information:
The simplest form of quantization frequently called 8-bit truecolor is to simply assign 3 bits to red, 3 to green and 2 to blue (the human eye is less sensitive to blue light) to create a 3-3-2.
Therefore, I expected the image matrix to have 225x300x3 dimensions with the above distribution of bits b/w RGB. But after I checked the dimensions of the matrix of the image, I found it to be 225x300 unit8, which is what one expects from an 8-bit grayscale image. But the image is a color image, as seen by any image viewer. So what is that I lack in knowledge or doing wrong? Is the problem with how I read the image?
Also, it occurred to me that uint8 is the smallest unsigned integer class. So how can we have colored images of 4,8,10, etc., bits represented and created?
My code:
>> I_8bit = imread('input_images\8_bit.png');
>> size(I_8bit)
ans =
225 300
>> class(I_8bit)
ans =
'uint8'
>> I_24bit = imread('input_images\24_bit.png');
>> size(I_24bit)
ans =
225 300 3
>> class(I_24bit)
ans =
'uint8'
(source: https://en.wikipedia.org/wiki/Color_depth#/media/File:8_bit.png)

Matlab supports several types of images, including
RGB images, which allow arbitrary colors, stored in terms of R,G,B components. The image is defined by a 3D m×n×3 array
Indexed images, in which each pixel is defined by an index to a colormap. The image is defined by a 2D m×n array and a c×3 colormap, where c si the number of colors.
It looks like the image you are loading is indexed. So you need the two-output version of imread to get the 2D array and the colormap:
[I_8bit, cmap] = imread('input_images\8_bit.png');
To display the image you need to specify the 2D array and the colormap:
imshow(I_8bit, cmap)
You can see the effect of changing the colormap, for example
cmap_wrong = copper(size(cmap, 1)); % different colormap with the same size
imshow(I_8bit, cmap_wrong)
To convert to an RGB image, use ind2rgb:
I_8bit_RGB = ind2rgb(I_8bit, cmap);
which then you can display as
imshow(I_8bit_RGB)

Related

How to filter out the background in an RGB image(Matlab)? [duplicate]

I have converted my image into a mask and I would now like to obtain what the original colours were given this mask. I have an array called objectPixels that determines which locations belong to the object I am segmenting out. I have tried the code below but I am not obtaining the original colours.
What am I doing wring?
mask = false(size(grayImage));
mask(objectPixels) = true;
%on R channel
tmp = originalImage(:,:,1);
If I understand your question properly, you have a mask of pixels that belong to some objects. You now wish to find an image where any pixels that are labeled true will provide the original colour at these locations while false we skip. I'm going to assume that the output pixels are black if the mask locations are false. This can easily be computed using bsxfun with times as the function. We would essentially replicate the mask for each colour channel in your image, then multiply the mask with the original image.
As such:
out = bsxfun(#times, originalImage, cast(mask, class(originalImage)));
mask is originally a logical array, and in order to multiply both the mask and your original image together, they must be the same type, and that's why cast is used so that we can cast the image to the same type as the original image. We use class to determine the class or type of the original image.
As an example, let's use the onion.png image that's part of MATLAB's system path. I'm going to convert this image to grayscale using rgb2gray then choose an arbitrary threshold of graylevel 100 to give us a mask. Anything greater than 100 will give a mask value of true, while anything else is set to false.
Once I generate this mask, let's figure out what the original colours were based on these mask values. As such:
originalImage = imread('onion.png');
mask = rgb2gray(originalImage) >= 100;
out = bsxfun(#times, originalImage, cast(mask, class(originalImage)));
%// Show the images now
figure;
subplot(1,3,1);
imshow(im);
title('Original Image');
subplot(1,3,2);
imshow(mask);
title('Mask');
subplot(1,3,3);
imshow(out);
title('Output Image');
With the above code, I implement the logic I was talking about, with an additional figure that shows the original image, the mask generated as well as the output image that shows you the original colours of where the mask locations were true.
This is what I get:

Coloring an 8-bit grayscale image in MATLAB

I have an 8-bit grayscale image with different values (0,1,2,3,4,..., 255). What I want to do is color the grayscale image with colors like blue, red, etc. Until now, I have been doing this coloring but only in a greyscale. How can I do it with actual colors?
Here is the code I have written so far. This is where I am searching for all values that are white in an image and replacing them with a darkish gray:
for k = 1:length(tifFiles)
baseFileName = tifFiles(k).name;
fullFileName = fullfile(myFolder, baseFileName);
fprintf(1, 'Now reading %s\n', fullFileName);
imageArray = imread(fullFileName);
%// Logic to replace white grayscale values with darkish gray here
ind_plain = find(imageArray == 255);
imageArray(ind_plain) = 50;
imwrite(imageArray, fullFileName);
end
What you are asking is to perform a pseudo colouring of an image. Doing this in MATLAB is actually quite easy. You can use the grayscale intensities as an index into a colour map, and each intensity would generate a unique colour. First, what you need to do is create a colour map that is 256 elements long, then use ind2rgb to create your colour image given the grayscale intensities / indices of your image.
There are many different colour maps that are available to you in MATLAB. Here are the current available colour maps in MATLAB without the recently added Parula colour map that was introduced in R2014:
How the colour maps work is that lower indices / grayscale values have colours that move toward the left side of the spectrum and higher indices / grayscale values have colours that move toward the right side of the spectrum.
If you want to create a colour map with 256 elements, you simply use any one of those colour maps as a function and specify 256 as the input parameter to generate a 256 element colour map for you. For example, if you wanted to use the HSV colour map, you would do this in MATLAB:
cmap = hsv(256);
Now, given your grayscale image in your MATLAB workspace is stored in imageArray, simply use ind2rgb this way:
colourArray = ind2rgb(double(imageArray)+1, cmap);
The first argument is the grayscale image you want to pseudocolour, and the second input is the colour map produced by any one of MATLAB's colour mapping functions. colourArray will contain your pseudo coloured image. Take note that we offset the grayscale image by 1 and also cast to double. The reason for this is because MATLAB is a 1-indexed programming language, so we have to start indexing into arrays / matrices starting at 1. Because your intensities range from [0,255], and we want to use this to index into the colour map, we must make this go from [1,256] to allow the indexing. In addition, you are most likely using uint8 images, and so adding 1 to a uint8 will simply saturate any values that are already at 255 to 255. We won't be able to go to 256. Therefore, you need to cast the image temporarily to double so that we can increase the precision of the image and then add 1 to allow the image to go to 256 if merited.
Here's an example using the cameraman.tif image that's part of the image processing toolbox. This is what it looks like:
So we can load in that image in MATLAB like so:
imageArray = imread('cameraman.tif');
Next, we can use the above image, generate a HSV colour map then pseudocolour the image:
cmap = hsv(256);
colourArray = ind2rgb(imageArray+1, cmap);
We get:
Take note that you don't have to use any of the colour maps that MATLAB provides. In fact, you can create your own colour map. All you have to do is create a 256 x 3 matrix where each column denotes the proportion of red (first column), green (second column) and blue (third column) values per intensity. Therefore, the first row gives you the colour that is mapped to intensity 0, the second row gives you the colour that is mapped to intensity 1 and so on. Also, you need to make sure that the intensities are floating-point and range from [0,1]. For example, these are the first 10 rows of the HSV colour map generated above:
>> cmap(1:10,:)
ans =
1.0000 0 0
1.0000 0.0234 0
1.0000 0.0469 0
1.0000 0.0703 0
1.0000 0.0938 0
1.0000 0.1172 0
1.0000 0.1406 0
1.0000 0.1641 0
1.0000 0.1875 0
1.0000 0.2109 0
You can then use this custom colour map into ind2rgb to pseudocolour your image.
Good luck and have fun!

Make a representative HSV image in matlab

I want to create an HSV image (or maybe a coordinate map) which shows that coordinates accurately.
I am using the following code and get an image like this the result of the following code which is not what I want.
img = rand(200,200);
[ind_x, ind_y] = ind2sub(size(img),find(isfinite(img)));
ind_x = reshape(ind_x,size(img));
ind_y = reshape(ind_y,size(img));
ind = ind_x.*ind_y;
figure, imagesc(ind); axis equal tight xy
Lets say you quantize the HSV space (0-1) into 256 bins. There will be 256*256*256 possible colors. We could fix a dimension (say saturation) and generate the matrix. Then there will be 256*256 colors.
[x1,x2]=meshgrid(linspace(0,1,256),linspace(0,1,256));
img(:,:,1)=x1;
img(:,:,2)=1; %fully saturated colors
img(:,:,3)=x2;
imgRGB=hsv2rgb(img); %for display purposes
imshow(imgRGB,[])
It will look different in RGB (that's where you would visualize). It looks similar to your image if you visualize HSV matrix (i.e. without converting it to RGB, but MATLAB doesn't know that its HSV)
imshow(img,[]);
The second image you have posted can be obtained with:
[x1,x2]=meshgrid(linspace(0,1,256),linspace(0,1,256));
img(:,:,1)=x1;
img(:,:,2)=0;
img(:,:,3)=x2;
imshow(img,[]) %visualizing HSV

count number of non gray pixels in RGB image in matlab

I have a RGB image which has only black and white squares. I want to count number to non gray pixels in this image. I am new to matlab. I want to check the quality of image as it should only contain black and white pixels.Actually I have undistorted this image due that some colored fringes are appeared.I want to know the how many color are introduced to check the quality of the image.
using matlab to get counts of specific pixel values in an image.
Images are RGBA <512x512x4 uint8> when read into matlab (although we can disregard the alpha channel).
Something like this
count = sum(im(:, :, 1) == 255 & im(:, :, 3) == 255 & im(:, :, 3) == 255);
will give you the count of such pixels. Replace sum with find to get the indices of those pixels if you need that.
A pixel is said to be gray if its R,G,B components are all same.
Using this logic
%// checking for equality of R,G,B values
B = any(diff(im,[],3),3); %// selecting only non-gray pixels
count = sum(B(:)); %// Number of non-gray pixels
PS: This answer is tailored from this and this answer.

Extracting numerical data from an intensity printout

I'm looking to create an intensity matrix in Matlab from an intensity image plot (saved as a jpeg (RGB) file) that was made using what appears to be the jet colormap from Matlab. I am essentially trying to reverse engineer the numerical data from the plot. The original image along with the color bar is linked (I do not have enough reputation to insert images).
http://i.imgur.com/BmryO6W.png
I initially thought this could be done with the rgb2gray command, but it produces the following image with the jet colormap applied which does not match the original image.
http://i.imgur.com/RlBei2z.png
As far as I can tell, the only route available from here is to try matching the RGB value for each pixel to a value in the colormap lookup table. Any suggestions on if this the fastest approach?
It looks like your method using rgb2gray is almost working, apart from the scale. Because the colormap is scaled automatically to the contents of your plot, I think you will have to re-scale it manually (unless you can automatically detect the tick labels on the colorbar). You can do this using the following formula:
% Some random data like yours
x = rand(1000) * 256;
% Scale data to fit your range
xRange = [min(x(:)) max(x(:))];
scaleRange = [-10 10];
y = (x - xRange(1)) * diff(scaleRange) / diff(xRange) + scaleRange(1);
You can check the operation's success with
>> [min(y(:)) max(y(:))]
ans =
-10 10

Resources