I do binary thresholding on a 16 bit gray scale image.This would help me in segmenting the region of interest.After binary thresholding,i would like to get the individual pixel intensities which are the intensities of the original 16 bit image and not the binary intensity values say 0,65535...
How can i do this?
Find the region of interest in image segmentation using the binary image. After this, use the pixel locations in the 16 bit image for further processing of the image.
To get a image from your original image, I and a binary (logical) segmented image BW:
I2 = I.*BW;
I2 should have the original values in the ROI and 0 elsewhere. Or, to get just a list of pixels and their values, via logical indexing:
I2 = I(BW);
Alternatively, depending on what you're doing, you may want to use regionprops:
stats = regionprops(BW,I,'MeanIntensity','PixelValues');
For a BW image showing the regions of interest, and a greyscale image I this will return the mean intensity and all list of all pixel values in I for each separate region (defined as a connected areas in BW).
Related
I have an image with dark blue spots on a black background. I want to convert this to inverse gray scale. By inverse, I mean, I want the black ground to be white.
When I convert it to gray scale, it makes everything look black and it makes it very hard to differentiate.
Is there a way to do an inverse gray scale where the black background takes the lighter shades?
Or, another preferable option is to represent the blue as white and the black as black.
I am using img = rgb2gray(img); in MATLAB for now.
From mathworks site:
IM2 = imcomplement(IM)
Is there a way to do an inverse gray scale where the black
background takes the lighter shades?
Based on your image description I created an image sample.png:
img1 = imread('sample.png'); % Read rgb image from graphics file.
imshow(img1); % Display image.
Then, I used the imcomplement function to obtain the complement of the original image (as suggested in this answer).
img2 = imcomplement(img1); % Complement image.
imshow(img2); % Display image.
This is the result:
Or, another preferable option is to represent the blue as white and
the black as black.
In this case, the simplest option is to work with the blue channel. Now, depending on your needs, there are two approaches you can use:
Approach 1: Convert the blue channel to a binary image (B&W)
This comment suggests using the logical operation img(:,:,3) > 0, which will return a binary array of the blue channel, where every non-zero valued pixel will be mapped to 1 (white), and the rest of pixels will have a value of 0 (black).
While this approach is simple and valid, binary images have the big disadvantage of loosing intensity information. This can alter the perceptual properties of your image. Have a look at the code:
img3 = img1(:, :, 3) > 0; % Convert blue channel to binary image.
imshow(img3); % Display image.
This is the result:
Notice that the round shaped spots in the original image have become octagon shaped in the binary image, due to the loss of intensity information.
Approach 2: Convert the blue channel to grayscale image
A better approach is to use a grayscale image, because the intensity information is preserved.
The imshow function offers the imshow(I,[low high]) overload, which adjusts the color axis scaling of the grayscale image through the DisplayRange parameter.
One very cool feature of this overload, is that we can let imshow do the work for us.
From the documentation:
If you specify an empty matrix ([]), imshow uses [min(I(:)) max(I(:))]. In other words, use the minimum value in I as black, and the maximum value as white.
Have a look at the code:
img4 = img1(:, :, 3); % Extract blue channel.
imshow(img4, []); % Display image.
This is the result:
Notice that the round shape of the spots is preserved exactly as in the original image.
I have this image (8 bit, pseudo-colored, gray-scale):
And I want to create an intensity band of a specific measure around it's border.
I tried erosion and other mathematical operations, including filtering to achieve the desired band but the actual image intensity changes as soon as I use erosion to cut part of the border.
My code so far looks like:
clear all
clc
x=imread('8-BIT COPY OF EGFP001.tif');
imshow(x);
y = imerode(x,strel('disk',2));
y1=imerode(y,strel('disk',7));
z=y-y1;
figure
z(z<30)=0
imshow(z)
The main problem I am encountering using this is that it somewhat changes the intensity of the original images as follows:
So my question is, how do I create such a band across image border without changing any other attribute of the original image?
Going with what beaker was talking about and what you would like done, I would personally convert your image into binary where false represents the background and true represents the foreground. When you're done, you then erode this image using a good structuring element that preserves the roundness of the contours of your objects (disk in your example).
The output of this would be the interior of the large object that is in the image. What you can do is use this mask and set these locations in the image to black so that you can preserve the outer band. As such, try doing something like this:
%// Read in image (directly from StackOverflow) and pseudo-colour the image
[im,map] = imread('http://i.stack.imgur.com/OxFwB.png');
out = ind2rgb(im, map);
%// Threshold the grayscale version
im_b = im > 10;
%// Create structuring element that removes border
se = strel('disk',7);
%// Erode thresholded image to get final mask
erode_b = imerode(im_b, se);
%// Duplicate mask in 3D
mask_3D = cat(3, erode_b, erode_b, erode_b);
%// Find indices that are true and black out result
final = out;
final(mask_3D) = 0;
figure;
imshow(final);
Let's go through the code slowly. The first two lines take your PNG image, which contains a grayscale image and a colour map and we read both of these into MATLAB. Next, we use ind2rgb to convert the image into its pseudo-coloured version. Once we do this, we use the grayscale image and threshold the image so that we capture all of the object pixels. I threshold the image with a value of 10 to escape some quantization noise that is seen in the image. This binary image is what we will operate on to determine those pixels we want to set to 0 to get the outer border.
Next, we declare a structuring element that is a disk of a radius of 7, then erode the mask. Once I'm done, I duplicate this mask in 3D so that it has the same number of channels as the pseudo-coloured image, then use the locations of the mask to set the values that are internal to the object to 0. The result would be the original image, but having the outer contours of all of the objects remain.
The result I get is:
I want to compute the extent of haze of an image for each block. This is done by finding the dark channel value that is used to reflect the extent of haze. This concept is from Kaiming He's paper on a Single Image Haze Removal using Dark Channel Prior.
The dark channel value for each block is defined as follows:
where I^c (x',y') denotes the intensity at a pixel location (x',y') in color channel c (one of Red, Green, or Blue color channel), and omega(x,y) denotes the neighborhood of the pixel location (x',y').
I'm not sure how to translate this equation in MATLAB?
If I correctly understand what this equation is asking for, you are essentially extracting pixel blocks centered at each (x,y) in the image, you determine the minimum value within this pixel block for the red, green, and blue channels. This results in 3 values where each value is the minimum within the pixel block for each channel. From these 3 values, you choose the minimum of these and that is the final result for a location (x,y) in the image.
We can do this very easily with ordfilt2. What ordfilt2 does is that it applies an order-statistics filter to your image. You specify a mask of which pixels needs to be analyzed in your neighbourhood, it gathers those pixels in the neighbourhood that are deemed valid and sorts their intensities. You then you choose the rank of the pixel you want in the end. A lower rank means a smaller value while a larger rank denotes a larger value. In our case, the mask would be set to all logical true and is the size of the neighbourhood you want to analyze.
Because you want a minimum, you would choose rank 1 of the result.
You would apply this to each red, green and blue channel, then for each spatial location, choose the minimum out of the three. Therefore, supposing your image was stored in im, and you wanted to apply a m x n neighbourhood to the image, do something like this:
%// Find minimum intensity for each location for each channel
out_red = ordfilt2(im(:,:,1), 1, true(m, n));
out_green = ordfilt2(im(:,:,2), 1, true(m, n));
out_blue = ordfilt2(im(:,:,3), 1, true(m, n));
%// Create a new colour image that has these all stacked
out = cat(3, out_red, out_green, out_blue);
%// Find dark channel image
out_dark = min(out, [], 3);
out_dark will contain the dark channel image you desire. The key to calculating what you want is in the last two lines of code. out contains the minimum values for each spatial location in the red, green and blue channels and they are all concatenated in the third dimension to produce a 3D matrix. After, I apply the min operation and look at the third dimension to finally choose which out of the red, green and blue channels for each pixel location will give the output value.
With an example, if I use onion.png which is part of MATLAB's system path, and specify a 5 x 5 neighbourhood (or m = 5, n = 5), this is what the original image looks like, as well as the dark channel result:
Sidenote
If you're an image processing purist, finding the minimum value for pixel neighbourhoods in a grayscale image is the same as finding the grayscale morphological erosion. You can consider each red, green or blue channel to be its own grayscale image. As such, we could simply replace ordfilt2 with imerode and use a rectangle structuring element to generate the pixel neighbourhood you want to use to apply to your image. You can do this through strel in MATLAB and specify the 'rectangle' flag.
As such, the equivalent code using morphology would be:
%// Find minimum intensity for each location for each channel
se = strel('rectangle', [m n]);
out_red = imerode(im(:,:,1), se);
out_green = imerode(im(:,:,2), se);
out_blue = imerode(im(:,:,3), se);
%// Create a new colour image that has these all stacked
out = cat(3, out_red, out_green, out_blue);
%// Find dark channel image
out_dark = min(out, [], 3);
You should get the same results as using ordfilt2. I haven't done any tests, but I highly suspect that using imerode is faster than using ordfilt2... at least on higher resolution images. MATLAB has highly optimized morphological routines and are specifically for images, whereas ordfilt2 is for more general 2D signals.
Or you can use the Visibility Metric to see how hazy an image is. It turns out someone wrote a beautiful code for it as well.The lower the metric, the higher is the haze in the image.
This metric can also be used as a pre-processor to autmatically adjust dehaze parameters.
I am currently writing a program on Matlab for Image Processing. I am using an image (below) to attempt to count the number of white cars in the image. I have used filtering commands, strel(disk, 2), and have managed to detect the two white cars in the image but due to the way the binary image (below) displays a car it counts one car as two.
Are there any solutions to overcome this problem or are there any particular methods I should be using as an alternative to the code below?
a = imread('Cars2.jpg'); %Read the image Car1.jpg
subplot(3,3,1), imshow (a); %Display RGB image Car1.jpg
b = rgb2gray(a); %Turn Car1 from RGB to greyscale
subplot(3,3,2), imshow (b); %Display greyscale image Car1.jpg
c = graythresh (a); %Automatically set appropriate threshold for foreground & background (Otsu's Method)
d = im2bw (b,0.8); %Convert from greyscale to binary image
subplot (3,3,3), imshow(d); %Display binary image Car1.jpg
subplot(3,3,4), imhist (b,256); %Display histogram for greyscale values (image, samples)
SE = strel ('disk',2); %Set Disk radius for filtering unnecessary pixels
e = imopen (d,SE); %Erode then Dilate image with Disk radius
subplot (3,3,5), imshow(e); %Display openned/filtered image Car1.jpg
B = bwboundaries(e);
imshow(e)
text(10,10,strcat('\color{red}Objects Found:',num2str(length(B))))
hold on
EDIT: As i have under 10 reputation I can't post the image displayed from the code but the theory is pretty generic so I hope you understand what I'm getting across. The images are similar to http://www.mathworks.co.uk/help/images/examples/detecting-cars-in-a-video-of-traffic.html
Instead of using bwboundaries I would use regionprops(e). You can then use some additional logic by looking at the area of the object and the shape of the bounding box to infer if the object is one or two cars.
If you are only interested in detecting white cars, your overall algorithm could be improved by converting the image into HSV colour space and thresholding on the saturation and value channels instead of using im2bw. If you have a video sequence I would segment using vision.ForegroundDetector or another Gaussian mixture model segmentation technique.
I am using an indexed image.How do I programatically obtain the pixel intensity values obtained by changing the colormap to hsv in the imtool? Is there a way to change the colormap of the indexed image to hsv(256)?
I am new to MATLAB, kindly help!
I have attached the image below:
Which channel does the imtool display and what does the value '91' in the imtool stand for? How do I obtain this value?
The Pixel info at the bottom displays the following information:
Pixel info: (X, Y): Pixel Value
Here, we have pixel value of 91 at (309, 510). 91 is the pixel intensity in a range of values (mostly 0 to 255). Only 1 channel is being read because it is a grayscale image.
You can create a hsv image out of an RGB image but it doesnt make sense to talk of a hsv conversion for a gray scale image. What you have is a grayscale image.