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

4 次查看(过去 30 天)
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!

采纳的回答

Image Analyst
Image Analyst 2013-1-15
% 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');

更多回答(2 个)

Image Analyst
Image Analyst 2013-1-13
编辑:Image Analyst 2013-1-13
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 个评论
Dimitri
Dimitri 2013-1-15
编辑:Dimitri 2013-1-15
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!
Dimitri
Dimitri 2013-1-18
编辑:Dimitri 2013-1-18
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?

请先登录,再进行评论。


Dimitri
Dimitri 2013-1-23
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

Community Treasure Hunt

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

Start Hunting!

Translated by