d3.js using d3.scale.sqrt() - d3.js

What does the d3.scale.sqrt() scale do? As per the documentation it is similar to d3.scale.pow().exponent(.5), so the returned scale is equivalent to the sqrt function for numbers; for example:
sqrt(0.25) returns 0.5.
so when we apply a domain similar to this:
d3.scale.sqrt().domain([1, 100]).range([10, 39])
does it signify it takes the value between 1-100 and return the sqrt function which ranges between 10-39? Could anybody clarify and provide more details on how this scale works?

The way scales work in D3 is that they map input values (defined by .domain()) to output values (defined by .range()). So
d3.scale.sqrt().domain([1, 100]).range([10, 39])
maps values from 1 to 100 to the 10 to 39 range. That is, 1 corresponds to 10 and 100 to 39. This has nothing to do with the transformation the scale applies, which only affects the distribution of values within the range. For the sqrt function, the growth is sub-linear, which means that more of the input values will fall into the latter part of the output range.

Related

How many kind of feature for region-based segmentation

I have to use region-based to classify foreground (FG) and background (BG). I read many papers about that problem. However, almost papers that I read, they often using mean feature to compare the mean square error such as
(I(x)-mean(FG)).^2>(I(x)-mean(BG)).^2=>x belong to BG
Some authors add some condition that used statistical reigon (add sigma term). How about the other feature to discribe image region. Could you suggest to me some feature? Thank you so much
Try this function I created in Matlab called 'Quantisation', note this is for grey scale images. it automatically finds thresholds in the image and will classify all pixels under 1 of the categories, FG or BG:
function [quant2_A_min,quant2_A_max] = Quantization(fname)
% If there is less that one input argument 'B20.BMP' will be read in.
if nargin <1
fname='B20.BMP'
end
% define fname as the variable 'X'.
X=fname;
%splits the image into 2 levels by obtaining 2 threshold values.
thresh = multithresh(X,1);
%Contructs a vector of max values so that the max value in each
%quantization interval is assigned to the 2 levels of o/p image
valuesMax = [thresh max(X(:))];
[quant2_A_max, index] = imquantize(X,thresh,valuesMax);
%Contructs a vector of min values so that the min value in each
%quantization interval is assigned to the 2 levels of the o/p image
valuesMin = [min(X(:)) thresh];
%use the output argument index to assign the MIN values to the output image
%instead if called imquantize again.
quant2_A_min = valuesMin(index);
%Display both 2 level images side by side
imshowpair(quant2_A_min,quant2_A_max,'montage');...
title('Quantised Images (Min & Max)', 'FontSize',14,...
'fontweight','bold');
end

MatLab - Shifting an image using FFT

I want to shift an image (represented by a 2D matrix) using the multiplication of its fft by exp(-j*2*pi*x*F), where x is the displacement. I have:
input=peaks(200);
H=fftshift(fft2(fftshift(input)));
x=19;
H=H*exp(-1i*x*2*pi*F);
IF_image=fftshift(ifft2(fftshift(H)));
imshow(IF_image)
But I'm having troubles identifying/representing the F in H[F] since my input is a 2 dimensional array. How could I do this?
The desired output will be my original image shifted in the horizontal axis (by x units) in the same frame so it would start at x+1. As an example:
If input=
1 2 3 4 5
6 7 8 9 0
and x=2, I want:
4 5 1 2 3
9 0 6 7 8
You identified the property for translation / shifting in 1D. For 2D, it's slightly different but based on the same principle. To achieve the translation in 2D, this is the translation / shift property, which is defined as:
x0,y0 would be the shift you want to introduce. As such, positive value of x0 would shift your 2D signal to the right, while a negative value would shift to the left. Similarly, a positive value of y0 would shift your 2D image downwards, while a negative value would shift upwards.
Therefore, given your Fourier Transform in 2D, you would need to add an additional term to the exponent. In addition, you must normalize by N or the size of your 2D signal. This is assuming that your 2D signal has the same number of rows and columns. If this isn't the case, then you would have to take u*x0 and you would divide by the number of columns and v*y0 would be divided by the number of rows.
Now, the reason why you're confused about F in your above code is because you aren't sure how to define this in 2D. You must define a frequency value for every point in the 2D grid. Because of your fftshift call, we would define the x and y values between -100 and 99, as your 2D signal is of size 200 x 200 and this would centre our 2D signal to be in the middle. This is actually what fftshift is doing. Similarly, ifftshift undoes the centering done by fftshift. To define these points in 2D, I use meshgrid. Once you define these points, you would take each pair of (x,y) co-ordinates, then create the complex exponential as you see in the above property.
As such, your code would have to be modified in this fashion. Bear in mind that I got rid of redundant fftshift and ifftshift calls in your original code. You would call the fft, then do fftshift to centre the spectrum. I also changed your variable input to in, as input is a function in MATLAB, and we don't want to unintentionally shadow the function with a variable.
I've also defined the x shift to be -35, and the y shift to be -50. This will mean that the resultant signal will shift to the left by 35, and up by 50.
Therefore:
in=peaks(200); %// Define input signal
H=fftshift(fft2(in)); %// Compute 2D Fourier Transform
x0=-35; %// Define shifts
y0=-50;
%// Define shift in frequency domain
[xF,yF] = meshgrid(-100:99,-100:99);
%// Perform the shift
H=H.*exp(-1i*2*pi.*(xF*x0+yF*y0)/200);
%// Find the inverse Fourier Transform
IF_image=ifft2(ifftshift(H));
%// Show the images
figure;
subplot(1,2,1);
imshow(in);
subplot(1,2,2);
imshow(real(IF_image));
Take note that I displayed the real component of the resultant image. This is due to the fact that once you take the inverse Fourier Transform, there may be some numerical imprecision and the complex part of the signal is actually quite small. We can ignore this by just using the real component of the signal.
This is the image I get:
As you can see, the image did shift properly, as verified by the property seen above. If you want to specify different shifts, you just need to change x0 and y0 to suit your tastes. In your case, you would specify y0 = 0, then x0 can be whatever you wish as you want a horizontal translation.

