Create boundary around the object - matlab

I have the input image. I want to create the boundary around the object and marked the boundary pixels as gray i.e. 128 intensity value. I need this type of output image. I traced the boundary of the object:
level = graythresh(im);
BW = im2bw(im,level);
figure; imshow(BW);
[B,L] = bwboundaries(BW,'noholes');
imshow(im);
hold on
for k = 1:length(B)
boundary = B{k};
plot(boundary(:,2), boundary(:,1), 'Color', [0.5 0.5 0.5], 'LineWidth', 5)
end
But it will only plot the boundary over the image. I want to create this boundary around the object of input image. How can I do this? I hope my question is clear.

While I don't know why you wan this, a word of advice: you may not want to do it. You are losing information of the image by doing so. It is possible that for you application knowing the indices of the boundaries is enough, and you do already know them.
However, this is what you would need to do in case of really wanting to do it:
clear;
clc;
im=imread('https://i.stack.imgur.com/r7uQz.jpg');
im=im(31:677,90:1118);
level = graythresh(im);
BW = im2bw(im,level);
[B,L] = bwboundaries(BW,'noholes');
for k = 1:length(B)
boundary = B{k};
%%%%%%%%% Fill the boundary locations with he desired value.
for ii=1:size(boundary,1)
im(boundary(ii,1), boundary(ii,2))=128;
end
end
If you want "fat" lines as in your image, add this after:
im128=im==128;
bigboundary=imdilate(im128,ones(5));
im(bigboundary)=128;

