Hi all. I have written from some tutorials and help pages an image analysis tool which takes a picture and converts it to black and white 8 bit, then thresholds, then selects out groups of flow, then outlines and THEN calculates an area for the ebb that the flow has produced.
I am curious as to how to accurately get my program to outline and group the flow?
Below is the code. You can just replace the image and see what I am talking about. For a more complicated 2D picture representing flow, the outline is inaccurate. Attached is the picture for the code. Thanks
%This program takes the threshold of the picture and then takes the
%brighter is then converted into area
clc; % Clear command window.
clearvars; % Get rid of variables from prior run of this m-file.
fprintf('Loading Flowdemo.m...\n'); % Message sent to command window.
workspace; % Make sure the workspace panel with all the variables is showing.
imtool close all; % Close all imtool figures.
format long g; format compact; captionFontSize = 14; % Check that user has the Image Processing Toolbox installed.
hasIPT = license('test', 'image_toolbox'); if ~hasIPT % User does not have the toolbox installed.
message = sprintf('Please install image toolbox'); reply = questdlg(message, 'Toolbox missing', 'Yes', 'No', 'Yes'); if strcmpi(reply, 'No') % User said No, so exit.
return; end end FileName = 'IMG_4087-793289.JPG'; originalImage = imread(FileName); % Checks for grayscale images
[rows, columns, numberOfColorChannels] = size(originalImage); if numberOfColorChannels > 1 promptMessage = sprintf('Your image file has %d color channels.\nThis demo was designed for grayscale images.\nDo you want me to convert it to grayscale for you so you can continue?', numberOfColorChannels); button = questdlg(promptMessage, 'Continue', 'Convert and Continue', 'Cancel', 'Convert and Continue'); if strcmp(button, 'Cancel') fprintf(1, 'Finished running micellesDemo.m.\n'); return; end % Converts color --> gray
originalImage = rgb2gray(originalImage); end % Display the grayscale image of the original image in a full window
subplot(3, 3, 1); imshow(originalImage); set(gcf, 'units','normalized','outerposition',[0 0 1 1]); %Displays a histogram of the colors.
[pixelCount, grayLevels] = imhist(originalImage); subplot(3, 3, 2); bar(pixelCount); title('Histogram of original image', 'FontSize', captionFontSize); xlim([0 grayLevels(end)]); % Scale x axis manually.
grid on; %Establishing a Threshold. Black and white
thresholdValue = 100; binaryImage = originalImage > thresholdValue; % Bright objects will be chosen if you use >.
% Do a "hole fill" to get rid of any background pixels or "holes" inside the micelles.
binaryImage = imfill(binaryImage, 'holes'); % Show the threshold as a vertical red bar on the histogram.
hold on; maxYValue = ylim; line([thresholdValue, thresholdValue], maxYValue, 'Color', 'r'); % Place a text label on the bar chart showing the threshold.
annotationText = sprintf('Thresholded at %d gray levels', thresholdValue); % For text(), the x and y need to be of the data class "double" so let's cast both to double.
text(double(thresholdValue + 5), double(0.5 * maxYValue(2)), annotationText, 'FontSize', 10, 'Color', [0 .5 0]); text(double(thresholdValue - 70), double(0.94 * maxYValue(2)), 'Background', 'FontSize', 10, 'Color', [0 0 .5]); text(double(thresholdValue + 50), double(0.94 * maxYValue(2)), 'Foreground', 'FontSize', 10, 'Color', [0 0 .5]); % Display the binary image.
subplot(3, 3, 3); imshow(binaryImage); title('Image converted into Binary after thresholding', 'FontSize', captionFontSize); % Identifies the conglomerate of micells
labeledImage = bwlabel(binaryImage, 8); subplot(3, 3, 4); imshow(labeledImage, []); % Show the gray scale image.
title('Micelle groups', 'FontSize', captionFontSize); micellMeasurements = regionprops(labeledImage, originalImage, 'all'); numberOfmicell = size(micellMeasurements, 1); % bwboundaries() returns a cell array, where each cell contains the row/column coordinates for an object in the image.
% Plot the borders of all the micelles on the original grayscale image using the coordinates returned by bwboundaries.
subplot(3, 3, 6); imshow(originalImage); title('Outlines, from bwboundaries()', 'FontSize', captionFontSize); axis image; % Make sure image is not artificially stretched because of screen's aspect ratio.
hold on; boundaries = bwboundaries(binaryImage); numberOfBoundaries = size(boundaries, 1); for k = 1 : numberOfBoundaries thisBoundary = boundaries{k}; plot(thisBoundary(:,2), thisBoundary(:,1), 'g', 'LineWidth', 2); end hold off; textFontSize = 14; % Used to control size of "micelle number" labels put atop the image.
labelShiftX = -7; % Used to align the labels in the centers of the coins.
micelleECD = zeros(1, numberOfmicell); % Print header line in the command window.
fprintf(1,'micelle # Mean Intensity Area Perimeter Centroid Diameter\n'); % Loop over all micelles printing their measurements to the command window.
for k = 1 : numberOfmicell % Loop through all micelles.
% Find the mean of each micelle. (R2008a has a better way where you can pass the original image
% directly into regionprops. The way below works for all versions including earlier versions.)
thismicellesPixels = micellMeasurements(k).PixelIdxList; % Get list of pixels in current micelle.
meanGL = mean(originalImage(thismicellesPixels)); % Find mean intensity (in original image!)
meanGL2008a = micellMeasurements(k).MeanIntensity; % Mean again, but only for version >= R2008a
micelleArea = micellMeasurements(k).Area; % Get area.
micellePerimeter = micellMeasurements(k).Perimeter; % Get perimeter.
micelleCentroid = micellMeasurements(k).Centroid; % Get centroid one at a time
micelleECD(k) = sqrt(4 * micelleArea / pi); % Compute ECD - Equivalent Circular Diameter.
fprintf(1,'#%2d %17.1f %11.1f %8.1f %8.1f %8.1f % 8.1f\n', k, meanGL, micelleArea, micellePerimeter, micelleCentroid, micelleECD(k)); % Put the "micelle number" labels on the "boundaries" grayscale image.
text(micelleCentroid(1) + labelShiftX, micelleCentroid(2), num2str(k), 'FontSize', textFontSize, 'FontWeight', 'Bold'); end
Best Answer