I have observed that whenever I use the command imagesc(image); the resultant image has some regions that are yellow in colour and the background is red.
Is there any way to segment these regions of the images ? If there is not do they have any similar pattern that can be used for thresholding or is the colour representation meaningless?
I am using Matlab R2012a on Windows.
When you are using imagesc (short for image scale), you are visualizing a matrix by mapping the lowest value of that matrix to one end of a colormap, and the highest value of the matrix to the other end.
By default, MATLAB uses the jet() colormap which is the normal RGB-colorrange. If some parts of your image turns out to be yellow, it means that the elements of the matrix has been some spesific place between the highest and lowest value.
The example below hopefully illustrates this more clearly and shows how you can segment out the "yellow" regions of a matrix (which doesn't really have any color per se)
colorRes = 256;
%# In a jet colormap with size 256, yellow is at placement 159
yellow = 159;
yellowScale = ((yellow/256));
image = repmat(1:colorRes,40,1);
figure(1);clf;
colormap(jet(colorRes))
subplot(2,1,1)
imagesc(image)
title('Original image')
%# Segment out yellow
colorDist = 1/colorRes*5; %# Make scalar higher to include colors close to yellow
imageSegmented = zeros(size(image));
imageSegmented(abs(image/colorRes-yellowScale)< colorDist) = 1;
subplot(2,1,2)
imagesc(imageSegmented)
title('Yellow segmented out')
Related
I tried to use image processing toolbox to count my colony. I used imfindcircles to find the colony and count. But I got some problems:
(1)Due to that my colony could be white and black, I tried to find the colony by using Bright or Dark in ObjectPolarity, and use a if loop to select which one I finally choose. But the first step of my if loop doesn't really work.
(2) For using imfindcircles to find the circle, I found it works for the colony in white, while the method is a disaster for the black colony. I'm kind of desperate now because I can't find other ways to segment the colony.
So finally i need to: label each colony in the plate, count the colony number, calculate each colony size, extract the mean gray value for each colony (the colour).
Thank you very much!!!
So here is my code:
im = imread(test.jpeg)
imshow(im)
% to find the colony
[centersBright, radiiBright] = imfindcircles(im,[30 60],'ObjectPolarity','bright','Sensitivity',0.925,'Method','twostage','EdgeThreshold',0.1)
[centersDark, radiiDark] = imfindcircles(im,[30 60],'ObjectPolarity','dark','Sensitivity',0.925,'Method','twostage','EdgeThreshold',0.15)
% to select which one is the correct count. if one of the length(centres) value is lower than 10, I consider it as an error. But if both length(centres) is low than 10, I consider it as a treatment effect and accept the value.
if length(centersDark)<10<length(centersBright)
centers=centersBright
radii=radiiBright
elseif length(centersBright)<10<length(centersDark)
centers=centersDark
radii=radiiDark
else
centers=[centersBright,centersDark]
radii=[radiiBright,radiiDark]
end
% view and label the colony
h = viscircles(centers,radii)
for k = 1:length(radii)
string = sprintf('%d',k)
text(centers(k,1),centers(k,2),string,'color','y','HorizontalAlignment', 'center','VerticalAlignment', 'middle')
area(k)=pi*radii(k)^2
end
Suggested Solution
While it's hard to distinguish between the colonies and their surrounding in the black and white version of your input, it is not hard to do so in the hue space by using thresholding.
The reason is that the colonies have a unique hue which is different from their background.
This will be more noticable after converting to HSV space:
Therefore, I suggest the folowing solution:
convert input image to HSV space
use thresholding on the hue component.
extract connected components
Use the connected components which are large enough for the mask
perform imclose opertation for cleaning the artifacts
Code
%reads the image
I = imread('colony2.png');
%convert to hsv
hsvIm = rgb2hsv(I);
%thresholding on the hue space
bwIm = hsvIm(:,:,1) < 0.15;
%find connected components
CC = bwconncomp(bwIm);
%choose only cc with sufficient amount of pixels
numPixels = cellfun(#numel,CC.PixelIdxList);
relevantCC = CC.PixelIdxList(numPixels > 10);
%generate a binary mask with these conencted componants
colonyMask = false(size(bwIm));
for ii=1:length(relevantCC)
colonyMask(relevantCC{ii}) = true;
end
%perform morpholopical operations for cleaning
colonyMask = imclose(colonyMask,strel('disk',1));
%display result
h = imshow(I); % Save the handle; we'll need it later
set(h, 'AlphaData', ~colonyMask);
Results
Selection of threshold
The threshold was chosen by choosing the first pick in the histogram of the hue component
histogram(hsvIm(:,:,1))
Hey I have two big matrices 400x400. That I want to create into one heatmap/colormap. Current code:
res = matrix_1*256/2 + matrix_2*256/2;
%res = res -max(max(res));
HeatMap(res)
surf(res,'EdgeColor','none');
view(0,90);
colormap(gray);
colorbar
disp('done');
where the heatmap function everyone can look up. But to give a visualization of the second one it results in:
This however does not let me know which matrix is dominant. But only that both are dominant (white) both are not dominant (dark). I would like to make a plot where I use fused data. E.g. Matrix 1 is nuance of red and Matrix 2 is nuance of green:
rgb = [matrix_1(i,ii), matrix_2(i,ii), 0]
then I want to make a 2D plot using the color that rgb represents. Is this possible ? I have looked at making my own colormap (but you guessed with no good results).
I have found solutions like this (how-to-create-an-interpolated-colormap-or-color-palette-from-two-colors) and create-a-colormap-in-matlab, but I how do I specify a specific colour for every point in a 2D plot?
Like this:
RGB = cat(3, matrix_1, matrix_2, zeros(size(matrix_1)));
imshow(RGB)
Now the chart will be black were neither are dominant, red where matrix_1 is but matrix_2 is not, green where matrix_2 is but matrix_1 is not and yellow where they both dominate.
If you wanted, you could even convert this back to an indexed image and get the colormap that colours it this way using rgb2ind and then create a surface plot using your original res for the heights (note there is no longer a need to scale this) and your new indexed image (ind) to specify the colours which are no longer enitrely goverened by height
res = (matrix_1 + matrix_2)/2;
[ind, map] = rgb2ind(RGB);
surf(res, ind, 'EdgeColor','none');
colormap(map)
colorbar
I have an image with some features/regions in it (balls in the above example). I want to color each ball with a different color based on its properties. For example, that might be its diameter in pixels.
While I'm done on the feature recognition side, I'm stuck when it comes to showing results. Right now I'm doing:
my_image = imread(...);
//ball recognition and other stuff
for i = 1:number_of_balls
ball_diameter(i) = ... //I calculate the diameter of the i-th ball
ball_indices = ... //I get the linear indices of the i-th ball
//ball coloring
my_image(ball_indices) = 255; //color the red channel
my_image(ball_indices + R*C) = 0; //color the blue channel
my_image(ball_indices + 2*R*C) = 0; //color the green channel
end
figure
imshow(my_image)
colormap jet(100) //I want 100 different classes
colorbar
caxis([0, 50]) //I assume all balls have a diameter < 50
In the above code I'm tinting all balls red, which is definitely not what I'm looking for. The issue is that, even if I know ball_diameter(i), I do not know which colormap class that ball will get in. In other words, I would need something like:
for i = 1:number_of_balls
// ...
if ball_diameter *belongs to class k*
my_image(ball_indices) = jet(k, 1);
my_image(ball_indices + R*C) = jet(k,2);
my_image(ball_indices + 2*R*C) = jet(k,3);
end
end
How to, and mostly, is there any other more logical way?
You can separate the assignment of pixels to classes from their coloring for display: you can use my_image as a 2D R-by-C labeling matrix: that is each object (ball) is assigned a different index from 1 to 100 (in case you have 100 objects in the image). Now when you want to display the result you can either ask the figure to map indexes to colors for you, using colormap or explicitly create a colored image using ind2rgb.
For example
%// create the index/labeling matrix
my_image = zeros( R, C );
for ii = 1:number_of_balls
my_image( ball_indices ) = ii; %// assign index to pixels and not atual colors
end
%// color using figure
figure;
imagesc( my_image );axis image;
colormap rand(100,3); %// map indexes to colors using random mapping
%//explicitly create a color image using ind2rgb
my_color_image = ind2rgb( my_image, rand(100,3) );
figure;
imshow( my_color_image ); % display the color image
Notes:
1. IMHO it is preferable to use random color map to display categorizations of pixels, as opposed to jet with which you usually end up with very similar colors to adjacent objects, making it very difficult to visually appreciate the result.
2. IMHO it is more convenient to use label matrix, you can also save it to file as an indexed image (png format) thus visualizing, saving and loading your results simply and efficiently.
A simple way is as follows:
Make a 2D image of the same size as your original.
Set the indices of each "ball" to the diameter or other relevant value
Display with imagesc
Use caxis, colormap, colorbar etc. to adjust the categories dynamically.
For example,
a = randi(200,200); % 200 x 200 image containing values 1 to 200 at random
imagesc(a)
colorbar
The above should show a random color field with the default colormap. The colorbar goes from 1 to 200.
colormap(jet(5))
The colorbar still goes from 1 to 200, but with only 5 colors.
caxis([1 100])
The colorbar now shows the five colors scaled from 1 to 100 (with everything above 100 in the top pot).
If you want to convert your 2D image full of different diameters to a set of discrete labels indicating diameter ranges, an easy way is to use histc with the second output bin being the same size as your input image, set to which bin the diameter value fell into. The second input in this case is the edges of the bins, not the centres.
[n bin] = histc(a,0:20:201);
I have a project on Fingerprint Matching and I got stuck at marking the points of termination and bifurcation on the image. I have already stored pixels' coordinates. How would I go about doing this?
Assuming that your image is stored in a grayscale image called im, and your points of termination and bifurcation are stored in 2D matrices where the first column denotes the row and the second column denotes the column of each point, you can easily do this using sub2ind. sub2ind converts 2D co-ordinates into linear indices so that you can easily vectorize setting pixels in an image, or locations in a matrix quickly. As such, make your grayscale image into a RGB image by stacking the image three times as a 3D matrix. If you recall, grayscale images in the RGB colour model have all of the red, green and blue channels the same. For example, gray would be (R,G,B) = (128,128,128).
Let's call your bifurcation points as bifur and terminations as term and are in that 2D matrix format I specified earlier. As such, do something like this:
%// Get linear indices for bifurcation and termination points
ind_b = sub2ind(size(im), bifur(:,1), bifur(:,2));
ind_t = sub2ind(size(im), term(:,1), term(:,2));
%// Mark them on the image
red = im;
green = im;
blue = im;
red(ind_b) = 255;
green(ind_b) = 0;
blue(ind_b) = 0;
red(ind_t) = 0;
green(ind_t) = 255;
blue(ind_t) = 0;
im_colour = cat(3, red, green, blue);
imshow(im_colour);
Let's walk through this code slowly. I first figure out the linear indices of where the bifurcation and termination points are in the image. What I do next is create red, green and blue channels that are all copies of the original image. After this, I access each colour channel and mark the bifurcation and termination points with different colours. For the bifurcation points, I made them purely red or (R,G,B) = (255,0,0). For the termination points, I made them purely green or (R,G,B) = (0,255,0). Once I set the colours for the points, I create a colour image by stacking the channels together with cat, and specifically choosing the third dimension. I finally show the image in the end.
What you may also have to play with is the size of the markings on the image. As you can see, the pixels that are marked are just the single pixels themselves, and depending on the resolution of your image, you may or may not be able to see them properly in the image. As such, I would recommend you mark the pixels within a grid surrounding the original point. Perhaps you can make this a 5 x 5 grid surrounding the pixel of interest. With this, perhaps make a for loop for each point and mark a 5 x 5 pixel grid that surrounds this point. I'm also going to assume that your markings are sufficiently well inside the image so that we don't risk drawing the grid out of bounds. So the code would be modified like so:
%// Get linear indices for bifurcation and termination points
ind_b = [];
for idx = 1 : size(bifur,1)
[c,r] = meshgrid(bifur(idx,2)-2:bifur(idx,2)+2, bifur(idx,1)-2:bifur(idx,1)+2);
c = c(:);
r = r(:);
ind_b = [ind_b; sub2ind(size(im), r, c);
end
ind_t = [];
for idx = 1 : size(term,1)
[c,r] = meshgrid(term(idx,2)-2:term(idx,2)+2, term(idx,1)-2:term(idx,1)+2);
c = c(:);
r = r(:);
ind_t = [ind_t; sub2ind(size(im), r, c);
end
%// Mark them on the image
red = im;
green = im;
blue = im;
red(ind_b) = 255;
green(ind_b) = 0;
blue(ind_b) = 0;
red(ind_t) = 0;
green(ind_t) = 255;
blue(ind_t) = 0;
im_colour = cat(3, red, green, blue);
imshow(im_colour);
What has changed is the beginning of the code. For each point that we have for the bifurcation and the termination points, I use meshgrid to determine a 5 x 5 grid of points that surround each relevant pixel, then generate the linear indices for each point within the 5 x 5 grid. I then add this into one final array for both so that we can carry out the same marking logic we saw above.
You'll have to play around with the colours if you want them to be other than red and green, but this should be something for you to start with. If you want a list of possible colours with the RGB model, a nice tool is the RGB colour picker where you figure out which colour you want, and it gives you the RGB values to replicate that colour.
Good luck!
I have a project on Fingerprint Matching and I got stuck at marking the points of termination and bifurcation on the image. I have already stored pixels' coordinates. How would I go about doing this?
Assuming that your image is stored in a grayscale image called im, and your points of termination and bifurcation are stored in 2D matrices where the first column denotes the row and the second column denotes the column of each point, you can easily do this using sub2ind. sub2ind converts 2D co-ordinates into linear indices so that you can easily vectorize setting pixels in an image, or locations in a matrix quickly. As such, make your grayscale image into a RGB image by stacking the image three times as a 3D matrix. If you recall, grayscale images in the RGB colour model have all of the red, green and blue channels the same. For example, gray would be (R,G,B) = (128,128,128).
Let's call your bifurcation points as bifur and terminations as term and are in that 2D matrix format I specified earlier. As such, do something like this:
%// Get linear indices for bifurcation and termination points
ind_b = sub2ind(size(im), bifur(:,1), bifur(:,2));
ind_t = sub2ind(size(im), term(:,1), term(:,2));
%// Mark them on the image
red = im;
green = im;
blue = im;
red(ind_b) = 255;
green(ind_b) = 0;
blue(ind_b) = 0;
red(ind_t) = 0;
green(ind_t) = 255;
blue(ind_t) = 0;
im_colour = cat(3, red, green, blue);
imshow(im_colour);
Let's walk through this code slowly. I first figure out the linear indices of where the bifurcation and termination points are in the image. What I do next is create red, green and blue channels that are all copies of the original image. After this, I access each colour channel and mark the bifurcation and termination points with different colours. For the bifurcation points, I made them purely red or (R,G,B) = (255,0,0). For the termination points, I made them purely green or (R,G,B) = (0,255,0). Once I set the colours for the points, I create a colour image by stacking the channels together with cat, and specifically choosing the third dimension. I finally show the image in the end.
What you may also have to play with is the size of the markings on the image. As you can see, the pixels that are marked are just the single pixels themselves, and depending on the resolution of your image, you may or may not be able to see them properly in the image. As such, I would recommend you mark the pixels within a grid surrounding the original point. Perhaps you can make this a 5 x 5 grid surrounding the pixel of interest. With this, perhaps make a for loop for each point and mark a 5 x 5 pixel grid that surrounds this point. I'm also going to assume that your markings are sufficiently well inside the image so that we don't risk drawing the grid out of bounds. So the code would be modified like so:
%// Get linear indices for bifurcation and termination points
ind_b = [];
for idx = 1 : size(bifur,1)
[c,r] = meshgrid(bifur(idx,2)-2:bifur(idx,2)+2, bifur(idx,1)-2:bifur(idx,1)+2);
c = c(:);
r = r(:);
ind_b = [ind_b; sub2ind(size(im), r, c);
end
ind_t = [];
for idx = 1 : size(term,1)
[c,r] = meshgrid(term(idx,2)-2:term(idx,2)+2, term(idx,1)-2:term(idx,1)+2);
c = c(:);
r = r(:);
ind_t = [ind_t; sub2ind(size(im), r, c);
end
%// Mark them on the image
red = im;
green = im;
blue = im;
red(ind_b) = 255;
green(ind_b) = 0;
blue(ind_b) = 0;
red(ind_t) = 0;
green(ind_t) = 255;
blue(ind_t) = 0;
im_colour = cat(3, red, green, blue);
imshow(im_colour);
What has changed is the beginning of the code. For each point that we have for the bifurcation and the termination points, I use meshgrid to determine a 5 x 5 grid of points that surround each relevant pixel, then generate the linear indices for each point within the 5 x 5 grid. I then add this into one final array for both so that we can carry out the same marking logic we saw above.
You'll have to play around with the colours if you want them to be other than red and green, but this should be something for you to start with. If you want a list of possible colours with the RGB model, a nice tool is the RGB colour picker where you figure out which colour you want, and it gives you the RGB values to replicate that colour.
Good luck!