How can I "remove" a certain part of a colored image? (Double Edges??)

Okay, So I have hundreds of images that I need to analyze using MATLAB. The Images are of the underside of a turtle. The images looks something like this (not the image im using, but just for reference) http://upload.wikimedia.org/wikipedia/commons/2/28/B3_Southern_painted_turtle_underside.jpg.
I want to get rid of the "body of the turtle, and just have the shell to work with (if you know turtle parts, i just want to use the plastron). I have tried using many edge detection codes, but i cant seem to just get rid of the "body" of the turtle.
Here's an example of what im trying to do/have so far.
f = imread('IMG_0003.jpg');
g = imcrop(f,[750 500 1800 1300]);
imshow(g)
% % % reads and crops
B=rgb2gray(g);
D=double(B);
for i=1:size(D,1)-2
for j=1:size(D,2)-2
%Sobel mask for x-direction:
Gx=((2*D(i+2,j+1)+D(i+2,j)+D(i+2,j+2))-(2*D(i,j+1)+D(i,j)+D(i,j+2)));
%Sobel mask for y-direction:
Gy=((2*D(i+1,j+2)+D(i,j+2)+D(i+2,j+2))-(2*D(i+1,j)+D(i,j)+D(i+2,j)));
%The gradient of the image
%B(i,j)=abs(Gx)+abs(Gy);
B(i,j)=sqrt(Gx.^2+Gy.^2);
end
end
figure,imshow(B); title('Sobel gradient');
% % % Converts it to gray scale, edge detection.
C = num2cell(D);
C(~D) = {{}};
imagesc(D, 'AlphaData', D)
colormap(gray)
set(gca, 'color', 'none')
Z = cell2mat(C);
% % % % Removes the background
q = double(Z);
im=mat2gray(q);
level = graythresh(im);
imb = im2bw(im,level);
imb = ~imb;
hope = imfill(imb,'holes');
figure,imshow(hope); title('HOPE');
A = numel(hope(hope==0))
B = numel(hope(hope==1))
******* I am a beginner at Matlab, so sorry for that. But, if you look at the image "hope", you can see that i can get an image of the entire turtle and shell to be white while discluding the background. I then counted the pixels of white to find how many made up the turtle. I WANT TO DO THIS WITH ONLY THE SHELL! (So maybe theres a way to highlight both the inner and outer edge and then cut out that middle part??? I dont know).
Please, any help would be greatly appreciated!! :) THANKS!
PS: I'm doing this so I can eventually find a proportion of "orange colored pixels on the turtle shell" to the "whole shell" of the turtle. I'm doing this for analytical purposes, so i can corolate this value to the same ratio on the top of the turtle shell. So once again, Just want to cut out the "body of the turtle" and be left with the shell. Thank you!

 Accepted Answer

% Demo to write an ellipse and a line into the overlay of an image,
% and then to burn those overlays into the image.
%----- Initializing steps -----
% Clean up
clc;
clear all;
close all;
workspace; % Display the workspace panel.
hasIPT = license('test', 'image_toolbox');
if ~hasIPT
% User does not have the toolbox installed.
message = sprintf('Sorry, but you do not seem to have the Image Processing Toolbox.\nDo you want to try to continue anyway?');
reply = questdlg(message, 'Toolbox missing', 'Yes', 'No', 'Yes');
if strcmpi(reply, 'No')
% User said No, so exit.
return;
end
end
% Display images to prepare for the demo.
monochromeImage = imread('pout.tif');
subplot(2, 4, 1);
imshow(monochromeImage);
title('Original Image');
subplot(2, 4, 2);
imshow(monochromeImage);
title('Original Image with ellipse in overlay');
subplot(2, 4, 5);
imshow(monochromeImage);
title('Original Image');
subplot(2, 4, 6);
imshow(monochromeImage);
title('Original Image with line in overlay');
set(gcf, 'units','normalized','outerposition',[0 0 1 1]); % Maximize figure.
set(gcf,'name','Image Analysis Demo','numbertitle','off')
%----- Burn ellipse into image -----
% Create elliptical mask, h, as an ROI object over the second image.
subplot(2, 4, 2);
hEllipse = imellipse(gca,[10 10 50 150]); % Second argument defines ellipse shape and position.
% Create a binary image ("mask") from the ROI object.
binaryImage = hEllipse.createMask();
% Display the ellipse mask.
subplot(2, 4, 3);
imshow(binaryImage);
title('Binary mask of the ellipse');
% Let's try to add some text. (Doesn't work)
% hText = text(50, 100, 'Line of Text');
% textMask = hText.createMask();
% binaryImage = binaryImage & textMask;
% imshow(binaryImage);
% Burn ellipse into image by setting it to 255 wherever the mask is true.
monochromeImage(binaryImage) = 255;
% Display the image with the "burned in" ellipse.
subplot(2, 4, 4);
imshow(monochromeImage);
title('New image with ellipse burned into image');
%----- Burn line into image -----
burnedImage = imread('pout.tif');
% Create line mask, h, as an ROI object over the second image in the bottom row.
subplot(2, 4, 6);
hLine = imline(gca,[10 100],[10 100]); % Second argument defines line endpoints.
% Create a binary image ("mask") from the ROI object.
binaryImage2 = hLine.createMask();
% Display the line mask.
subplot(2, 4, 7);
imshow(binaryImage2);
title('Binary mask of the line');
% Burn line into image by setting it to 255 wherever the mask is true.
burnedImage(binaryImage2) = 255;
% Display the image with the "burned in" line.
subplot(2, 4, 8);
imshow(burnedImage);
title('New image with line burned into image');

