Variance and Mean of Image - matlab

I am calculating mean and variance of my original and stego image to compare them
I am using grayscale BMP image for comaprison
image=imread("image name")
M = mean(image(:))
V = var((image(:)))
Is this is correct way fo calculating mean/var in MATLAB? My Variance is getting more than mean..
Any help appreciated..

These are indeed the correct way to calculate the mean and variance over all the pixels of your image.
It is not impossible that your variance is larger than the mean as both are defined in the following way:
mean = sum(x)/length(x)
variance = sum((x - mean(x)).^2)/(length(x) - 1);
For example, if you generate noise from a standard normal distribution with randn(N,1), you will get N samples, and if you calculate the mean and variance, you will get approximately 0 and 1. So there as well, your variance may well be larger than the mean.
Both have a totally different meaning: the mean gives you an idea where your pixels are (i.e. are they white, black, 50% gray, ...). The mean will give you an idea of what pixel color to choose to summarize the color of the complete image. The variance gives you an idea how the pixel values are spread: e.g. if your mean pixel value is 50% gray, are most of the other pixels also 50% gray (small variance) or do you have 50 black pixels and 50 white pixels (large variance)? So you could also view it as a way to get an idea how well the mean summarizes the image (i.e. with zero variance, most of the information is captured by the mean).
edit: For the RMS value (Root Mean Square) of a signal, just do what the definition says. In most cases you want to remove the DC component (i.e. the mean) before calculating the RMS value.
edit 2: What I forgot to mention was: it also makes little sense to compare the numerical value of the variance with the mean from a physical point of view. The mean has the same dimension as your data (in case of pixels, think of intensity), while the variance has the dimension of your data squared (so intensity^2). The standard deviation (std in MATLAB), which is the square root of the variance on the other hand has the same dimension as the data, so there you could make some comparisons (it is another question whether you should do such comparison).

If you are workign with RGB image (H x W x 3), you have to calculate mean and variance separately for each channel. In this case the mean pixel will also be 3-values vector.
for ch = 1:3
M(ch) = mean(reshape(img(:,:,ch),[],1));
V(ch) = var(reshape(img(:,:,ch),[],1));
end
MATLAB has function image. Avoid using it as a variable.

Related

What is the effect of mean and variance in Gaussian noise?

