이 질문을 팔로우합니다.
- 팔로우하는 게시물 피드에서 업데이트를 확인할 수 있습니다.
- 정보 수신 기본 설정에 따라 이메일을 받을 수 있습니다.
How can one distinguish the background from the foreground and detect the edges of the seedling?
조회 수: 1 (최근 30일)
이전 댓글 표시
What are some effective approaches or methodologies that can be utilized to differentiate between the background and foreground and accurately delineate the edges of the seedling? I am attaching a image with thier expected results.
input and expect output is
답변 (1개)
Image Analyst
2023년 6월 15일
This is pretty trivial. Simply use the Color Thresholder on the Apps tab of the tool ribbon. Use it and export the function. Write back if you can't figure it out.
댓글 수: 11
Dynamic
2023년 6월 15일
@Image Analyst Sorry for minimul information I have provided. I want an automated code
Image Analyst
2023년 6월 15일
편집: Image Analyst
2023년 6월 15일
Did you even attempt to use the Color Threshold to generate "auomated" code? And what do you really want? Just the edges (then what)? The area? The color? The area fraction? I mean, you must want something other than the edges, which don't do you much good as a final result.
To learn other fundamental concepts, invest 2 hours of your time here:
Image Analyst
2023년 6월 16일
OK, I guess you're having a lot of trouble. Try this:
% Demo to find area and boundaries of a green region.
% By Image Analyst.
clc; % Clear the command window.
close all; % Close all figures (except those of imtool.)
clearvars;
workspace; % Make sure the workspace panel is showing.
format long g;
format compact;
fontSize = 18;
fprintf('Beginning to run %s.m ...\n', mfilename);
%-----------------------------------------------------------------------------------------------------------------------------------
% Read in image.
folder = pwd;
baseFileName = 'dynamic.png';
fullFileName = fullfile(folder, baseFileName);
% Check if file exists.
if ~exist(fullFileName, 'file')
% The file doesn't exist -- didn't find it there in that folder.
% Check the entire search path (other folders) for the file by stripping off the folder.
fullFileNameOnSearchPath = baseFileName; % No path this time.
if ~exist(fullFileNameOnSearchPath, 'file')
% Still didn't find it. Alert user.
errorMessage = sprintf('Error: %s does not exist in the search path folders.', fullFileName);
uiwait(warndlg(errorMessage));
return;
end
end
rgbImage = imread(fullFileName);
[rows, columns, numberOfColorChannels] = size(rgbImage);
% Display the RGB image full size.
subplot(2, 2, 1);
imshow(rgbImage, []);
axis('on', 'image');
caption = sprintf('Original Image : "%s"', baseFileName);
title(caption, 'FontSize', fontSize, 'Interpreter', 'None');
drawnow;
hp = impixelinfo(); % Set up status line to see values when you mouse over the image.
% Set up figure properties:
% Enlarge figure to full screen.
hFig1 = gcf;
hFig1.Units = 'Normalized';
hFig1.WindowState = 'maximized';
% 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.
hFig1.Name = 'Demo by Image Analyst';
% Threshold the image to find the leaf.
[mask,maskedRGBImage] = createMask(rgbImage)
% Take the biggest blob
% mask = bwareafilt(mask);
% Display the binary image.
subplot(2, 2, 2);
imshow(mask, []);
axis('on', 'image');
caption = sprintf(' Mask Image');
title(caption, 'FontSize', fontSize, 'Interpreter', 'None');
drawnow;
hp = impixelinfo(); % Set up status line to see values when you mouse over the image.
% Get the area 2 different ways.
area1 = bwarea(mask) % Weights according to the shape of the local outline.
area2 = sum(mask(:)) % This is a simple pixel count.
% Get the area (pixel count) and Feret diameters.
props = regionprops(mask, 'Area')
allAreas = [props.Area]
caption = sprintf('Mask Image. %d blobs. Total Area = %d pixels.', numel(allAreas), sum(allAreas));
title(caption, 'FontSize', fontSize, 'Interpreter', 'None');
% Plot the borders of all the blobs in the overlay above the original grayscale image
% using the coordinates returned by bwboundaries().
% bwboundaries() returns a cell array, where each cell contains the row/column coordinates for an object in the image.
subplot(2, 2, 3);
imshow(rgbImage); % Optional : show the original image again. Or you can leave the binary image showing if you want.
% Here is where we actually get the boundaries for each blob.
boundaries = bwboundaries(mask);
% boundaries is a cell array - one cell for each blob.
% In each cell is an N-by-2 list of coordinates in a (row, column) format. Note: NOT (x,y).
% Column 1 is rows, or y. Column 2 is columns, or x.
numberOfBoundaries = size(boundaries, 1); % Count the boundaries so we can use it in our for loop
% Here is where we actually plot the boundaries of each blob in the overlay.
hold on; % Don't let boundaries blow away the displayed image.
for k = 1 : numberOfBoundaries
thisBoundary = boundaries{k}; % Get boundary for this specific blob.
x = thisBoundary(:,2); % Column 2 is the columns, which is x.
y = thisBoundary(:,1); % Column 1 is the rows, which is y.
plot(x, y, 'r-', 'LineWidth', 2); % Plot boundary in red.
end
hold off;
caption = sprintf('%d Outlines, from bwboundaries()', numberOfBoundaries);
fontSize = 15;
title(caption, 'FontSize', fontSize);
axis('on', 'image'); % Make sure image is not artificially stretched because of screen's aspect ratio.
%===============================================================================================
function [BW,maskedRGBImage] = createMask(RGB)
%createMask Threshold RGB image using auto-generated code from colorThresholder app.
% [BW,MASKEDRGBIMAGE] = createMask(RGB) thresholds image RGB using
% auto-generated code from the colorThresholder app. The colorspace and
% range for each channel of the colorspace were set within the app. The
% segmentation mask is returned in BW, and a composite of the mask and
% original RGB images is returned in maskedRGBImage.
% Auto-generated by colorThresholder app on 15-Jun-2023
%------------------------------------------------------
% Convert RGB image to chosen color space
I = rgb2hsv(RGB);
% Define thresholds for channel 1 based on histogram settings
channel1Min = 0.160;
channel1Max = 0.302;
% Define thresholds for channel 2 based on histogram settings
channel2Min = 0.303;
channel2Max = 1.000;
% Define thresholds for channel 3 based on histogram settings
channel3Min = 0.257;
channel3Max = 0.986;
% Create mask based on chosen histogram thresholds
sliderBW = (I(:,:,1) >= channel1Min ) & (I(:,:,1) <= channel1Max) & ...
(I(:,:,2) >= channel2Min ) & (I(:,:,2) <= channel2Max) & ...
(I(:,:,3) >= channel3Min ) & (I(:,:,3) <= channel3Max);
BW = sliderBW;
% Initialize output masked image based on input image.
maskedRGBImage = RGB;
% Set background pixels where BW is false to zero.
maskedRGBImage(repmat(~BW,[1 1 3])) = 0;
end
Dynamic
2023년 6월 16일
Hi @Image Analyst, thanks for your code. Actually, I am working to solve another complex problem using DL. That is why my system is occupied. I just want the output I have uploaded as expected output. Just edges.
Image Analyst
2023년 6월 16일
Yes, but you haven't said WHY and that is very important. The perimeter image is not the last, final step in your analysis. You're going to do something with that image right? Not just look at it and say, "Cool, that's fun!"
Anyway, you can simply call bwperim on the mask. I added the line of code to do that at the end of the script. Run it when your DL model is done training. (You know you can start two instances of MATLAB at one time, right? So you can work in one instance while the deep learning training is going on in the other instance.)
% Demo to find area and Feret extents of a leaf.
% By Image Analyst.
clc; % Clear the command window.
close all; % Close all figures (except those of imtool.)
clearvars;
workspace; % Make sure the workspace panel is showing.
format long g;
format compact;
fontSize = 18;
fprintf('Beginning to run %s.m ...\n', mfilename);
%-----------------------------------------------------------------------------------------------------------------------------------
% Read in image.
folder = pwd;
baseFileName = 'dynamic.png';
fullFileName = fullfile(folder, baseFileName);
% Check if file exists.
if ~exist(fullFileName, 'file')
% The file doesn't exist -- didn't find it there in that folder.
% Check the entire search path (other folders) for the file by stripping off the folder.
fullFileNameOnSearchPath = baseFileName; % No path this time.
if ~exist(fullFileNameOnSearchPath, 'file')
% Still didn't find it. Alert user.
errorMessage = sprintf('Error: %s does not exist in the search path folders.', fullFileName);
uiwait(warndlg(errorMessage));
return;
end
end
rgbImage = imread(fullFileName);
[rows, columns, numberOfColorChannels] = size(rgbImage);
% Display the RGB image full size.
subplot(2, 2, 1);
imshow(rgbImage, []);
axis('on', 'image');
caption = sprintf('Original Image : "%s"', baseFileName);
title(caption, 'FontSize', fontSize, 'Interpreter', 'None');
drawnow;
hp = impixelinfo(); % Set up status line to see values when you mouse over the image.
% Set up figure properties:
% Enlarge figure to full screen.
hFig1 = gcf;
hFig1.Units = 'Normalized';
hFig1.WindowState = 'maximized';
% 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.
hFig1.Name = 'Demo by Image Analyst';
hFig1.NumberTitle = "off"
% Threshold the image to find the leaf.
[mask,maskedRGBImage] = createMask(rgbImage)
% Take the biggest blob
% mask = bwareafilt(mask);
% Display the binary image.
subplot(2, 2, 2);
imshow(mask, []);
axis('on', 'image');
caption = sprintf('Mask Image');
title(caption, 'FontSize', fontSize, 'Interpreter', 'None');
drawnow;
hp = impixelinfo(); % Set up status line to see values when you mouse over the image.
% Get the area 2 different ways.
area1 = bwarea(mask) % Weights according to the shape of the local outline.
area2 = sum(mask(:)) % This is a simple pixel count.
% Get the area (pixel count) and Feret diameters.
props = regionprops(mask, 'Area')
allAreas = [props.Area]
caption = sprintf('Mask Image. %d blobs. Total Area = %d pixels.', numel(allAreas), sum(allAreas));
title(caption, 'FontSize', fontSize, 'Interpreter', 'None');
% Plot the borders of all the blobs in the overlay above the original grayscale image
% using the coordinates returned by bwboundaries().
% bwboundaries() returns a cell array, where each cell contains the row/column coordinates for an object in the image.
subplot(2, 2, 3);
imshow(rgbImage); % Optional : show the original image again. Or you can leave the binary image showing if you want.
% Here is where we actually get the boundaries for each blob.
boundaries = bwboundaries(mask);
% boundaries is a cell array - one cell for each blob.
% In each cell is an N-by-2 list of coordinates in a (row, column) format. Note: NOT (x,y).
% Column 1 is rows, or y. Column 2 is columns, or x.
numberOfBoundaries = size(boundaries, 1); % Count the boundaries so we can use it in our for loop
% Here is where we actually plot the boundaries of each blob in the overlay.
hold on; % Don't let boundaries blow away the displayed image.
for k = 1 : numberOfBoundaries
thisBoundary = boundaries{k}; % Get boundary for this specific blob.
x = thisBoundary(:,2); % Column 2 is the columns, which is x.
y = thisBoundary(:,1); % Column 1 is the rows, which is y.
plot(x, y, 'r-', 'LineWidth', 2); % Plot boundary in red.
end
hold off;
caption = sprintf('%d Outlines, from bwboundaries()', numberOfBoundaries);
fontSize = 15;
title(caption, 'FontSize', fontSize);
axis('on', 'image'); % Make sure image is not artificially stretched because of screen's aspect ratio.
% Get the perimeter as an image instead of in (x,y) coordinates as above.
perimImage = bwperim(mask);
subplot(2, 2, 4);
imshow(perimImage, []);
axis('on', 'image');
caption = sprintf('Perimeter Image');
title(caption, 'FontSize', fontSize, 'Interpreter', 'None');
%===============================================================================================
function [BW,maskedRGBImage] = createMask(RGB)
%createMask Threshold RGB image using auto-generated code from colorThresholder app.
% [BW,MASKEDRGBIMAGE] = createMask(RGB) thresholds image RGB using
% auto-generated code from the colorThresholder app. The colorspace and
% range for each channel of the colorspace were set within the app. The
% segmentation mask is returned in BW, and a composite of the mask and
% original RGB images is returned in maskedRGBImage.
% Auto-generated by colorThresholder app on 15-Jun-2023
%------------------------------------------------------
% Convert RGB image to chosen color space
I = rgb2hsv(RGB);
% Define thresholds for channel 1 based on histogram settings
channel1Min = 0.160;
channel1Max = 0.302;
% Define thresholds for channel 2 based on histogram settings
channel2Min = 0.303;
channel2Max = 1.000;
% Define thresholds for channel 3 based on histogram settings
channel3Min = 0.257;
channel3Max = 0.986;
% Create mask based on chosen histogram thresholds
sliderBW = (I(:,:,1) >= channel1Min ) & (I(:,:,1) <= channel1Max) & ...
(I(:,:,2) >= channel2Min ) & (I(:,:,2) <= channel2Max) & ...
(I(:,:,3) >= channel3Min ) & (I(:,:,3) <= channel3Max);
BW = sliderBW;
% Initialize output masked image based on input image.
maskedRGBImage = RGB;
% Set background pixels where BW is false to zero.
maskedRGBImage(repmat(~BW,[1 1 3])) = 0;
end
Dynamic
2023년 6월 16일
Hello @Image Analyst, Thanks for your support. Your generated result and using canny edge detection provide similar results but did you see if some portion of two leaves are overlapping then it will provide one edge shape? That I am not expecting. I just want the image I have shared as the expected output.
Image Analyst
2023년 6월 16일
It depends on how you define green. Did you play around with the sliders in the Color Thresholder? You might also separate blobs with watershed.
Again, WHY is it necessary to have the perimeters and have separations? I'll probably quit helping unless you help me help you by answering my questions. (I don't like having my questions ignored especially when it's to help you.) And don't just say (like so many people do) "I need it because I need it" or something to that effect.
Dynamic
2023년 6월 16일
Hello @Image Analyst, I appreciate your insightful comments. I apologize for neglecting to mention the purpose behind my previous inquiry. This request stems from an assignment for my coursework, where we are required to implement a preprocessing technique. This technique will be applied to a total of 500 images we have on hand. Additionally, a senior student in our laboratory is currently engaged in developing a deep learning model to accurately identify leaf shapes and count them.
Image Analyst
2023년 6월 16일
Good luck with your assignment. Here is an interface that might help with processing hundreds of images:
To identify the leaf shape you might need to eliminate the stem. You could use imopen() but that will change the shape of the perimeter slightly so you'd have to cleverly craft the algorithm so that only the stem is removed and the leaf edges are not changed.
If this Answer solves your original question, then could you please click the "Accept this answer" link to award the answerer with "reputation points" for their efforts in helping you? They'd appreciate it. Thanks in advance. 🙂 Note: you can only accept one answer (so pick the best one) but you can click the "Vote" icon for as many Answers as you want. Voting for an answer will also award reputation points.
Dynamic
2023년 6월 17일
Hello @Image Analyst, thanks for your suggestion. For you, it may be trivial work. Please if you provide me a fully automated code for the same I will be highly thankful. Thanks advanced
Image Analyst
2023년 6월 17일
@Dynamic I can't and won't. I don't want to be responsible for you getting expelled from the university for cheating and unethically turning in someone else's code as your own. You might want to take that risk but I don't want to enable it. Plus you don't learn anything if I just completely do the assignment for you and give you 100% automated, finished, turnkey code to do it all. If you just want that, then hire a consultant. You won't learn anything but they will give you "fully automated code".
I've given you a substantial amount of code already, plus a GUI for batch processing a bunch of files. I think that should be enough for you to continue on with it. If you want a non-GUI, script for batch processing, see the FAQ: https://matlab.fandom.com/wiki/FAQ#How_can_I_process_a_sequence_of_files?
참고 항목
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!오류 발생
페이지가 변경되었기 때문에 동작을 완료할 수 없습니다. 업데이트된 상태를 보려면 페이지를 다시 불러오십시오.
웹사이트 선택
번역된 콘텐츠를 보고 지역별 이벤트와 혜택을 살펴보려면 웹사이트를 선택하십시오. 현재 계신 지역에 따라 다음 웹사이트를 권장합니다:
또한 다음 목록에서 웹사이트를 선택하실 수도 있습니다.
사이트 성능 최적화 방법
최고의 사이트 성능을 위해 중국 사이트(중국어 또는 영어)를 선택하십시오. 현재 계신 지역에서는 다른 국가의 MathWorks 사이트 방문이 최적화되지 않았습니다.
미주
- América Latina (Español)
- Canada (English)
- United States (English)
유럽
- 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)
아시아 태평양
- Australia (English)
- India (English)
- New Zealand (English)
- 中国
- 日本Japanese (日本語)
- 한국Korean (한국어)