Mutual information and joint entropy of two images - MATLAB

I have two black and white images and I need to calculate the mutual information.
Image 1 = X
Image 2 = Y
I know that the mutual information can be defined as:
MI = entropy(X) + entropy(Y) - JointEntropy(X,Y)
MATLAB already has built-in functions to calculate the entropy but not to calculate the joint entropy. I guess the true question is: How do I calculate the joint entropy of two images?
Here is an example of the images I'd like to find the joint entropy of:
X =
0 0 0 0 0 0
0 0 1 1 0 0
0 0 1 1 0 0
0 0 0 0 0 0
0 0 0 0 0 0
Y =
0 0 0 0 0 0
0 0 0.38 0.82 0.38 0.04
0 0 0.32 0.82 0.68 0.17
0 0 0.04 0.14 0.11 0
0 0 0 0 0 0
To calculate the joint entropy, you need to calculate the joint histogram between two images. The joint histogram is essentially the same as a normal 1D histogram but the first dimension logs intensities for the first image and the second dimension logs intensities for the second image. This is very similar to what is commonly referred to as a co-occurrence matrix. At location (i,j) in the joint histogram, it tells you how many intensity values we have encountered that have intensity i in the first image and intensity j in the second image.
What is important is that this logs how many times we have seen this pair of intensities at the same corresponding locations. For example, if we have a joint histogram count of (7,3) = 2, this means that when we were scanning both images, when we encountered the intensity of 7, at the same corresponding location in the second image, we encountered the intensity of 3 for a total of 2 times.
Constructing a joint histogram is very simple to do.
First, create a 256 x 256 matrix (assuming your image is unsigned 8-bit integer) and initialize them to all zeroes. Also, you need to make sure that both of your images are the same size (width and height).
Once you do that, take a look at the first pixel of each image, which we will denote as the top left corner. Specifically, take a look at the intensities for the first and second image at this location. The intensity of the first image will serve as the row while the intensity of the second image will serve as the column.
Find this location in the matrix and increment this spot in the matrix by 1.
Repeat this for the rest of the locations in your image.
After you're done, divide all entries by the total number of elements in either image (remember they should be the same size). This will give us the joint probability distribution between both images.
One would be inclined to do this with for loops, but as it is commonly known, for loops are notoriously slow and should be avoided if at all possible. However, you can easily do this in MATLAB in the following way without loops. Let's assume that im1 and im2 are the first and second images you want to compare to. What we can do is convert im1 and im2 into vectors. We can then use accumarray to help us compute the joint histogram. accumarray is one of the most powerful functions in MATLAB. You can think of it as a miniature MapReduce paradigm. Simply put, each data input has a key and an associated value. The goal of accumarray is to bin all of the values that belong to the same key and do some operation on all of these values. In our case, the "key" would be the intensity values, and the values themselves are the value of 1 for every intensity value. We would then want to add up all of the values of 1 that map to the same bin, which is exactly how we'd compute a histogram. The default behaviour for accumarray is to add all of these values. Specifically, the output of accumarray would be an array where each position computes the sum of all values that mapped to that key. For example, the first position would be the summation of all values that mapped to the key of 1, the second position would be the summation of all values that mapped to the key of 2 and so on.
However, for the joint histogram, you want to figure out which values map to the same intensity pair of (i,j), and so the keys here would be a pair of 2D coordinates. As such, any intensities that have an intensity of i in the first image and j in the second image in the same spatial location shared between the two images go to the same key. Therefore in the 2D case, the output of accumarray would be a 2D matrix where each element (i,j) contains the summation of all values that mapped to key (i,j), similar to the 1D case that was mentioned previously which is exactly what we are after.
In other words:
indrow = double(im1(:)) + 1;
indcol = double(im2(:)) + 1; %// Should be the same size as indrow
jointHistogram = accumarray([indrow indcol], 1);
jointProb = jointHistogram / numel(indrow);
With accumarray, the first input are the keys and the second input are the values. A note with accumarray is that if each key has the same value, you can simply assign a constant to the second input, which is what I've done and it's 1. In general, this is an array with the same number of rows as the first input. Also, take special note of the first two lines. There will inevitably be an intensity of 0 in your image, but because MATLAB starts indexing at 1, we need to offset both arrays by 1.
Now that we have the joint histogram, it's really simple to calculate the joint entropy. It is similar to the entropy in 1D, except now we are just summing over the entire joint probability matrix. Bear in mind that it will be very likely that your joint histogram will have many 0 entries. We need to make sure that we skip those or the log2 operation will be undefined. Let's get rid of any zero entries now:
indNoZero = jointHistogram ~= 0;
jointProb1DNoZero = jointProb(indNoZero);
Take notice that I searched the joint histogram instead of the joint probability matrix. This is because the joint histogram consists of whole numbers while the joint probability matrix will lie between 0 and 1. Because of the division, I want to avoid comparing any entries in this matrix with 0 due to numerical roundoff and instability. The above will also convert our joint probability matrix into a stacked 1D vector, which is fine.
As such, the joint entropy can be calculated as:
jointEntropy = -sum(jointProb1DNoZero.*log2(jointProb1DNoZero));
If my understanding of calculating entropy for an image in MATLAB is correct, it should calculate the histogram / probability distribution over 256 bins, so you can certainly use that function here with the joint entropy that was just calculated.
What if we have floating-point data instead?
So far, we have assumed that the images that you have dealt with have intensities that are integer-valued. What if we have floating point data? accumarray assumes that you are trying to index into the output array using integers, but we can still certainly accomplish what we want with this small bump in the road. What you would do is simply assign each floating point value in both images to have a unique ID. You would thus use accumarray with these IDs instead. To facilitate this ID assigning, use unique - specifically the third output from the function. You would take each of the images, put them into unique and make these the indices to be input into accumarray. In other words, do this instead:
[~,~,indrow] = unique(im1(:)); %// Change here
[~,~,indcol] = unique(im2(:)); %// Change here
%// Same code
jointHistogram = accumarray([indrow indcol], 1);
jointProb = jointHistogram / numel(indrow);
indNoZero = jointHistogram ~= 0;
jointProb1DNoZero = jointProb(indNoZero);
jointEntropy = -sum(jointProb1DNoZero.*log2(jointProb1DNoZero));
Note that with indrow and indcol, we are directly assigning the third output of unique to these variables and then using the same joint entropy code that we computed earlier. We also don't have to offset the variables by 1 as we did previously because unique will assign IDs starting at 1.
Aside
You can actually calculate the histograms or probability distributions for each image individually using the joint probability matrix. If you wanted to calculate the histograms / probability distributions for the first image, you would simply accumulate all of the columns for each row. To do it for the second image, you would simply accumulate all of the rows for each column. As such, you can do:
histogramImage1 = sum(jointHistogram, 1);
histogramImage2 = sum(jointHistogram, 2);
After, you can calculate the entropy of both of these by yourself. To double check, make sure you turn both of these into PDFs, then compute the entropy using the standard equation (like above).
How do I finally compute Mutual Information?
To finally compute Mutual Information, you're going to need the entropy of the two images. You can use MATLAB's built-in entropy function, but this assumes that there are 256 unique levels. You probably want to apply this for the case of there being N distinct levels instead of 256, and so you can use what we did above with the joint histogram, then computing the histograms for each image in the aside code above, and then computing the entropy for each image. You would simply repeat the entropy calculation that was used jointly, but apply it to each image individually:
%// Find non-zero elements for first image's histogram
indNoZero = histogramImage1 ~= 0;
%// Extract them out and get the probabilities
prob1NoZero = histogramImage1(indNoZero);
prob1NoZero = prob1NoZero / sum(prob1NoZero);
%// Compute the entropy
entropy1 = -sum(prob1NoZero.*log2(prob1NoZero));
%// Repeat for the second image
indNoZero = histogramImage2 ~= 0;
prob2NoZero = histogramImage2(indNoZero);
prob2NoZero = prob2NoZero / sum(prob2NoZero);
entropy2 = -sum(prob2NoZero.*log2(prob2NoZero));
%// Now compute mutual information
mutualInformation = entropy1 + entropy2 - jointEntropy;
Hope this helps!

