You are now following this question
- You will see updates in your followed content feed.
- You may receive emails, depending on your communication preferences.
how to connect coordinate points?
4 views (last 30 days)
Show older comments
I have used bwlabel to label the connected components of a picture.Then I have used find() to have the coordinates for the pixels in object 1 and saved it in [r c].
Now is there any way to use those co-ordinate and draw them again to reconstruct the object?
My code is something like that::
img = imread('global1.jpg');
b_img = im2bw(img);
[m,n] = bwlabel(b_img,4);
[r c] = find(m==1);
Accepted Answer
Matt Kindig
on 4 Oct 2012
Hi Sayak,
I'm a little bit unclear on what you are trying to do, but I think you want to use bwboundaries. That will give you the coordinates on the border of the image, which you can then use to reconstruct the object.
doc bwboundaries
doc bwtraceboundary
4 Comments
Sayak
on 4 Oct 2012
First thanks for your reply. See the picture given above which contains a silhouette of a man and a woman. Now when I use bwlabel it returns vectors of indices for the pixels that make up a specific object.
In my case [r,c] = find(bwlabel(b_img)==2) results in an array of coordinate points based on the array [r,c]. now what I want to do is to isolate the picture of girl from the boy. And my approach was to use bwlabel(b_img) == 1 [for male] or bwlabel(b_img) == 2 [for female]. And use the coordinate points and to isolate them.
Is my approach is right? What should I do for better result?
Matt Kindig
on 4 Oct 2012
The output of bwlabel gives you a label matrix, which identifies each distinct region. You can then use your approach to isolate the male and female images. That is,
L = bwlabel(b_img,4);
male = (L==1); %these might be reversed, i.e. male=1, female=2
female = (L==2);
Sayak
on 5 Oct 2012
Edited: Sayak
on 5 Oct 2012
Yes I have done that. Now to distinguish male and female I have used the following approach.
1) Taking an array full of 0's, having a size equal to the original image and named this array as 'mask'.
2) Storing the values of Male (by doing male = find(L==1);) in [r c].
3) For each values of male array, I have changed the value of the array mask to 1. Thus it will only show the pixel positions of male in the mask.
4)Typecast mask to logical/uint8 and do a imshow() thus only to show the male-part of the original image.
Problem : As the main image is of 90 x 91 and the mask is also 90 x 91. But the male array is of 6021 x 2. So whenever I am checking the values of mask and male it produces 'array out of bound exception'.
I do not know how to get rid of that problem. What should I do?
My code so far::
img = imread('C:\Users\Sayak\Documents\MATLAB\mat_pic\global1.jpg');
%img = imresize(img,0.5);
b_img = im2bw(img);
[glo_r,glo_c,glo_p] = size(b_img);
%edge(b_img);
for i = 1 : glo_r
for j = 1 : glo_c
mask(i,j) = 0;
end
end
[m,n] = bwlabeln(b_img,4);
[r1 c1] = find(m==1);
rc = [r1 c1];
for i = 1 : glo_r
for j = 1 : glo_c
if(mask(i,j) ~= rc(i,j))
mask(i,j) = 1;
end
end
end
imshow(logical(mask)); % is it correct approach ?
Image Analyst
on 6 Oct 2012
No, this is definitely NOT the correct approach. It will absolutely fail for many images. See my latest comment.
More Answers (1)
Image Analyst
on 4 Oct 2012
Edited: Image Analyst
on 5 Oct 2012
The usual Mathworks-recommended way is to use ismember():
keeperBlobsImage = ismember(labeledImage, blobNumberToKeep);
where blobNumberToKeep can be either a single number of a vector of numbers that you want to keep. See my BlobsDemo for a demo http://www.mathworks.com/matlabcentral/fileexchange/?term=authorid%3A31862 - I extract out two types of coins from the standard MATLAB demo image.
22 Comments
Image Analyst
on 5 Oct 2012
Sorry - that was the answers profile. I've corrected it to my File Exchange. Look for "Image Segmentation Tutorial - BlobsDemo". http://www.mathworks.com/matlabcentral/fileexchange/?term=authorid%3A31862
Sayak
on 6 Oct 2012
Its a super work. But being a beginner I feel it somehow tough to understand. I have done something to distinguish connected components. My code is working fine with manual array. But when I am working with the picture, it is not showing the male and female images differently.
My Code::
BW = [1 1 1 0 0 0 0 0
1 1 1 0 1 1 0 0
1 1 1 0 1 1 0 0
1 1 1 0 0 0 1 0
1 1 1 0 0 0 1 0
1 1 1 0 0 0 1 0
1 1 1 0 0 1 1 0
1 1 1 0 0 0 0 0];
BW = im2bw(BW);
figure, imshow(BW);
[gr,gc,gp] = size(BW);
mask = zeros(gr,gc);
[L n]= bwlabel(BW,4);
[r c] = find(L==1);
rc = [r c];
% temp(gr,gc);
[a,b]=size(rc);
for i = 1 : gr
for j = 1 : gc
m = 1; while(m<=a)
if(i==rc(m,1) && j==rc(m,2))
mask(i,j) = 1;
end
m = m + 1;
end
end
end
figure, imshow(uint8(mask)); % mask contains the rows and columns of objects returned by find()
This works fine unless I am providing the picture (link above) to BW.
Image Analyst
on 6 Oct 2012
Edited: Image Analyst
on 6 Oct 2012
No, that's the inefficient, complicated, non-MATLAB way of doing it. You can do all that with just one line:
blob1 = ismember(L, 1);
instead of using mask, zeros(), find(), im2bw(), the "for" loop, the "while" loop, the "if" statement, etc. All that is totally unnecessary and just makes it way more complicated than it needs to be.
Here, here's a full-blown demo, using your image of 3 blobs, where I extract each of the 3 blobs one at a time. Note that if you label with 8 connectivity instead of 4 connectivity, you'd have just 2 blobs since it would consider blobs touching at the pixel corners to be part of the same blob, while 4 connectivity considers them as separate blobs.
BW = [...
1 1 1 0 0 0 0 0
1 1 1 0 1 1 0 0
1 1 1 0 1 1 0 0
1 1 1 0 0 0 1 0
1 1 1 0 0 0 1 0
1 1 1 0 0 0 1 0
1 1 1 0 0 1 1 0
1 1 1 0 0 0 0 0];
subplot(2, 3,1);
imshow(BW, 'InitialMagnification', 800);
title('Original Binary Image', 'FontSize', 20);
% Label the image with 4 connectivity
[L n]= bwlabel(BW, 4);
% Note: 8 connectivity would get you two blobs.
% Display the three blobs.
subplot(2, 3, 2);
imshow(L, [], 'InitialMagnification', 800);
title('Labeled Image', 'FontSize', 20);
coloredLabels = label2rgb (L, 'hsv', 'k', 'shuffle'); % pseudo random color labels
subplot(2, 3, 3);
imshow(coloredLabels, []);
title('Labeled Image, with colored labels.', 'FontSize', 16);
%======== KEY PART BELOW =======================
% Extract the two blobs.
blob1 = ismember(L, 1);
blob2 = ismember(L, 2);
blob3 = ismember(L, 3);
%======== KEY PART ABOVE =======================
% Display the blobs.
subplot(2, 3, 4);
imshow(blob1, 'InitialMagnification', 800);
title('Blob 1', 'FontSize', 20);
subplot(2, 3, 5);
imshow(blob2, 'InitialMagnification', 800);
title('Blob 2', 'FontSize', 20);
subplot(2, 3, 6);
imshow(blob3, 'InitialMagnification', 800);
title('Blob 3', 'FontSize', 20);
% Enlarge figure to full screen.
set(gcf, 'units','normalized','outerposition',[0 0 1 1]);
Thanks for the comment about BlobsDemo. I thought it was easy for beginners since I had more comments than lines of code. Since it's designed for beginners, I'll have to take a look at it to see how it can be made even more instructive.
Sayak
on 7 Oct 2012
Ok, I understand now. But consider this picture ::
It can clearly visible that male and female are not connected. Now, even if I use blob, still I am unable to differentiate the male from the female. May be in that case what I need is to use only those connected components who's size are big than some threshold value. Taking your advice if I do this,
[L n]= bwlabel(BW, 4);
for (i = 1 : n)
blob(i) = ismember(L, i);
end
then it again would be a non-robust approach as I do not need every connected component for the differentiation of male from female. So what should I do here and why is the blob approach is unable to find those male and female separately?
Image Analyst
on 7 Oct 2012
No, you can't do that. ismember returns an entire image, where as blob(i) can take only a single number, not a whole array of numbers. I'm not sure why you say that you can't get the two shapes. You can. Just do this:
shape1 = ismember(L, 1); % Left hand side shape = man.
shape2 = ismember(L, 2); % Right hand side shape = woman.
Those are integer/grayscale/labeled images. If you want binary images, you can just compare to zero.
binaryShape1 = ismember(L, 1) > 0;
binaryShape2 = ismember(L, 2) > 0;
Image Analyst
on 7 Oct 2012
OK, in case my latest comment is still not enough, I downloaded your image and applied my code to it. Here I extract each shape:
clc; % Clear the command window.
close all; % Close all figures (except those of imtool.)
imtool close all; % Close all imtool figures.
clear; % Erase all existing variables.
workspace; % Make sure the workspace panel is showing.
format longg;
format compact;
fontSize = 14;
% Read in a standard MATLAB gray scale demo image.
folder = 'C:\Users\Mark\Documents\Temporary';
% Read in a standard MATLAB color demo image.
baseFileName = 'man_woman.jpg';
% Get the full filename, with path prepended.
fullFileName = fullfile(folder, baseFileName);
if ~exist(fullFileName, 'file')
% Didn't find it there. Check the search path for it.
fullFileName = baseFileName; % No path this time.
if ~exist(fullFileName, 'file')
% Still didn't find it. Alert user.
errorMessage = sprintf('Error: %s does not exist.', fullFileName);
uiwait(warndlg(errorMessage));
return;
end
end
rgbImage = imread(fullFileName);
grayImage = rgbImage(:,:,2); % Get green channel as a gray scale image.
% Get the dimensions of the image. numberOfColorBands should be = 3.
[rows columns numberOfColorBands] = size(rgbImage);
% Display the original color image.
subplot(2, 3, 1);
imshow(grayImage, []);
title('Original Gray Image', 'FontSize', fontSize);
% Enlarge figure to full screen.
set(gcf, 'units','normalized','outerposition',[0 0 1 1]);
% Binarize it.
binaryImage = grayImage < 128;
subplot(2, 3, 2);
imshow(binaryImage);
title('Original Binary Image', 'FontSize', 20);
% Label the image with 4 connectivity
[L n]= bwlabel(binaryImage, 4);
% Note: 8 connectivity would get you two blobs.
% Display the three blobs.
subplot(2, 3, 3);
imshow(L, [], 'InitialMagnification', 800);
title('Labeled Image', 'FontSize', 20);
coloredLabels = label2rgb (L, 'hsv', 'k', 'shuffle'); % pseudo random color labels
subplot(2, 3, 4);
imshow(coloredLabels, []);
title('Labeled Image, with colored labels.', 'FontSize', 16);
%======== KEY PART BELOW =======================
% Extract the two blobs.
blob1 = ismember(L, 1);
blob2 = ismember(L, 2);
%======== KEY PART ABOVE =======================
% Display the blobs.
subplot(2, 3, 5);
imshow(blob1, 'InitialMagnification', 800);
title('Blob 1', 'FontSize', 20);
subplot(2, 3, 6);
imshow(blob2, 'InitialMagnification', 800);
title('Blob 2', 'FontSize', 20);
Sayak
on 8 Oct 2012
First thank you. Now, I understood the functionality of that function. Using blob works fine here. But in the case where the picture is somehow complicated (i.e. where some background is present and different objects are actually connected), how to use ismember() function to distinguish them?
Another, if I use bwboundaries() and distinguish different area of a connected component, then based on that, can I crop that particuler area?
Image Analyst
on 10 Oct 2012
No background subtraction is needed, just thresholding.
Sayak
on 11 Oct 2012
I tried this following code hence to extract the connected 'big component' but in vein.
I = imread('1.jpg');
level = graythresh(I);
BW = im2bw(I, level);
figure;imshow(BW)
BW = im2bw(rgb2gray(I), 0.25);
figure;
imshow(BW);
BW1 = BW;
CC = bwconncomp(BW);
numPixels = cellfun(@numel,CC.PixelIdxList);
[biggest,idx] = max(numPixels);
BW(CC.PixelIdxList{idx}) = 0;
figure, imshow(BW);
figure, imshow(BW1);
Ir = imsubtract(BW1,BW);
figure;
imshow(Ir)
So, what should I do in case where I need to detect foreground elements? What changes should I make in my code above?
Image Analyst
on 11 Oct 2012
You need to call regionprops. See my image segmentation demo in my File Exchange.
Sayak
on 12 Oct 2012
Ok, I have understood the segmentation that you have done. And its based upon area and intensity. I have tried it but the fact is that whenever I am trying to crop the image based upon Bounding Box area, its not giving the desirable output (not detecting a human and crop him/her properly). I have done the following (following your way from the segmentation demo)
read image
- binary conversion
- labeling the image
- regionprops
- finding blobArea
- finding allowableAreaIndexes
- keeperIndexes using ismember()
- for 1 to n number of blobs
- measure boudningBox and keep it in thisBlobsBoundingBox
- imcrop(keeperBlobsImage, thisBlobsBoundingBox);
- subplot them.
But the problem is it does not showing different objects within the rectangular bounding box. How to do that?
Image Analyst
on 12 Oct 2012
This is completely different than a 2 gray level silhouette - this is a full color photograph. Please give the code you used to take that photo and arrive at the binary image of the three people.
Sayak
on 13 Oct 2012
Edited: Image Analyst
on 14 Oct 2012
I have read the picture then changed it to gray-scale and at last I am able to segment the picture based on the binary mask.But the problem is the blob-approach is not working here. Here is the code.
%--------------------------------------------------------------
clc;
clear mem;
clear all;
% Take the input Image
originalImage=imread('C:\Users\Sayak\Documents\MATLAB\mat_pic\human.jpg');
subplot(2,2,1); imshow(originalImage); title('originalImage');
%Change Color space
hsvColorspace=rgb2hsv(originalImage);
subplot(2,2,2); imshow(hsvColorspace); title('hsvColorspace');
% Gray Scale Conversion with respect to blue
GrayScaleImage=hsvColorspace(:,:,1);
%GrayScaleImage = bwareaopen(GrayScaleImage,100);
[rows columns planes]=size(GrayScaleImage);
%Creating Binary Mask
BinaryMask= GrayScaleImage > 0.5;
subplot(2,2,3);
imshow(BinaryMask);
title('BinaryMask');
h = waitbar(0,'Please wait...');
% Pre-allocating mask
segmentationMask=[];
for i=1:rows
for j=1:columns
if BinaryMask(i,j) == 1
segmentationMask(i,j,1)=originalImage(i,j,1);
segmentationMask(i,j,2)=originalImage(i,j,2);
segmentationMask(i,j,3)=originalImage(i,j,3);
else
segmentationMask(i,j,1)=0;
segmentationMask(i,j,2)=0;
segmentationMask(i,j,3)=0;
end
end
waitbar(i/rows,h)
end
segmentedImage=uint8(segmentationMask);
subplot(2,2,4);
imshow(segmentedImage);
title('segmentedImage');
%--------------------------------------------------------
Now how to apply the blob-approach to distinguish the people from the image?
Image Analyst
on 14 Oct 2012
No, sorry but that algorithm is way way too primitive to extract out the silhouettes of the people. You can't just find all the reddish pixels in the image and expect that you'll get each person, including their closing, which is not red and overlaps. YUV color space will be no better than hsv colorspace.
Image Analyst
on 15 Oct 2012
In general, watershed segmentation. See Steve Eddins's demo: http://blogs.mathworks.com/steve/2006/06/02/cell-segmentation/
See Also
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!An Error Occurred
Unable to complete the action because of changes made to the page. Reload the page to see its updated state.
Select a Web Site
Choose a web site to get translated content where available and see local events and offers. Based on your location, we recommend that you select: .
You can also select a web site from the following list
How to Get Best Site Performance
Select the China site (in Chinese or English) for best site performance. Other MathWorks country sites are not optimized for visits from your location.
Americas
- América Latina (Español)
- Canada (English)
- United States (English)
Europe
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom (English)
Asia Pacific
- Australia (English)
- India (English)
- New Zealand (English)
- 中国
- 日本Japanese (日本語)
- 한국Korean (한국어)