How to create a silhouette from image

4 ビュー (過去 30 日間)
Brenton Poke
Brenton Poke 2017 年 2 月 23 日
回答済み: Shiba Kuanar 2019 年 10 月 11 日
I need to create a silhouette from an image to take the central moments on for a car classifier. I've already been able to process the image using k-means clustering, but can't get the last part of my problem solved. I basically need to remove the largest region that touches all four borders of the image, then make the rest black (leaving a white background). Below are how far I've gotten to my goal. How can I go from the second image to what i'm looking for?

採用された回答

Image Analyst
Image Analyst 2017 年 2 月 24 日
Try this. You'll see you get a black silhouette of the car (including the shadow since your kmeans did not classify it as part of the background, but as part of the car which is why I didn't recommend kmeans):
clc; % Clear the command window.
close all; % Close all figures (except those of imtool.)
clear; % Erase all existing variables. Or clearvars if you want.
workspace; % Make sure the workspace panel is showing.
format long g;
format compact;
fontSize = 15;
%===============================================================================
% Get the name of the image the user wants to use.
baseFileName = 'Full image k=3.bmp';
% Get the full filename, with path prepended.
folder = pwd
fullFileName = fullfile(folder, baseFileName);
%===============================================================================
% Read in demo image.
indexedImage = imread(fullFileName);
% Get the dimensions of the image.
[rows, columns, numberOfColorChannels] = size(indexedImage);
% Display the original image.
subplot(2, 2, 1);
imshow(indexedImage, []);
axis on;
caption = sprintf('Original kmeans Indexed Image, %s', baseFileName);
title(caption, 'FontSize', fontSize, 'Interpreter', 'None');
% Set up figure properties:
% Enlarge figure to full screen.
set(gcf, 'Units', 'Normalized', 'OuterPosition', [0 0 1 1]);
% Get rid of tool bar and pulldown menus that are along top of figure.
set(gcf, 'Toolbar', 'none', 'Menu', 'none');
% Give a name to the title bar.
set(gcf, 'Name', 'Demo by ImageAnalyst', 'NumberTitle', 'Off')
drawnow;
hp = impixelinfo(); % Set up status line to see values when you mouse over the image.
% Get a mask for the value of the pixels in the upper left corner at pixel 2,2
% Because there seems to be a 1 pixel wide edge effect so we're going in one pixel.
mask = indexedImage == indexedImage(2, 2);
% Display the image.
subplot(2, 2, 2);
imshow(mask, []);
axis on;
caption = sprintf('Initial Mask Image');
title(caption, 'FontSize', fontSize, 'Interpreter', 'None');
drawnow;
% Get largest region, which will be the background..
mask = bwareafilt(mask, 1);
% Fill holes.
mask = ~bwareafilt(~mask, 1);
% Display the image.
subplot(2, 2, 3);
imshow(mask, []);
axis on;
caption = sprintf('Silhouette Image');
title(caption, 'FontSize', fontSize, 'Interpreter', 'None');
drawnow;
  2 件のコメント
Image Analyst
Image Analyst 2017 年 2 月 24 日
So basically 3 lines of code:
mask = indexedImage == indexedImage(2, 2);
mask = bwareafilt(mask, 1);
mask = ~bwareafilt(~mask, 1);
get you what you asked for, doesn't it? You could even get that down to one line of code if you wanted:
mask = ~bwareafilt(~bwareafilt(indexedImage == indexedImage(2, 2), 1), 1);
but that's a bit cryptic and hard to follow.
If you want the silhouette white instead of black, get rid of the ~ before bwareafilt() on the last line:
mask = indexedImage == indexedImage(2, 2);
mask = bwareafilt(mask, 1);
mask = bwareafilt(~mask, 1);
Brenton Poke
Brenton Poke 2017 年 2 月 27 日
編集済み: Brenton Poke 2017 年 2 月 27 日
That works beautifully with my current code, thanks! This was my result.

サインインしてコメントする。

その他の回答 (4 件)

Image Analyst
Image Analyst 2017 年 2 月 23 日
You don't need kmeans. It's not needed for an image like that. Just wastes time for no reason. Simply find a mask and you're done
topGL = 255; % Whatever white is.
silhouetteImage = rgbImage(:,:,1) < topGL | rgbImage(:,:,2) < topGL | rgbImage(:,:,3) < topGL;
imshow(silhouetteImage); % Display logical/binary image.
  2 件のコメント
Brenton Poke
Brenton Poke 2017 年 2 月 23 日
I'm not sure how to apply your code or what it means. I used the k-means method because that's what I learned in a course and much of the code for it was done for us. I'm really close and just want to work off of what I already have done.
Image Analyst
Image Analyst 2017 年 2 月 23 日
I'm just making a mask of everything that is not pure white. If you want to do it the more complicated way using kmeans(), then you need to take your kmeans image and extract the class that is the background, and use bwareafilt() (because there are more purple regions there than just the surround).
% kmeans code..... like attached demo.... then...
backgroundClass = kmeansImage == 1; % Or whatever index it is.
silhouetteImage = bwareafilt(backgroundClass, 1); % Extract largest region.
imshow(silhouetteImage); % Display logical/binary image.

サインインしてコメントする。


John BG
John BG 2017 年 2 月 23 日
Hi Brenton
please help me out and tell if I am on the right direction
1.
capture
A=imread('etiquette.jpg');
% figure(1);imshow(A);
2. picking on peculiar combination of car colour
A(A<80)=255;
figure(2);imshow(A)
A1=A(:,:,1);A2=A(:,:,2);A3=A(:,:,3);
p1=find(A1>200);
p2=find(A2<170);
pc=intersect(p1,p2);
B=zeros(size(A1));
B(pc)=255;
figure(3);imshow(B)
.
would the chassis do as point for, from here, get the silhouette?
there is a bit of noise and reflection ribbon, you may also want it off, right?
awaiting answer
John BG
  6 件のコメント
Image Analyst
Image Analyst 2017 年 2 月 24 日
Did you see my second answer (below)? It does what you want in 3 lines of code.
John BG
John BG 2017 年 2 月 24 日
Brenton
because you told me to start from the image you obtained with your K-means analysis I started from im2.jpg here attached.
The size may not match because I took the image from your question.
Apply my lines to the outcome of your K-means, check it works with im2.jpg here attached.
John BG

サインインしてコメントする。


Shiba Kuanar
Shiba Kuanar 2019 年 10 月 11 日
Hi All,
I used the code - to get a black silhouette of the car (very beginning)
I am getting the result but with some error message (below): (also attached figure for review)
__________________________________________________________________
Error using images.internal.imageDisplayValidateParams>validateCData (line 119)
If input is logical (binary), it must be two-dimensional.
Error in images.internal.imageDisplayValidateParams (line 27)
common_args.CData = validateCData(common_args.CData,image_type);
Error in images.internal.imageDisplayParseInputs (line 78)
common_args = images.internal.imageDisplayValidateParams(common_args);
Error in imshow (line 241)
images.internal.imageDisplayParseInputs({'Parent','Border','Reduce'},preparsed_varargin{:});
Error in SilhouetShiba (line 44)
imshow(mask, []);
  1 件のコメント
Image Analyst
Image Analyst 2019 年 10 月 11 日
TestImageSIL.png is probably not a grayscale image. Use rgb2rgray() to make in into grayscale.

サインインしてコメントする。


Shiba Kuanar
Shiba Kuanar 2019 年 10 月 11 日
Thank You

カテゴリ

Help Center および File ExchangeConvert Image Type についてさらに検索

Community Treasure Hunt

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

Start Hunting!

Translated by