You can binarize the image and detect the contours using OpenCV.
Here is the Python implementation:
img = cv2.imread(r'D:\Image\temp1.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret,bw = cv2.threshold(gray,100,255,cv2.THRESH_BINARY)
_,contours,hierarchy = cv2.findContours(bw, cv2.RETR_CCOMP, 1)
for cnt in contours:
c = np.random.randint(0,256,3)
c = (int(c[0]), int(c[1]), int(c[2]))
cv2.drawContours(img,[cnt],0,c,2)
Output image:

Related

Area calculation in MATLAB

I am working on a paper and I need to find out the area of the region having color black from the image that I have attached.
Original image
I have done some processing by using threshold and complimenting the image.Processed image
Now I'm having a problem finding the area of the black colored region. Can someone please help? I'm new to MATLAB.
Here is my code :
img1=imread('C:/Users/Allan/Desktop/unnamed1.jpg');
imshow(img1)
img1=rgb2gray(img1);
imshow(img1)
img2=im2bw(img1,graythresh(img1));
imshow(img2)
img2=~img2;
imshow(img2)
B = bwboundaries(img2);
imshow(img2)
hold on
for k = 1:length(B)
boundary = B{k};
plot(boundary(:,2), boundary(:,1), 'g', 'LineWidth', 0.2)
end
use regionprops or bwarea:
% take the NOT image
bw = ~img2;
% find individual regions
cc = bwconncomp(bw);
% find area for each black region
props = regionprops(cc,{'Area','Centroid'});
regionArea = [props(:).Area];
% find area of total black region
totalArea = bwarea(bw);
% plotting
for ii = find(regionArea > 100)
c = props(ii).Centroid;
text(c(1),c(2),num2str(regionArea(ii)),'Color','b',...
'HorizontalAlignment','center','VerticalAlignment','middle',...
'FontWeight','bold');
end

Filling region of RGB image specified by polygon in Matlab

After finding boundaries of my regions of interest in an RGB image I want to fill them with specific color on the original picture
img=imread('I.png');
BW=~im2bw(img,0.5);
B = bwboundaries(a2);
for k = 1:length(B)
boundary = B{k};
% here should color everything inside boundary in blue
end
What function can I use to do this? I tried also using imshow() and than ploting regions on it, but don't know how to save it in the original resolution.
If you insist on filling with polygon, you can use fill, but then you might face some problems:
img = imread('Prueba.jpg');
figure;
imshow(img)
BW = ~im2bw(img, 0.55);
B = bwboundaries(BW);
hold on
for k = 1:length(B)
boundary = B{k};
fill(boundary(:, 2), boundary(:, 1), 'b')
end
As shown in this example, there are regions of the image that are surrounded by a boundary but they are actually supposed to be outside the boundary.
Instead, in this way you can avoid the issue:
imgR = img(:, :, 1);
imgG = img(:, :, 2);
imgB = img(:, :, 3);
imgR(BW) = 0;
imgG(BW) = 0;
imgB(BW) = intmax(class(imgB));
IMG = cat(3, imgR, imgG, imgB);
figure; imshow(IMG)

How can I count no. of holes in an image and measure their diameter using matlab morphological operators?

So I have a graylevel image that demonstrates an electronic circuit card and I'm supposed to inspect the number of holes and the diameter of the holes, and I'm also allowed to use morphology operators in Matlab. The image is as follows:
I could wrote some codes that can count number of holes, but I don't know how to measure their diameters!
clear; close all; clc; warning off
im = imread('input\pcb.jpg');
im1 = im2bw(im,0);
% im1 = ~im2bw(im,0);
figure; imshow(im1);
strel1 = strel('disk',2);
im2 = imclose(im1,strel1);
figure; imshow(im2);
im3 = imfill(im2,'holes');
figure; imshow(im3);
im4 = im3 & ~im1;
figure; imshow(im4);
strel2 = strel('disk',3);
im5 = imopen(im4,strel2);
figure; imshow(im5);
[~,numCC] = bwlabel(im5);
fprintf('Number of holes equals:\t%d\n',numCC);
I appreciate any comments in advance!
Finally I just wrote some code, and it seems that it's working somehow perfect!
Actually the number of holes are counted as 4 and their diameters are not precise ones but they're approximated using built-in MATLAB functions. The thing is that one of the holes is not separated distinctly! and it makes the results estimated ...
clear; close all; clc; warning off
im = imread('input\pcb.jpg');
level = graythresh(im);
imBin = im2bw(im,level);
figure(1); imshow(imBin); title('Binarized Original Image');
imBinInv = ~imBin;
figure(2); imshow(imBinInv); title('Inverted Binarized Original Image');
imInvHolSep = imdilate(imerode(imBinInv,strel('disk',21)),strel('disk',23));
figure(3); imshow(imInvHolSep); title('Inverted Holes Separated');
imInHolSepBound = imInvHolSep & ~imerode(imInvHolSep,strel('disk',2));
figure(4); imshow(imInHolSepBound); title('Inverted Holes Boundaries');
imInvHolSepFill = imfill(imInHolSepBound,'holes');
figure(5); imshow(imInvHolSepFill); title('Inverted Holes Filled After Setting Boundaries');
imInvHolSepDist = imerode(imInvHolSepFill,strel('disk',1));
figure(6); imshow(imInvHolSepDist); title('Inverted Holes Eroded Just For The Case of Indistinct Hole');
imInvHolSepMinus = imInvHolSepDist & ~imBin;
figure(7); imshow(imInvHolSepMinus); title('Inverted Holes Minus The Inverted Binarized Image');
imInvHolSepSmooth = imdilate(imInvHolSepMinus,strel('disk',2));
figure(8); imshow(imInvHolSepSmooth); title('Final Approximated Inverted Holes Smoothed');
[~,numCC] = bwlabel(imInvHolSepSmooth);
fprintf('Number of holes equals:\t%d\n',numCC);
stats = regionprops(imInvHolSepSmooth);
centroid = zeros(length(stats),2);
area = zeros(length(stats),1);
for c1 = 1:length(stats)
centroid(c1,:) = stats(c1).Centroid;
area(c1) = stats(c1).Area;
fprintf('Diameter of the hole with centroid coordinates [%.2f, %.2f] is:\t%.2f\n',centroid(c1,1),centroid(c1,2),sqrt(area(c1)/pi));
end

Matlab won't superimpose rectangle

I'm trying to plot rectangles around blobs in every frame of a video. Method insertShape works but not very well. Method rectangle doesn't seem to do anything and I don't understand where's the problem as it works with a .avi file but won't with .mp4 ...
firstRunFlag = true;
threshold = 0.18;
se_erode = strel('square', 3);
se_dilate = strel('square', 30);
v = VideoReader('Traffic.mp4');
figure;
while hasFrame(v)
frame_now = readFrame(v);
if (firstRunFlag)
frame_prev = frame_now;
firstRunFlag = false;
end
frame_diff = frame_now - frame_prev;
frame_diff_grayscale = rgb2gray(frame_diff);
bw = im2bw(frame_diff_grayscale, threshold);
bw = imerode(bw, se_erode);
bw = imdilate(bw, se_dilate);
bw = imfill(bw,'holes');
boxes = regionprops(bw, 'BoundingBox');
imshow(frame_now);
for i=1:length(boxes)
this_box = boxes(i).BoundingBox;
rectangle('Position', [this_box(1), this_box(2), this_box(3), this_box(4)], 'EdgeColor', 'r', 'LineWidth', 2)
end
frame_prev = frame_now;
end
It also seems to be working on a single image, but not when displaying frame after frame...
Sometimes matlab does not update a plot, when there are several operations applied to it (like imshowing consecutive frames and rectanlges). Thus, it is useful to force matlab to update the plot using drawnow command.

Filters for noise reduction (Image Processing in Matlab)

This code simply estimates the boundaries of objects in an image for further processing
f = imread(ImageFile);
i = rgb2gray(f);
threshold = graythresh(i);
bw = im2bw(i, threshold);
imshow(bw)
se = strel('disk',3);
bw = imclose(bw,se);
bw = bwareaopen(bw, 30);
[B,L] = bwboundaries(bw,'noholes');
imshow(label2rgb(L, #jet, [.5 .5 .5]))
hold on
for k = 1:length(B)
boundary = B{k};
plot(boundary(:,2), boundary(:,1), 'w', 'LineWidth', 2)
end
It works well with this image. Correct result.
However when I tried it with this one, I get an incorrect results
(I tried more images but cannot post any more links)
the results were not even close to being perfect. I tried using Wiener filter, it smoothed out left part of the image but the right part still has a lot of noise. Median filter makes it worse.
What would be the most effective way to reduce such noise? Also I am looking for a generalized solution so that when I use it with images with similar background it still works.