count and average certain pixels in image with MATLAB

I have one image in bmp format, with size of 512*512. I want to count the number of pixels with values more than 11 and then find the average of these pixels. Here is my code. I don't know what is the problem but the sum of pixel values is wrong and it is always 255. I tried with different images.
Could you please help me to figure it out?
A=imread('....bmp');
sum=0; count=0;
for i=1:512
for j=1:512
if (A(i,j)>=11)
sum=sum+A(i,j);
count=count+1;
end
end
end
disp('Number of pixels grater than or equal to 11')
disp(count)
disp('sum')
disp(sum)
disp('Average')
Avrg=sum/count;
disp(Avrg)
Why doesn't your code work
Difficult to tell, could you display a portion of your matrix and the size using something like
disp(A(1:10,1:10))
disp(size(A))
% possibly also the min and max...
disp(min(A(:))
disp(max(A(:))
just to be sure the format of A is as you expect - imread could have given you a 512x512x3 matrix if the image was read in color, or the image may be in the interval [0,1].
Better approach
Once you're sure that the matrix is indeed 512x512, and has values above 11, you're best off by generating a mask, i.e.
mask = A > 11;
numabove11 = sum(mask(:));
avabove11 = mean(A(mask));
Also in your code you use >= i.e. greater than or equal to, but you say 'greater than' - pick which you want and be consistent.
Explanation
So what do these 3 lines do?
Generate a logical matrix, same size as A that is true wherever A > 11, else false.
Sum the logical matrix, which means sum values that are 1 everywhere that A > 11, else 0 (boolean values are converted to floats for this summation).
Index in to matrix A using logical indexing, and take the mean of those values.
Avoid shadowing builtins
In your code you use the variable sum - this is bad practice as there is a builtin matlab function with the same name, which becomes unusable if you use a variable of the same name.
I also faced a similar problem and actually the solution lies in the fact that matlab stores A(i,j) in uint8 format whose maximum value is 255, so, just change the statement:
sum=sum+A(i,j);
to
sum=sum+double(A(i,j));
I hope this helps.

How to compute frequency of data using FFT?

I want to know the frequency of data. I had a little bit idea that it can be done using FFT, but I am not sure how to do it. Once I passed the entire data to FFT, then it is giving me 2 peaks, but how can I get the frequency?
Thanks a lot in advance.
Here's what you're probably looking for:
When you talk about computing the frequency of a signal, you probably aren't so interested in the component sine waves. This is what the FFT gives you. For example, if you sum sin(2*pi*10x)+sin(2*pi*15x)+sin(2*pi*20x)+sin(2*pi*25x), you probably want to detect the "frequency" as 5 (take a look at the graph of this function). However, the FFT of this signal will detect the magnitude of 0 for the frequency 5.
What you are probably more interested in is the periodicity of the signal. That is, the interval at which the signal becomes most like itself. So most likely what you want is the autocorrelation. Look it up. This will essentially give you a measure of how self-similar the signal is to itself after being shifted over by a certain amount. So if you find a peak in the autocorrelation, that would indicate that the signal matches up well with itself when shifted over that amount. There's a lot of cool math behind it, look it up if you are interested, but if you just want it to work, just do this:
Window the signal, using a smooth window (a cosine will do. The window should be at least twice as large as the largest period you want to detect. 3 times as large will give better results). (see http://zone.ni.com/devzone/cda/tut/p/id/4844 if you are confused).
Take the FFT (however, make sure the FFT size is twice as big as the window, with the second half being padded with zeroes. If the FFT size is only the size of the window, you will effectively be taking the circular autocorrelation, which is not what you want. see https://en.wikipedia.org/wiki/Discrete_Fourier_transform#Circular_convolution_theorem_and_cross-correlation_theorem )
Replace all coefficients of the FFT with their square value (real^2+imag^2). This is effectively taking the autocorrelation.
Take the iFFT
Find the largest peak in the iFFT. This is the strongest periodicity of the waveform. You can actually be a little more clever in which peak you pick, but for most purposes this should be enough. To find the frequency, you just take f=1/T.
Suppose x[n] = cos(2*pi*f0*n/fs) where f0 is the frequency of your sinusoid in Hertz, n=0:N-1, and fs is the sampling rate of x in samples per second.
Let X = fft(x). Both x and X have length N. Suppose X has two peaks at n0 and N-n0.
Then the sinusoid frequency is f0 = fs*n0/N Hertz.
Example: fs = 8000 samples per second, N = 16000 samples. Therefore, x lasts two seconds long.
Suppose X = fft(x) has peaks at 2000 and 14000 (=16000-2000). Therefore, f0 = 8000*2000/16000 = 1000 Hz.
If you have a signal with one frequency (for instance:
y = sin(2 pi f t)
With:
y time signal
f the central frequency
t time
Then you'll get two peaks, one at a frequency corresponding to f, and one at a frequency corresponding to -f.
So, to get to a frequency, can discard the negative frequency part. It is located after the positive frequency part. Furthermore, the first element in the array is a dc-offset, so the frequency is 0. (Beware that this offset is usually much more than 0, so the other frequency components might get dwarved by it.)
In code: (I've written it in python, but it should be equally simple in c#):
import numpy as np
from pylab import *
x = np.random.rand(100) # create 100 random numbers of which we want the fourier transform
x = x - mean(x) # make sure the average is zero, so we don't get a huge DC offset.
dt = 0.1 #[s] 1/the sampling rate
fftx = np.fft.fft(x) # the frequency transformed part
# now discard anything that we do not need..
fftx = fftx[range(int(len(fftx)/2))]
# now create the frequency axis: it runs from 0 to the sampling rate /2
freq_fftx = np.linspace(0,2/dt,len(fftx))
# and plot a power spectrum
plot(freq_fftx,abs(fftx)**2)
show()
Now the frequency is located at the largest peak.
If you are looking at the magnitude results from an FFT of the type most common used, then a strong sinusoidal frequency component of real data will show up in two places, once in the bottom half, plus its complex conjugate mirror image in the top half. Those two peaks both represent the same spectral peak and same frequency (for strictly real data). If the FFT result bin numbers start at 0 (zero), then the frequency of the sinusoidal component represented by the bin in the bottom half of the FFT result is most likely.
Frequency_of_Peak = Data_Sample_Rate * Bin_number_of_Peak / Length_of_FFT ;
Make sure to work out your proper units within the above equation (to get units of cycles per second, per fortnight, per kiloparsec, etc.)
Note that unless the wavelength of the data is an exact integer submultiple of the FFT length, the actual peak will be between bins, thus distributing energy among multiple nearby FFT result bins. So you may have to interpolate to better estimate the frequency peak. Common interpolation methods to find a more precise frequency estimate are 3-point parabolic and Sinc convolution (which is nearly the same as using a zero-padded longer FFT).
Assuming you use a discrete Fourier transform to look at frequencies, then you have to be careful about how to interpret the normalized frequencies back into physical ones (i.e. Hz).
According to the FFTW tutorial on how to calculate the power spectrum of a signal:
#include <rfftw.h>
...
{
fftw_real in[N], out[N], power_spectrum[N/2+1];
rfftw_plan p;
int k;
...
p = rfftw_create_plan(N, FFTW_REAL_TO_COMPLEX, FFTW_ESTIMATE);
...
rfftw_one(p, in, out);
power_spectrum[0] = out[0]*out[0]; /* DC component */
for (k = 1; k < (N+1)/2; ++k) /* (k < N/2 rounded up) */
power_spectrum[k] = out[k]*out[k] + out[N-k]*out[N-k];
if (N % 2 == 0) /* N is even */
power_spectrum[N/2] = out[N/2]*out[N/2]; /* Nyquist freq. */
...
rfftw_destroy_plan(p);
}
Note it handles data lengths that are not even. Note particularly if the data length is given, FFTW will give you a "bin" corresponding to the Nyquist frequency (sample rate divided by 2). Otherwise, you don't get it (i.e. the last bin is just below Nyquist).
A MATLAB example is similar, but they are choosing the length of 1000 (an even number) for the example:
N = length(x);
xdft = fft(x);
xdft = xdft(1:N/2+1);
psdx = (1/(Fs*N)).*abs(xdft).^2;
psdx(2:end-1) = 2*psdx(2:end-1);
freq = 0:Fs/length(x):Fs/2;
In general, it can be implementation (of the DFT) dependent. You should create a test pure sine wave at a known frequency and then make sure the calculation gives the same number.
Frequency = speed/wavelength.
Wavelength is the distance between the two peaks.

Resources