Measuring different parts of a region within a binary-masked image
4 visualizaciones (últimos 30 días)
Mostrar comentarios más antiguos
William
el 2 de Jul. de 2024
Comentada: William
el 3 de Jul. de 2024
Hello,
I am attempting to quantify the dimensions of a region within timelapse frames (here, measuring an area of sand in water) for several thousand images. I want to measure the relative width of the sand area of each image, including local maxima and minima as well as the sediment-water boundary length (see magenta bars/line in 'SurfaceTestRGBandBinaryMaskMeas.jpg').
I am using the Matlab Image Processing Toolbox and, using the Image Batch Processor, I have been able to use the Image Segmenter and imcrop functions to isolate the sand and water from frame artifacts (see cyan box in 'SurfaceTestRGBandBinaryMaskMeas.jpg') and convert the RGB image into a binary mask (see attached code), but after that, I'm at a loss for how to get the measurements I indicated above without measuring each frame by hand.
Additionally, due to lighting issues for some of the frames, the binary masking sometimes does not separate dark areas of sand from the water, which sometimes results in being unable to measure part of the sand boundary (see binary image in attached jpg).
Any help is much appreciated!
0 comentarios
Respuesta aceptada
Taylor
el 2 de Jul. de 2024
I used the Color Thresholder app to create a function that transforms the cropped image from the RGB to Lab colorspace and thesholds the second channel at "0" (max value doesn't really matter). Then I used the Image Region Analyzer app to create a function that fills holes in the BW image/logical mask and filters out smaller areas (<1000). Then I sum each row and report the maximum and minimum values of each sum and where they occur. Hope this helps!
img = imread("SurfaceTestRGB.jpg");
imshow(img)
imgCrop = imcrop(img, [364 67 2008 1675]);
imshow(imgCrop)
[bwCrop, imgCropMasked] = createMask(imgCrop);
imshow(imgCropMasked)
[bwCropFilt, properties] = filterRegions(bwCrop);
imshow(bwCropFilt)
rowSums = sum(bwCropFilt, 2);
[maxRowWidth, maxRowWidthIdx] = max(rowSums);
[minRowWidth, minRowWidthIdx] = min(rowSums);
disp("The maximum width is " + maxRowWidth + " and occurs at row " + maxRowWidthIdx)
disp("The minimum width is " + minRowWidth + " and occurs at row " + minRowWidthIdx)
areaSand = nnz(bwCropFilt) / numel(bwCropFilt);
disp("The area of sand in the image is " + areaSand)
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 02-Jul-2024
%------------------------------------------------------
% Convert RGB image to chosen color space
I = rgb2lab(RGB);
% Define thresholds for channel 1 based on histogram settings
channel1Min = 2.494;
channel1Max = 99.201;
% Define thresholds for channel 2 based on histogram settings
channel2Min = 0;
channel2Max = 30.353;
% Define thresholds for channel 3 based on histogram settings
channel3Min = -4.991;
channel3Max = 59.831;
% 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
function [BW_out,properties] = filterRegions(BW_in)
%filterRegions Filter BW image using auto-generated code from imageRegionAnalyzer app.
% Auto-generated by imageRegionAnalyzer app on 02-Jul-2024
%---------------------------------------------------------
BW_out = BW_in;
% Fill holes in regions.
BW_out = imfill(BW_out, 'holes');
% Filter image based on image properties.
BW_out = bwpropfilt(BW_out,'Area',[1000 + eps(1000), Inf]);
% Get properties.
properties = regionprops(BW_out, {'Area', 'Circularity', 'Eccentricity', 'EquivDiameter', 'EulerNumber', 'MajorAxisLength', 'MinorAxisLength', 'Orientation', 'Perimeter'});
end
Más respuestas (0)
Ver también
Categorías
Más información sobre Convert Image Type en Help Center y File Exchange.
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!