I = imread('us-currency.png');
mean = 0.5;
variance = 0.5;
J = imnoise(I,'gaussian', mean, variance);
imshow(J);
What are the effects of mean and variance on that image?
Does mean increases the brightness?
Does variance increases the amount of noise?
Input
Output
The mean and variance set which distribution the random values will taken from.
Once you add those numbers to an image you change the image properties as well.
If the image mean value is imageMeanVal, assuming the image is large, then after the addition of the random noise its mean value will be `imageMeanVal + noiseMeanVal' since the image and the noise are independent.
If you define the brightness of an image as its mean value then you're right, the mean value changes (Increase or decrease) the image brightness.
The same logic holds for the Variance / Standard Deviation.
Yet it is hard to say what's Variance of an image is.
Sometimes one could say it is the power of data in the image and the variance of the noise is the power of noise.
Hence if you increase the power of the added noise, if one looks on the power ration of the image to the noise, you decrease it and makes the data in the image harder to notice.
This is basically the SNR of the noised image.

How to make "well" a ridge-shape from a given 2d line? (gaussian, matlab)

My goal is to make a ridge(mountain)-like shape from the given line. For that purpose, I applied the gaussian filter to the given line. In this example below, one line is vertical and one has some slope. (here, background values are 0, line pixel values are 1.)
Given line:
Ridge shape:
When I applied gaussian filter, the peak heights are different. I guess this results from the rasterization problem. The image matrix itself is discrete integer space. The gaussian filter is actually not exactly circular (s by s matrix). Two lines also suffer from rasterization.
How can I get two same-peak-height nice-looking ridges(mountains)?
Is there more appropriate way to apply the filter?
Should I make a larger canvas(image matrix) and then reduce the canvas by interpolation? Is it a good way?
Moreover, I appreciate if you can suggest a way to make ridges with a certain peak height. When using gaussian filter, what we can do is deciding the size and sigma of the filter. Based on those parameters, the peak height varies.
For information, image matrix size is 250x250 here.
You can give a try to distance transform. Your image is a binary image (having only two type of values, 0 and 1). Therefore, you can generate similar effects with distance transform.
%Create an image similar to yours
img=false(250,250);
img(sub2ind(size(img),180:220,linspace(20,100,41)))=1;
img(1:200,150)=1;
%Distance transform
distImg=bwdist(img);
distImg(distImg>5)=0; %5 is set manually to achieve similar results to yours
distImg=5-distImg; %Get high values for the pixels inside the tube as shown
%in your figure
distImg(distImg==5)=0; %Making background pixels zero
%Plotting
surf(1:size(img,2),1:size(img,1),double(distImg));
To get images with certain peak height, you can change the threshold of 5 to a different value. If you set it to 10, you can get peaks with height equal to the next largest value present in the distance transform matrix. In case of 5 and 10, I found it to be around 3.5 and 8.
Again, if you want to be exact 5 and 10, then you may multiply the distance transform matrix with the normalization factor as follows.
normalizationFactor=(newValue-minValue)/(maxValue-minValue) %self-explanatory
Only disadvantage I see is, I don't get a smooth graph as you have. I tried with Gaussian filter too, but did not get a smooth graph.
My result:

Decomposing an image into two frequency components using DCT?

I am a beginner in digital image processing field, recently I am working on a project where I have to decompose an image into two frequency components namely (low and high) using DCT. I searched a lot on web and I found that MATLAB has a built-in function for Discrete Cosine Transform which is used like this:
dct_img = dct2(img);
where img is input image and dct_img is resultant DCT of img.
Question
My question is, "How can I decompose the dct_img into two frequency components namely low and high frequency components".
As you've mentioned, dct2 and idct2 will do most of the job for you. The question that remains is then: What is high frequency and what is low frequency content? The coefficients after the 2 dimensional transform will actually represent two frequencies each (one in x- and one in y-direction). The following figure shows the bases for each coefficient in an 8x8 discrete cosine transform:
Therefore, that question of low vs. high can be answered in different ways. A common way, which is also used in the JPEG encoding, proceeds diagonally from zero-frequency downto the max as shown above. As we can see in the following example that is mostly motivated because natural images are largely located in the "top left" corner of "low" frequencies. It is certainly worth looking at the result of dct2 and play around with the actual choice of your regions for high and low.
In the following I'm dividing the spectrum diagonally and also plotting the DCT coefficients - in logarithmic scale because otherwise we would just see one big peak around (1,1). In the example I'm cutting far above half of the coefficients (adjustable with cutoff) we can see that the high-frequency part ("HF") still contains some relevant image information. If you set cutoff to 0 or below only noise of small amplitude will be left.
%// Load an image
Orig = double(imread('rice.png'));
%// Transform
Orig_T = dct2(Orig);
%// Split between high- and low-frequency in the spectrum (*)
cutoff = round(0.5 * 256);
High_T = fliplr(tril(fliplr(Orig_T), cutoff));
Low_T = Orig_T - High_T;
%// Transform back
High = idct2(High_T);
Low = idct2(Low_T);
%// Plot results
figure, colormap gray
subplot(3,2,1), imagesc(Orig), title('Original'), axis square, colorbar
subplot(3,2,2), imagesc(log(abs(Orig_T))), title('log(DCT(Original))'), axis square, colorbar
subplot(3,2,3), imagesc(log(abs(Low_T))), title('log(DCT(LF))'), axis square, colorbar
subplot(3,2,4), imagesc(log(abs(High_T))), title('log(DCT(HF))'), axis square, colorbar
subplot(3,2,5), imagesc(Low), title('LF'), axis square, colorbar
subplot(3,2,6), imagesc(High), title('HF'), axis square, colorbar
(*) Note on tril: The lower triangle-function operates with respect to the mathematical diagonal from top-left to bottom-right, since I want the other diagonal I'm flipping left-right before and afterwards.
Also note that this kind of operations are not usually applied to entire images, but rather to blocks of e.g. 8x8. Have a look at blockproc and this article.
An easy example:
I2 = dct_img;
I2(8:end,8:end) = 0;
I3 = idct2(I2);
imagesc(I3)
I3 can be seen as the image after low pass filter (the low frequency components), then idct2(dct_img - I2) can be viewed as high frequency.

Garment Cropping from mannequin

I have two images – mannequin with and without garment.
Please refer sample images below. Ignore the jewels, footwear on the mannequin, imagine the second mannequin has only dress.
I want to extract only the garment from the two images for further processing.
The complexity is that there is slight displacement in the position of camera when taking the two pictures. Due to this simple subtraction to generate the garment mask will not work.
Can anyone tell me how to handle it?
I think I need to do registration between the two images so that I can extract only the garment from the image?
Any references to blogs, articles and codes is highly appreciated.
--
Thanks
Idea
This is an idea of how you could do it, I haven't tested it but my gut tells me it might work. I'm assuming that there will be slight differences in the pose of the manequin as well as the camera attitude.
Let the original image be A, and the clothed image be B.
Take the difference D = |A - B|, apply a median filter that is proportional to the largest deviation you expect from pose and camera attitude error: Dmedian = Median(D, kernelsize).
Quantize Dmedian into a binary mask Dmask = Q(Dmedian, threshold) using appropriate threshold values to obtain an approximate mask for the garment (this will be smaller than the garment itself due to the median filter). Reject any shapes in Dmedian that have too small area by setting their pixels to 0.
Expand the shape(s) in Dmask proportionally to the size of the median kernel into Emask=expand(Dmask, k*kernelsize). Then construct the difference in the masks Fmask=|Dmask - Emask| which now contains areas of pixels where the garment edge is expected to be. For every pixel in Fmask which is in this area, find the correlation Cxy between A and B using a small neighbourhood, store the correlations into an image C=1.0 - Corr(A,B, Fmask, n).
Your final garment mask will be M=C+Dmask.
Explanation
Since your image has nice and continuous swatches of colour, the difference between the two similar images will be thin lines and small gradients where the pose and camera attitude is different. When taking a median filter of the difference image over a sufficiently large kernel, these lines will be removed because they are in a minority of the pixels.
The garment on the other hand will (hopefully) have a significant difference from the colors in the unclothed version. And will generate a bigger difference. Thresholding the difference after the median filter should give you a rough mask of the garment that is undersized dues to some of the pixels on the edge being rejected due to their median values being too low. You could stop here if the approximation is good enough for you.
By expanding the mask we obtained above we get a probable region for the "true" edge. The above process has served to narrow our search region for the true edge considerably and we can apply a more costly correlation search between the images along this edge to find where the garment is. High correlation means no carment and low correlation means garment.
We use the inverted correlation as an alpha value together with the initially smaller mask to obtain a alpha valued mask of the garment that can be used for extracting it.
Clarification
Expand: What I mean by "expanding the mask" is to find the contour of the mask region and outsetting/growing/enlarging it to make it larger.
Corr(A,B,Fmask,n): Is just an arbitrarily chosen correlation function that gives correlation between pixels in A and B that are selected by the mask Fmask using a region of size n. The function returns 1.0 for perfect match and 0.0 for anti-match for each pixel tested. A good function is this pseudocode:
foreach px_pos in Fmask where Fmask[px_pos] == 1
Ap = subregion(A, px_pos, size) - mean(mean(A));
Bp = subregion(B, px_pos, size) - mean(mean(B))
Cxy = sum(sum(Ap .* Bp))*sum(sum(Ap .* Bp)) / (sum(sum(Ap.*Ap))*sum(sum(Bp.*Bp)))
C[px_pos] = 1.0 - Cxy;
end
where subregion selects a region of size size around the pixel with position px_pos.
You can see that if Ap == Bp then Cxy=1

Plot of mean square error [EDIT]

If this be the formula for MSE for RGB images A,B of same size 256*200, then how to obtain a line plot for every pixel with x axis representing pixels and y axis representing the MSE values
MSE = reshape(mean(mean((double(A) - double(B)).^2,2),1),[1,3])
There are only two images A ,B. The plot should illustrate change between each pixel of A and B which is meant by MSE.
If you want to display the changes "between each pixel" then what you're showing is not mean squared errors any more -- there's no averaging going on. (Unless you intend to average across the three colour planes, but I don't recommend that: changes in R,G,B are not equally salient to the human visual system. If you really must do this, you might want to weight them, say, 2:4:1 for something a bit more representative, but this is still ad hoc and not likely to give a very accurate idea of what differences will look biggest.)
Of course it's perfectly reasonable to want to see the per-pixel errors, but I wouldn't recommend using a line plot to display them; it's likely to be confusing rather than informative. Rather, display them as an image:
errs = (double(A)-double(B)).^2;
image(errs / max(errs(:)));
axis image;
which you can then compare by eye with A and B to see what image regions/features/... correspond to worse errors. The brightness and colour of each pixel indicate the amount of error and how it's distributed across the R, G, and B planes.
On the other hand, perhaps what you actually need is mean squared error over individual rows, or columns, of the image. In that case, after creating errs as above, use mean to compute the row or column means; that will give you a 256-by-1-by-3 image or a 1-by-200-by-3 image; now I would suggest plotting R,G,B curves separately unless you (probably foolishly in my opinion, as mentioned above) insist on averaging the planes.
row_errs = mean(errs,2); % this is now of size [n,1,3]
now row_errs(:,:,1) is a vector of MS-across-rows red errors, row_errs(:,:,2) is a vector of MS-across-rows green errors, etc. You can feed these to plot.