Get regions within black border of image - matlab

I begin with the following image:
I perform local thresholding by comparing a pixel to its neighborhood mean. I also crop out the white border surrounding the image after this local thresholding with the following code:
I = imread('img_path');
N = 21;
localMean = conv2(double(I), double(1/(N^2) * ones(N)), 'same');
BW = I > localMean;
borderSize = ceil(double(N) / 2);
R = [borderSize, borderSize, size(BW, 2) - 2*borderSize, size(BW, 1) - 2*borderSize];
BW = imcrop(BW, R);
This leaves me with the following image:
As you can see, there is a clear black border surrounding each of the segmented cells. How do I go about removing all things in this image OTHER than those regions within the black border?
If this is not possible, then are there any other techniques I should take a look at that might make give my local thresholding less noise?
Any help is appreciated.

you can use Otsu's thresholding (graythresh) and morphological operations:
im = im2double(imread('cells.png'));
% otsu thresholding
t = graythresh(im);
bw = im > t;
% morphological open to remove small noise
bw = imopen(bw,strel('disk',5,0));
% fill holes to form solid objects
bw = imfill(bw,'holes');
% show
imshow(bw)

Related

Image blurring results in a sharp edge

I'm doing some processing with MATLAB on an RGB image.
I had to obtain a circular blurring like in the image below:
obtained through this code:
A = imread('lena .bmp');
I = rgb2gray(A);
[rNum,cNum,~] = size(I);
%center and radius of the circular mask
x1 = 256.5;
y1 = 256.5;
radius = 100;
%circular mask creation
[x,y] = ndgrid((1:rNum)-y1,(1:cNum)-x1);
mask = (x.^2 + y.^2)<radius^2;
h = ones(30,30)/900; %gaussian filter
J = roifilt2(h,I,mask); %apply the filter at the mask
%filtering plane - by - plane in order to apply the circular blurred mask
%to the RGB image
filtered_im = zeros(size(A));
filtered_im(:,:,1) = roifilt2(h, A(:,:,1), mask);
filtered_im(:,:,2) = roifilt2(h, A(:,:,2), mask);
filtered_im(:,:,3) = roifilt2(h, A(:,:,3), mask);
filtered_im = uint8(filtered_im);
figure
imshow(filtered_im)
title('Circular blurring RGB image');
The effect obtained, anyway, is too artificial because the transition between the blurred circular mask and the rest of the image is too sharp. Is there a possibility to make this transition more faded in order to obtain a more natural effect?
You can use a weighted average of both the original image and the modified one, using as weights a mask based on the distance to the center of the circle.
The original one would have more weight in the external part of the circle, and the modified image in the center. This could create a transition in the blurring.

how to perform image enhancement over a small region of an image?

I would like to enhance a portion of the image. I would like to enhance the regions within rectangular region esp on the green rectangle region
You can use imcrop.
[I2 rect] = imcrop(I)
This will ask you to draw a rectangle and rect will thus contain the coordinates of that rectangle. I2 contains the cropped image and you can then apply any function you would like on that matrix.
Using a function like ginput you can select a point on an image, and with having a width and height values of a rectangle, you can crop a rectangle from your image. Then you can use any function such as imadjust to enhance your cropped part.
a= 100; % height
b= 100; % width
I = imread('myimage.png'); % read the image file
figure;imagesc(I); % plot the image
[x,y] = ginput(1); % select a point
I2 = I(:,:,1); %
Ic = imcrop(I2,[x-a/2 y-b/2 a b]); % crop a rectangle around the selected point
J = imadjust(Ic); % adjust the contrast
If you want to be able to select a rectangle, you can use the following command:
imshow('myimage.png');
rect = getrect;

Can we rotate an image in MATLAB filled with background color of original image?

By default, MATLAB function imrotate rotate image with black color filled in rotated portion. See this, http://in.mathworks.com/help/examples/images_product/RotationFitgeotransExample_02.png
We can have rotated image with white background also.
Question is, Can we rotate an image (with or without using imrotate) filled with background of original image?
Specific to my problem: Colored image with very small angle of rotation (<=5 deg.)
Here's a naive approach, where we simply apply the same rotation to a mask and take only the parts of the rotated image, that correspond to the transformed mask. Then we just superimpose these pixels on the original image.
I ignore possible blending on the boundary.
A = imread('cameraman.tif');
angle = 10;
T = #(I) imrotate(I,angle,'bilinear','crop');
%// Apply transformation
TA = T(A);
mask = T(ones(size(A)))==1;
A(mask) = TA(mask);
%%// Show image
imshow(A);
You can use padarray() function with 'replicate' and 'both' option to interpolate your image. Then you can use imrotate() function.
In the code below, I've used ceil(size(im)/2) as pad size; but you may want bigger pad size to eliminate the black part. Also I've used s and S( writing imR(S(1)-s(1):S(1)+s(1), S(2)-s(2):S(2)+s(2), :)) to crop the image where you can extract bigger part of image just expanding boundary of index I used below for imR.
Try this:
im = imread('cameraman.tif'); %// You can also read a color image
s = ceil(size(im)/2);
imP = padarray(im, s(1:2), 'replicate', 'both');
imR = imrotate(imP, 45);
S = ceil(size(imR)/2);
imF = imR(S(1)-s(1):S(1)+s(1)-1, S(2)-s(2):S(2)+s(2)-1, :); %// Final form
figure,
subplot(1, 2, 1)
imshow(im);
title('Original Image')
subplot(1, 2, 2)
imshow(imF);
title('Rotated Image')
This gives the output below:
Not so good but better than black thing..

