how this command works"meanGL = mean(black​MaskedImag​e(binaryIm​age));". My input image is a HSV image. How it calculates the mean.

I have HSV image. from that image some area is masked. the mean brightness of that area is supposed to be calculated.
I need to know how this command works"meanGL = mean(blackMaskedImage(binaryImage));". My input image is a HSV image. How it calculates the mean. As HSV has three different values of every pixel. Then mean which is sum of pixel value divided by total pixel no. will not work.

Risposte (2)

Let's just take it one step at a time. See if this helps explain it
grayScaleImage = magic(6)
grayScaleImage = 6×6
35 1 6 26 19 24 3 32 7 21 23 25 31 9 2 22 27 20 8 28 33 17 10 15 30 5 34 12 14 16 4 36 29 13 18 11
binaryImage = grayScaleImage > 30
binaryImage = 6×6 logical array
1 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0
pixelsInMask = grayScaleImage(binaryImage)
pixelsInMask = 6×1
35 31 32 36 33 34
% Get the mean of the pixels in the mask
meanWithinMask = mean(pixelsInMask)
meanWithinMask = 33.5000
You can't do it on a 3-channel HSV image. You can only do it on one channel at a time

9 Commenti

Agree. And totally understood your explanation. But I m getting results. It calculates and returns value around 0.774. I am not understanding what and how exactly it is calculating. If it is calculating any one channel than which one Hue, Saturation or Value??
As explained in my answer, if blackMaskedImage is a 3-channel HSV image, and if binaryImage is a single-channel logical mask, then the result is the arithmetic mean of the first channel only.
In this case, it would be the arithmetic mean of normalized hue angles, which is not generally useful if you're trying to find an average color..
This is the program
a = imread('untitled.png');
hsv = rgb2hsv(a);
subplot(2, 3, 1);
imshow(hsv, []);
title('Original Grayscale Image', 'FontSize', fontSize);
set(gcf, 'Position', get(0,'Screensize')); % Maximize figure.
message = sprintf('Left click and hold to begin drawing.\nSimply lift the mouse button to finish');
uiwait(msgbox(message));
roi = drawcircle();
% Create a binary image ("mask") from the ROI object.
binaryImage = roi.createMask();
% Display the mask.
subplot(2, 3, 2);
imshow(binaryImage);
title('Binary mask of the region', 'FontSize', fontSize);
% Calculate the area, in pixels, that they drew.
numberOfPixels1 = sum(binaryImage(:))
% Another way to calculate it that takes fractional pixels into account.
numberOfPixels2 = bwarea(binaryImage)
% Get coordinates of the boundary of the freehand drawn region.
structBoundaries = bwboundaries(binaryImage);
xy=structBoundaries{1}; % Get n by 2 array of x,y coordinates.
x = xy(:, 2); % Columns.
y = xy(:, 1); % Rows.
subplot(2, 3, 1); % Plot over original image.
hold on; % Don't blow away the image.
plot(x, y, 'LineWidth', 2);
% Burn line into image by setting it to 255 wherever the mask is true.
burnedImage = hsv;
burnedImage(binaryImage) = 255;
% Display the image with the mask "burned in."
subplot(2, 3, 3);
imshow(burnedImage);
caption = sprintf('New image with\nmask burned into image');
title(caption, 'FontSize', fontSize);
% Mask the image and display it.
% Will keep only the part of the image that's inside the mask, zero outside mask.
blackMaskedImage = hsv;
blackMaskedImage(~binaryImage) = 0;
subplot(2, 3, 4);
imshow(blackMaskedImage);
title('Masked Outside Region', 'FontSize', fontSize);
% Calculate the mean
meanGL = mean(blackMaskedImage(binaryImage));
% Report results.
message = sprintf('Mean value within drawn area = %.3f\nNumber of pixels = %d\nArea in pixels = %.2f', ...
meanGL, numberOfPixels1, numberOfPixels2);
msgbox(message);
% Now do the same but blacken inside the region.
insideMasked = hsv;
insideMasked(binaryImage) = 0;
subplot(2, 3, 5);
imshow(insideMasked);
title('Masked Inside Region', 'FontSize', fontSize);
% Now crop the image.
topLine = min(x);
bottomLine = max(x);
leftColumn = min(y);
rightColumn = max(y);
width = bottomLine - topLine + 1;
height = rightColumn - leftColumn + 1;
croppedImage = imcrop(blackMaskedImage, [topLine, leftColumn, width, height]);
"Airthmetic mean of normalized hue" means Hue is normalized to [0-1], than its mean is calculated.
But acutally I need to calculate is average brightness.
I don't know why you're trying to do that by converting to HSV. Are you assuming that the appearance of the image means that it's an HSV image?
That's a pseudocolor image. Superficially, it's RGB, but it represents a 2D map of values -- a grayscale image.
The problem is simply that the map is unknown and the scaling and units are unknown. We could answer the question "how do I find the average brightness of an RGB image", but If this is a pseudocolor image representing some quantity like temperature, then there's not enough information to answer the question "how do I find the average (e.g.) temperature".
It might help to know more about what this image means or how it was created.
If you just want the average brightness, use the V image, or convert your original RGB image to grayscale and get the mean of the grayscale image. Don't overthink it. If you need to convert to HSV for segmentation purposes (like find all read pixels), fine, then you can use the V channel since you already have it. If not doing segmentation and just want the overall brightness, use the gray scale image.
What is V image?
According to me mean of grayscale image gives mean pixel intensity.
And pixel intensity and brightness both are seperate parameters.
I don't want to do any segmentation.
"My aim is to extract as many different features possible from the image." My images are screenshot of thermal images saved in .png format. When I take screenshot I know it looses information about temperature.
Thermal Images I study using its camera's software, it gives average temperature but no other information.
My purpose is to extract as much information as possible form the .png format of image.
Intensity (as in HSI) is the dim3 mean of an RGB image (though there are other interpretations of the word). Value (as in HSV) is the dim3 maximum of an RGB image.
If you can get so much as two points of known temperature and a colorbar, it's possible to approximate the underlying data.
Regarding using any particular brightness metric as a means to analyze a pseduocolor image, consider the following:
% generate a simple 2D image
n = 100;
A = repmat(linspace(0,1,n),[n 1]).';
% let's "convert" this to indexed so that we can colormap it
Aind = gray2ind(A,n);
% colormap it with different maps
B = im2uint8(ind2rgb(Aind,gray(n)));
C = im2uint8(ind2rgb(Aind,hsv(n)));
D = im2uint8(ind2rgb(Aind,parula(n)));
imshow([B C D],'border','tight')
% a mask
mask = logical(eye(n));
imshow(mask,'border','tight')
% this is the average value in the underlying data
meanA = mean(A(mask))
meanA = 0.5000
% a linear grayscale map _could_ give us a correct answer in a relative sense,
% i.e. we still know which pixels are hotter than others, but without the scaling information,
% we don't know what temperature they actually are.
Bv = max(B,[],3);
meanBv = mean(Bv(mask))
meanBv = 127.5000
% but if you're dealing with a rainbow map,
% you can't divine anything from V either way
Cv = max(C,[],3);
meanCv = mean(Cv(mask))
meanCv = 255
% even a map that appears to have monotonic brightness
% won't necessarily have monotonic V
Dv = max(D,[],3);
meanDv = mean(Dv(mask))
meanDv = 224.0400
imshow([Bv Cv Dv],'border','tight')
So even apparent spatial features (e.g. edges) in V might not actually exist in the underlying data.