More Answers (2)

I don't know why you used edge detection. Simple thresholding will do it. Similarly, using cell arrays and cropping (at least for that image) are unnecessary.
Anyway, I think you'll have to use imline() to draw a line across the legs, head, and tail? Why? Because legs are both under the shell area and outside the shell are. You want to consider the part of the leg under the shell as "shell" but you don't want the part of the leg not under the shell to count as shell area. And without getting really complicated, you can't do it. Assuming you have only a few hundred images or so, it will be faster to just manually draw across the body parts jutting out. Then once that's done, you can just threshold to find the total shell. Then call regionprops to get the areas. The largest area is the shell of course - smaller areas are the legs, head, or tail. Now do color segmentation -- there are several examples of different methods in my File Exchange. You might have to do a morphological closing to get rid of some lines on the legs which are pretty close in color to the lighter undershell color. Now you have everything - total shell area, and lighter undershell area.
But I didn't see a ColorChecker chart in the image. Depending on how variable your illumination and exposure are, you might need this.

11 Comments

Thank you so much for your response! Sorry I didn't respond quicker, I didn't have access to this stuff until today. But, is there any way to do it without using imline? I have a couple thousand images to go through and this could prove very timely. As for the cropping, I used cropping because in the actual images I have, there is a black and white strip at the top of the image that I figured might interfere with my analysis (it's just four squares, black-white-black-white in the top left corner. Maybe this is some color checker thing, I'm not sure since I didn't take the images, I'm just figuring out how to do an analysis. I could figure that out though. Also, for the colors in the images I'm using, the turtle shell isn't as pale as that in comparison to the rest of the turtle. As a whole it has more of a darker color, and the shell tends to just have like ribbons or "splotches" of orange that I wanted to measure.
Thanks again!
Can you upload any of your images?
Ohh and one more thing, if I need to use the imline() command, how exactly do I use this to cut out the legs, tail, head? Sorry, like I said, I'm just starting to use MATLAB.
Give me a minute and I will try.
http://www.facebook.com/pages/Terrapin-Station-and-Freshwater-Turtles/118675974883450 If you go to this page, the two images that were just added show the top and bottomg of the turtle.
Well the legs look so much like the shell, and they are tucked in various amounts, so it would be difficult to find which little bump in the outline is part of a leg sticking out as opposed to just part of the shell. So I think a manual method is probably the way to go. If you wanted to try, you could fit an ellipse to the shell and mask off anything that stuck outside the ellipse, figuring that anything what stuck out was a leg. That might sort of work for some images but wouldn't be robust enough to do it correctly on thousands of images. See my code below for how to write a line into an image. You' want to write in a line with gray levels 255 so that it basically draws a background line between the shell and the leg sticking out.
I'm having a little trouble understanding. So, I write in the line, and it will "burn out" that line segment from the image (separating the leg from the shell area). Doing this will allow me to keep from including the legs in my calculations by ignoring their areas? Is this correct? And is there a way to draw multiple lines at once, or no? Do I have to draw the line then finish then "call" the new image to draw another line?
Here is what I have so far. So a few questions, why do the lines appear as red dotted lines when I run the code? Also, what am I supposed to use the thresholding for? To turn the image to black and white? and then just take the area of the shell? I'm assuming after I do this I should recall the just cropped image to do color segmentation, and use the value I get for the orange from that with the value I get from the black and white image?
% % % % % COLOR ANALYSIS FOR SHELL COLOR % % % % %
f = imread('IMG_0001.jpg');
g = imcrop(f,[750 500 1800 1300]);
imshow(g); title ('Cropped Image');
% % % reads and crops % % %
% % % DRAW LINES % % %
% % % Line1 % % %
burnedImage = g;
hLine = imline();
binaryImage1 = hLine.createMask();
burnedImage(binaryImage1) = 255;
imshow(burnedImage); title('BurnedImage1');
% % % Line2 % % %
hLine=imline();
binaryImage2 = hLine.createMask();
burnedImage(binaryImage2) = 255;
imshow(burnedImage); title('BurnedImage2');
% % % Line3 % % %
hLine=imline();
binaryImage3 = hLine.createMask();
burnedImage(binaryImage3) = 255;
imshow(burnedImage); title('BurnedImage3');
% % % Line4 % % %
hLine=imline();
binaryImage4 = hLine.createMask();
burnedImage(binaryImage4) = 255;
imshow(burnedImage); title('BurnedImage4');
% % % Line5 % % %
hLine=imline();
binaryImage5 = hLine.createMask();
burnedImage(binaryImage5) = 255;
imshow(burnedImage); title('BurnedImage5');
Also, the lines don't appear to be solid, which im guessing will be a problem.
BW = im2bw(burnedImage, .5); %converts the truecolor image RGB to a binary image.%
imshow(BW);
I added this on to the bottom of the code.
I revised the code to the following:
% % % % % COLOR ANALYSIS FOR SHELL COLOR % % % % %
% % % reads and crops % % %
f = imread('IMG_0001.jpg');
g = imcrop(f,[750 500 1800 1300]);
figure, imshow(g); title ('Cropped Image');
% % % Converts to BW Image to fill shell and cut out parts that are not shell % % %
burnedImage = g;
BW = im2bw(burnedImage, .5); % converts the truecolor image RGB to a binary image %
BW=~BW; % Inverse of the BW image %
filled = imfill(BW, 'holes'); % Fills the holes of the shell %
filled=~filled; % Inverse of the filled image %
figure, imshow(filled); title('Filled Black and White Image');
% % % DRAW LINES % % %
burnedImage = filled;
% % % Line1 % % %
hLine = imline();
binaryImage1 = hLine.createMask();
burnedImage(binaryImage1) = 255;
imshow(burnedImage); title('BurnedImage1');
% % % Line2 % % %
hLine=imline();
binaryImage2 = hLine.createMask();
burnedImage(binaryImage2) = 255;
imshow(burnedImage); title('BurnedImage2');
% % % Line3 % % %
hLine=imline();
binaryImage3 = hLine.createMask();
burnedImage(binaryImage3) = 255;
imshow(burnedImage); title('BurnedImage3');
% % % Line4 % % %
hLine=imline();
binaryImage4 = hLine.createMask();
burnedImage(binaryImage4) = 255;
imshow(burnedImage); title('BurnedImage4');
% % % Line5 % % %
hLine=imline();
binaryImage5 = hLine.createMask();
burnedImage(binaryImage5) = 255;
imshow(burnedImage); title('BurnedImage5');
burnedImage = ~burnedImage % So the Shell is the white (counted Area) %
figure, imshow(burnedImage); title('Image for Analysis');
% % % Find Area of each Region % % %
STATS = regionprops(burnedImage, 'Area');
STATS
For some reason, STATS returns: 12x1 struct array with fields: Area Not sure what this means. Nevermind fixed that by taking out the last inverse. It is returning just one area though, how should I go about getting values for separated regions? Any suggestions? Thanks!
I found out what that meant, and how to get the code to output the area, and only the largest area (which is what I'm looking for). I still need help on why the lines aren't "solid" and how to make them solid though.
I posted a question specific to what I need and it can be found by searching the following:
How do you make lines solid and/or thicker? How do you "split" an image by drawing a line at the desired location?

Sign in to comment.

My question has been answered and addressed by Image Analyst, and can be found by searching for the following:
How do you make lines solid and/or thicker? How do you "split" an image by drawing a line at the desired location? Image Segmentation

Categories

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!