Stretching an ellipse in an image to form a circle

I want to stretch an elliptical object in an image until it forms a circle. My program currently inputs an image with an elliptical object (eg. coin at an angle), thresholds and binarizes it, isolates the region of interest using edge-detect/bwboundaries(), and performs regionprops() to calculate major/minor axis lengths.
Essentially, I want to use the 'MajorAxisLength' as the diameter and stretch the object on the minor axis to form a circle. Any suggestions on how I should approach this would be greatly appreciated. I have appended some code for your perusal (unfortunately I don't have enough reputation to upload an image, the binarized image looks like a white ellipse on a black background).
EDIT: I'd also like to apply this technique to the gray-scale version of the image, to examine what the stretch looks like.
code snippet:
rgbImage = imread(fullFileName);
redChannel = rgbImage(:, :, 1);
binaryImage = redChannel < 90;
labeledImage = bwlabel(binaryImage);
area_measurements = regionprops(labeledImage,'Area');
allAreas = [area_measurements.Area];
biggestBlobIndex = find(allAreas == max(allAreas));
keeperBlobsImage = ismember(labeledImage, biggestBlobIndex);
measurements = regionprops(keeperBlobsImage,'Area','MajorAxisLength','MinorAxisLength')
You know the diameter of the circle and you know the center is the location where the major and minor axes intersect. Thus, just compute the radius r from the diameter, and for every pixel in your image, check to see if that pixel's Euclidean distance from the cirlce's center is less than r. If so, color the pixel white. Otherwise, leave it alone.
[M,N] = size(redChannel);
new_image = zeros(M,N);
for ii=1:M
for jj=1:N
if( sqrt((jj-center_x)^2 + (ii-center_y)^2) <= radius )
new_image(ii,jj) = 1.0;
end
end
end
This can probably be optimzed by using the meshgrid function combined with logical indices to avoid the loops.
I finally managed to figure out the transform required thanks to a lot of help on the matlab forums. I thought I'd post it here, in case anyone else needed it.
stats = regionprops(keeperBlobsImage, 'MajorAxisLength','MinorAxisLength','Centroid','Orientation');
alpha = pi/180 * stats(1).Orientation;
Q = [cos(alpha), -sin(alpha); sin(alpha), cos(alpha)];
x0 = stats(1).Centroid.';
a = stats(1).MajorAxisLength;
b = stats(1).MinorAxisLength;
S = diag([1, a/b]);
C = Q*S*Q';
d = (eye(2) - C)*x0;
tform = maketform('affine', [C d; 0 0 1]');
Im2 = imtransform(redChannel, tform);
subplot(2, 3, 5);
imshow(Im2);

Matlab fill shapes by white

As you see, I have shapes and their white boundaries. I want to fill the shapes in white color.
The input is:
I would like to get this output:
Can anybody help me please with this code? it doesn't change the black ellipses to white.
Thanks alot :]]
I = imread('untitled4.bmp');
Ibw = im2bw(I);
CC = bwconncomp(Ibw); %Ibw is my binary image
stats = regionprops(CC,'pixellist');
% pass all over the stats
for i=1:length(stats),
size = length(stats(i).PixelList);
% check only the relevant stats (the black ellipses)
if size >150 && size < 600
% fill the black pixel by white
x = round(mean(stats(i).PixelList(:,2)));
y = round(mean(stats(i).PixelList(:,1)));
Ibw = imfill(Ibw, [x, y]);
end;
end;
imshow(Ibw);
Your code can be improved and simplified as follows. First, negating Ibw and using BWCONNCOMP to find 4-connected components will give you indices for each black region. Second, sorting the connected regions by the number of pixels in them and choosing all but the largest two will give you indices for all the smaller circular regions. Finally, the linear indices of these smaller regions can be collected and used to fill in the regions with white. Here's the code (quite a bit shorter and not requiring any loops):
I = imread('untitled4.bmp');
Ibw = im2bw(I);
CC = bwconncomp(~Ibw, 4);
[~, sortIndex] = sort(cellfun('prodofsize', CC.PixelIdxList));
Ifilled = Ibw;
Ifilled(vertcat(CC.PixelIdxList{sortIndex(1:end-2)})) = true;
imshow(Ifilled);
And here's the resulting image:
If your images are all black&white, and you have the image processing toolkit, then this looks like what you need:
http://www.mathworks.co.uk/help/toolbox/images/ref/imfill.html
Something like:
imfill(image, [startX, startY])
where startX, startY is a pixel in the area that you want to fill.