Accedi per commentare.

What it means is probably not a good place to start. Let's back up, because we're probably not doing what we think we're doing anyway. Consider the following example of masking a multichannel image:
% a contrived MxNx3 image
% the channel values are in distinct ranges for clarity
inpict = magic(5) + permute([0 100 200],[1 3 2])
inpict =
inpict(:,:,1) = 17 24 1 8 15 23 5 7 14 16 4 6 13 20 22 10 12 19 21 3 11 18 25 2 9 inpict(:,:,2) = 117 124 101 108 115 123 105 107 114 116 104 106 113 120 122 110 112 119 121 103 111 118 125 102 109 inpict(:,:,3) = 217 224 201 208 215 223 205 207 214 216 204 206 213 220 222 210 212 219 221 203 211 218 225 202 209
% a MxNx1 logical mask
mask = logical(eye(5))
mask = 5×5 logical array
1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1
% select some pixels to average
% if we naively apply a single-channel mask to a multichannel image
% we only select the first channel, and nothing else
selectedpix = inpict(mask)
selectedpix = 5×1
17 5 13 21 9
% if we expand the mask to match the depth of the image, we get more
% but the results from all channels are in a single column and will get averaged together
numchans = size(inpict,3);
selectedpix = inpict(repmat(mask,[1 1 numchans]))
selectedpix = 15×1
17 5 13 21 9 117 105 113 121 109
% so reshape the output
selectedpix = reshape(selectedpix,[],3)
selectedpix = 5×3
17 117 217 5 105 205 13 113 213 21 121 221 9 109 209
% now you can get the average tuple
avgcolor = mean(selectedpix,1)
avgcolor = 1×3
13 113 213
So the depth of the image and mask determine what's actually being selected and averaged. You have a multichannel image, regardless of whether it's HSV or RGB or whatever. Chances are that your mask isn't multichannel, so you're not selecting what you think you're selecting.
That's the general idea, but now back to specifics. Your image is HSV. While what I showed would work for finding the arithmetic mean of the pages of an arbitrary 3D array, taking the arithmetic mean of an HSV image doesn't make sense, because it doesn't make sense to take the arithmetic mean of angles.
For example, say we have this image and mask:
rgbpict = imread('peppers.png');
mask = imread('redpepmask.png')>128;
% get the pixels selected by the mask
numchans = size(rgbpict,3);
selectedpix = rgbpict(repmat(mask,[1 1 numchans]));
selectedpix = reshape(selectedpix,[],3);
% now you can get the average tuple
avgRGB = cast(mean(selectedpix,1),class(rgbpict))
avgRGB = 1×3
184 34 39
% show it
imshow(permute(avgRGB,[1 3 2]),'border','tight')
% do the same thing to an HSV copy
hsvpict = rgb2hsv(rgbpict);
% get the pixels selected by the mask
numchans = size(hsvpict,3);
selectedpix = hsvpict(repmat(mask,[1 1 numchans]));
selectedpix = reshape(selectedpix,[],3);
% now you can get the average tuple
avgHSV = cast(mean(selectedpix,1),class(hsvpict))
avgHSV = 1×3
0.7044 0.8454 0.7212
avgRGB = im2uint8(hsv2rgb(avgHSV)) % convert to uint8-scale RGB for display
avgRGB = 1×3
64 28 184
% show it
imshow(permute(avgRGB,[1 3 2]),'border','tight')
So the average color we get from the arithmetic mean of HSV is wildly incorrect. Why is that? For an explanation, see this answer:

3 Commenti

Sir I understood the first half, but example made me confuse. anywaz I have not got the solution. I want to know if I m coverting my RGB into HSV. Then selecting a ROI and masking it out. for that selected area how can I calculate the brightness. Various literaturre says that in HSV, V is brightness. So, shall I take out V component of selected area and take average.
or the brightness that I am getting from command
meanGL = mean(black​MaskedImag​e(binaryIm​age))
is correct?
V is the "brightness" component in the HSV model, but as far as visible light images are concerned, V is one of the worst measures of perceived brightness that you can use.
Note the emphasis on visible light. If this is something like a thermal image, then the brightness is entirely an artifact of the applied colormap and doesn't tell you anything about the underlying data. Like I said in the other comment, it would help to know what the image means or if there is other information about its source.
That said, if you wanted to find the average V in a given region, you can simply work on that channel alone.
% the same MxNx3 image as before
% pretend this is our HSV image
hsv = magic(5) + permute([0 100 200],[1 3 2]);
% get only the value channel
V = hsv(:,:,3);
% apply the mask to V alone and get the average V
meanV = mean(V(mask))
... but bear in mind what you're actually looking at when you're dealing with V.
A = imread('https://www.mathworks.com/matlabcentral/answers/uploaded_files/1394519/Untitled.png');
% V is just the dim3 max of RGB
% if all you wanted were V, this is another way to get it
Av = max(A,[],3);
imshow(Av,'border','tight')
Note that all four circles are largely the same value. Is that expected?
You might try something like this:
A = imread('https://www.mathworks.com/matlabcentral/answers/uploaded_files/1394519/Untitled.png');
% a guess as to what the original colormap was
% these are the approximate breakpoints
% but there's no way to know what their spacing was
% so there's no way to know if linearity is preserved here
CT0 = [0 0 0; 1 0 1; 0 0 0.75; 0 1 1; 0 0.5 0; 1 1 0; 0.75 0 0; 1 1 1];
x0 = linspace(0,1,size(CT0,1)); % they may not have been uniformly-spaced
xf = linspace(0,1,256);
CTin = interp1(x0,CT0,xf,'linear');
% remove the colormap to get some relative measure of the underlying data
B = rgb2ind(A,CTin);
B = ind2gray(B,gray(size(CTin,1)));
imshow(B,'border','tight')
The little speckles are an artifact of the imperfect map estimation and what is likely some sort of interpolation or compression that's taken place. Those can be filtered out if desired.
% get rid of spurious peaks
B = amedfilt(B); % MIMT tool
At this point, you don't necessarily know what temperature anything is, or whether the mapping is linear (due to the map estimation), but you can be somewhat sure that it's at least monotonic. You should be able to say that the SE container is warmer than the other three. That's something you can't get from V or I or any weighted average of the RGB image channels.
The function amedfilt() is part of MIMT.

Accedi per commentare.

Categorie

Richiesto:

il 25 Mag 2023

Modificato:

DGM
il 27 Mag 2023

Community Treasure Hunt

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

Start Hunting!

Translated by