I am a beginner in C++ programming. I try working with arrays and the Eigen module. Now I came across a problem I could solve in hours. Maybe it is pretty basic, but I am lost.
QPair<int, double> ConnectivityMeasures::calcImaginaryCoherence(const RowVectorXd& vecFirst, const RowVectorXd& vecSecond, int iNumberEpochs)
{
Eigen::FFT<double> fft;
int N = std::max( vecFirst.cols(), vecSecond.cols() ) ;
//Compute the NFFT
int b = ceil( log2(2.0 * N - 1) ) ;
int fftsize = pow(2,b) ;
//Zero Padding --> Cropping/Extending the Signal to the NFFT size. Cropping=Deleting Values; Extending=Fill up with Zeros
RowVectorXd xImCohInputVecFirst = RowVectorXd::Zero(fftsize) ;
xImCohInputVecFirst.head(vecFirst.cols() ) = vecFirst ;
RowVectorXd xImCohInputVecSecond = RowVectorXd::Zero(fftsize) ;
xImCohInputVecSecond.head( vecSecond.cols() ) = vecSecond ;
//FFT for freq domain to both vectors
RowVectorXcd freqvec ;
RowVectorXcd freqvec2 ;
fft.fwd(freqvec, xImCohInputVecFirst) ;
freqvec.conjugate() ;
fft.fwd(freqvec2, xImCohInputVecSecond) ;
freqvec2.conjugate() ;
// Calculate PowerSpectralDensitiy (PSD) and CrossSpectralDensity(CSD)
VectorXcd Rxy(iNumberEpochs, fftsize);
VectorXcd Rxx(iNumberEpochs, fftsize);
VectorXcd Ryy(iNumberEpochs, fftsize);
for (int i = 0; i < iNumberEpochs; i++)
{
Rxy[i] = sqrt( pow((freqvec[i].real() * freqvec2[i].real() + freqvec[i].imag() * freqvec2[i].imag()), 2 ) + pow((freqvec[i].real() * freqvec2[i].imag() + freqvec[i].imag() * freqvec2[i].real()), 2) );
Rxx[i] = ( pow(freqvec[i], 2) );
Ryy[i] = ( pow(freqvec2[i], 2) );
}
// Average PSD, CSD over the Number of Epochs; not over channels
RowVectorXcd Rxy_mean(freqvec) = Rxy.mean() ;
RowVectorXcd Rxx_mean(freqvec) = Rxx.mean() ;
RowVectorXcd Ryy_mean(freqvec2) = Ryy.mean() ;
So my problem starts here. I have a 2D Array for my Rxy, Rxx and Ryy values. Stored like [number of epochs, number of frequencies].
Now I want to average all frequency values of each epoch to a single value and store them as Rxy_mean, Ryy_mean and Rxx_mean
My Compiler spit out ' Syntax error: missing ";" before "=" '
Does anyone can say how to fix this, proceed or point out my mistake with a simple example ?
Thanks in advance,
Daniel
Related
I am a very beginner in c++ and I want to do some spectral calculations, in this case calculating the 'Cross Spectral Density' of two signal (vecFirst, vecSecond), which are already processed with a FastFourierTransformation. Resulting in freqvec and freqvec2, containing complex values for each frequency.
For this calculating it is essential to keep every value as a complex value. E.g.: CoSpectrum, which is calculated in line 6, should has a complex value as a result.
RowVectorXcd freqvec;
RowVectorXcd freqvec2;
fft.fwd(freqvec, vecFirst);
fft.fwd(freqvec2, vecSecond);
// # Create conjugate complex
freqvec.conjugate();
freqvec2.conjugate();
RowVectorXcd Rxy(freqvec.cols());
for (int i = 0; i < freqvec.cols(); i++) {
std::complex<double>CoSpectrum( freqvec(i).real() * freqvec2(i).real() + freqvec(i).imag() * freqvec2(i).imag()) ;
std::complex<double>QuadSpectrum( freqvec(i).real() * freqvec2(i).imag() - freqvec(i).real() * freqvec2(i).imag() ) ;
std::complex<double>CoSpectrum_sqr = CoSpectrum * CoSpectrum ;
std::complex<double>QuadSpectrum_sqr = QuadSpectrum * QuadSpectrum ;
Rxy(i) = sqrt(std::complex<double>(CoSpectrum_sqr + QuadSpectrum_sqr)) ;
}
}
Unfortunately I only get complex values with zero in the imaginary part.
Can anyone tell me why?
I am guessing the expression freqvec(i).real() only returns a double value, but how can I get the real part but keep it a complexvalue. Or, accordingly, just multiply the imaginary part of a complex number with the real part of another and keep it the result a complex double.
Thanks for any help in advance.
At first: Thank you very much. I had thought of something like that, but wasn't sure. Thank got there a nice people like you who care about beginners.
So I changed the snippet as following:
// ### Attempting to compute the Frequency Power for Frequency Bins..
RowVectorXcd freqvec;
RowVectorXcd freqvec2;
fft.fwd(freqvec, vecFirst);
fft.fwd(freqvec2, vecSecond);
std::cout<<"freqvec:"<<freqvec.cols()<<std::endl;
// ### Attempting to compute the PowerSpectralDensitiy(PSD) and CrossSpectralDensity(CSD). The cross-spectral density is the Fourier transform of the cross-correlation function.
RowVectorXcd Rxy(n_Epochs, freqvec.cols());
RowVectorXcd Rxx(n_Epochs, freqvec.cols());
RowVectorXcd Ryy(n_Epochs, freqvec.cols());
for (int i = 0; i < n_Epochs; i++) {
std::complex<double>CoSpectrum( std::complex<double>(freqvec(i).real(),0) * std::complex<double>(freqvec2(i).real(),0) + std::complex<double>(0,freqvec(i).imag()) * std::complex<double>(0, freqvec2(i).imag()) ) ;
std::complex<double>QuadSpectrum( std::complex<double>(freqvec(i).real(), 0) * std::complex<double>(0, freqvec2(i).imag()) - std::complex<double>(0,freqvec(i).imag()) * std::complex<double>(freqvec2(i).real(), 0) ) ;
std::complex<double>CoSpectrum_sqr = CoSpectrum * CoSpectrum ;
std::complex<double>QuadSpectrum_sqr = QuadSpectrum * QuadSpectrum ;
Rxy(i) = sqrt(std::complex<double>(CoSpectrum_sqr + QuadSpectrum_sqr)) ;
Rxx(i) = std::complex<double>(freqvec(i).real(), 0) * std::complex<double>(freqvec(i).real(), 0) + std::complex<double>(0, freqvec(i).imag()) * std::complex<double>(0, freqvec(i).imag()) ;
Ryy(i) = std::complex<double>(freqvec2(i).real(), 0) * std::complex<double>(freqvec2(i).real(), 0) + std::complex<double>(0, freqvec2(i).imag()) * std::complex<double>(0, freqvec2(i).imag()) ;
}
}
This solved my problem. Thanks again for the nice discussion.
Dear community,
I am facing a rather annoying problem. I am calculating the Cross Spectral Density (CSD) between two time signals, which were already proccessed with FFT to two complex frequency vectors(Singal1 =>freqvec, Signal2 => freqvec2).
RowVectorXcd CSD(n_Epochs, fftsize);
for(int j = 0; j < fftsize; j++) {
std::complex<double> cospectrum = freqvec(j).real() * freqvec2(j).real() + freqvec(j).imag() * freqvec2(j).imag() ;
std::complex<double> quadspectrum = freqvec(j).real() * freqvec2(j).imag() - freqvec(j).imag() * freqvec2(j).real() ;
std::cout << "cospectrum:"<<cospectrum<< std::endl;
CSD(j) = sqrt( pow( cospectrum, 2 ) + pow( quadspectrum, 2) ) ;
For further computations I need to get the imaginary part of this calculation correctly.
The calculation does work, but somehow the result always has an imaginary value of zero.
I have been trying to implement the meanshift algorithm for tracking objects, and have gone through the concepts involved.
As per now I have managed to successfully generate a backprojected stream from my camera with a single channel hue roi histogram and a single channel hue video stream which seems fine, I know there is a meanshift function within the opencv library but I am trying to implement one myself using the data structures provided in opencv, calculating the moments and computing the mean centroid of the search window.
But for some reason I am unable to locate the problem within my code as it keeps on converging to the upper left corner of my video stream for any input roi (region of interest) to be tracked. Following is a code snippet of the function for calculating the centroid of the search window where I feel the problem lies but not sure what it is, I would really appreciate if someone can point me in the right direction:
void moment(Mat &backproj, Rect &win){
int x_c, y_c, x_c_new, y_c_new;
int idx_row, idx_col;
double m00 = 0.0 , m01 = 0.0 , m10 = 0.0 ;
double res = 1.0, TOL = 0.003 ;
//Set the center of search window as the center of the probabilistic image:
y_c = (int) backproj.rows / 2 ;
x_c = (int) backproj.cols / 2 ;
//Centroid search solver until residual below certain tolerance:
while (res > TOL){
win.width = (int) 80;
win.height = (int) 60;
//First array element at position (x,y) "lower left corner" of the search window:
win.x = (int) (x_c - win.width / 2) ;
win.y = (int) (y_c - win.height / 2);
//Modulo correction since modulo of negative integer is negative in C:
if (win.x < 0)
win.x = win.x % backproj.cols + backproj.cols ;
if (win.y < 0)
win.y = win.y % backproj.rows + backproj.rows ;
for (int i = 0; i < win.height; i++ ){
//Traverse along y-axis (height) i.e. rows ensuring wrap around top/bottom boundaries:
idx_row = (win.y + i) % (int)backproj.rows ;
for (int j = 0; j < win.width; j++ ){
//Traverse along x-axis (width) i.e. cols ensuring wrap around left/right boundaries:
idx_col = (win.x + j) % (int)backproj.cols ;
//Compute Moments:
m00 += (double) backproj.at<uchar>(idx_row, idx_col) ;
m10 += (double) backproj.at<uchar>(idx_row, idx_col) * i ;
m01 += (double) backproj.at<uchar>(idx_row, idx_col) * j ;
}
}
//Compute new centroid coordinates of the search window:
x_c_new = (int) ( m10 / m00 ) ;
y_c_new = (int) ( m01 / m00 );
//Compute the residual:
res = sqrt( pow((x_c_new - x_c), 2.0) + pow((y_c_new - y_c), 2.0) ) ;
//Set new search window centroid coordinates:
x_c = x_c_new;
y_c = y_c_new;
}
}
It's my second ever query on stackoverflow so please excuse me for any guidelines that I forgot to follow.
EDIT
changed m00 , m01 , m10 to block level variables within WHILE-LOOP instead of function level variables, thanks to Daniel Strul for pointing it out but the problem still remains. Now the search window jumps around the frame boundaries instead of focusing on the roi.
void moment(Mat &backproj, Rect &win){
int x_c, y_c, x_c_new, y_c_new;
int idx_row, idx_col;
double m00 , m01 , m10 ;
double res = 1.0, TOL = 0.003 ;
//Set the center of search window as the center of the probabilistic image:
y_c = (int) backproj.rows / 2 ;
x_c = (int) backproj.cols / 2 ;
//Centroid search solver until residual below certain tolerance:
while (res > TOL){
m00 = 0.0 , m01 = 0.0 , m10 = 0.0
win.width = (int) 80;
win.height = (int) 60;
//First array element at position (x,y) "lower left corner" of the search window:
win.x = (int) (x_c - win.width / 2) ;
win.y = (int) (y_c - win.height / 2);
//Modulo correction since modulo of negative integer is negative in C:
if (win.x < 0)
win.x = win.x % backproj.cols + backproj.cols ;
if (win.y < 0)
win.y = win.y % backproj.rows + backproj.rows ;
for (int i = 0; i < win.height; i++ ){
//Traverse along y-axis (height) i.e. rows ensuring wrap around top/bottom boundaries:
idx_row = (win.y + i) % (int)backproj.rows ;
for (int j = 0; j < win.width; j++ ){
//Traverse along x-axis (width) i.e. cols ensuring wrap around left/right boundaries:
idx_col = (win.x + j) % (int)backproj.cols ;
//Compute Moments:
m00 += (double) backproj.at<uchar>(idx_row, idx_col) ;
m10 += (double) backproj.at<uchar>(idx_row, idx_col) * i ;
m01 += (double) backproj.at<uchar>(idx_row, idx_col) * j ;
}
}
//Compute new centroid coordinates of the search window:
x_c_new = (int) ( m10 / m00 ) ;
y_c_new = (int) ( m01 / m00 );
//Compute the residual:
res = sqrt( pow((x_c_new - x_c), 2.0) + pow((y_c_new - y_c), 2.0) ) ;
//Set new search window centroid coordinates:
x_c = x_c_new;
y_c = y_c_new;
}
}
The reason your algorithms always converges to the upper left corner independently of the input data is that m00, m10 and m01 are never reset to zero:
On iteration 0, for each moment variable m00, m10 and m01, you compute the right value m0
Between iteration 0 and iteration 1 , the moments variables are not reset and keep their previous value
Thus, on iteration 1, for each moment variable m00, m10 and m01, you actually sum the new moment with the old one and obtain ( m0 + m1 )
On iteration 2, you carry on summing the new moments on top of the previous ones and obtain ( m0 + m1 + m2 )
And so on, iteration by iteration.
At the very least, the moment variables should be reset at the beginning of each iteration.
Ideally, they should not be function-level variables but should rather be block-level variables, as they have no use outside the loop iterations (except for debugging purpose):
while (res > TOL){
...
double m00 = 0.0, m01 = 0.0, m10 = 0.0;
for (int i = 0; i < win.height; i++ ){
...
EDIT 1
The reason for the second problem you encounter (the ROI jumping all around the place) is that the computations of the moments are based on the relative coordinates i and j.
Thus, what you compute is [ avg(j) , avg(i) ], wher as what you really want is [ avg(y) , avg(x) ]. To solve this issue, I had proposed a first solution. I"ve replaced it by a much simpler solution below.
EDIT 2
The simplest solution is to add the coordinates of the ROI corner right at the end of each iteration:
x_c_new = win.x + (int) ( m10 / m00 ) ;
y_c_new = win.y + (int) ( m01 / m00 );
I have been trying to implement a simple Gaussian blur algorithm, for my image editing program. However, I have been having some trouble making this work, and I think the problem lies in the below snippet:
for( int j = 0; j < pow( kernel_size, 2 ); j++ )
{
int idx = ( i + kx + ( ky * img.width ));
//Try and overload this whenever possible
valueR += ( img.p_pixelArray[ idx ].r * kernel[ j ] );
valueG += ( img.p_pixelArray[ idx ].g * kernel[ j ] );
valueB += ( img.p_pixelArray[ idx ].b * kernel[ j ] );
if( kx == kernel_limit )
{
kx = -kernel_limit;
ky++;
}
else
{
kx++;
}
}
kx = -kernel_limit;
ky = -kernel_limit;
A brief explanation of the code above: kernel size is the size of the kernel (or matrix) generated by the Gaussian blur formula. kx and ky are variables to be used for iterating over the kernel. i is the parent loop, that nests this one, and goes over every pixel in the image. Each value variable simply holds a float R, G, or B value, and is used afterwards to obtain the final result. The if-else is used to increase kx and ky. idx is used to find the correct pixel. kernel limit is a variable set to
(*kernel size* - 1) / 2
So I can have kx going from -1 ( with a 3x3 kernel ) to +1, and the same thing with ky. I think the problem lies with the line
int idx = ( i + kx + ( ky * img.width ));
But I am not sure. The image I get is:
As can be seen, the color is blurred in a diagonal direction, and looks more like some kind of motion blur than Gaussian blur. If someone could help out, I would be very grateful.
EDIT:
The way I fill the kernel is as follows:
for( int i = 0; i < pow( kernel_size, 2 ); i++ )
{
// This. Is. Lisp.
kernel[i] = (( 1 / ( 2 * pi * pow( sigma, 2 ))) * pow (e, ( -((( pow( kx, 2 ) + pow( ky, 2 )) / 2 * pow( sigma, 2 ))))));
if(( kx + 1 ) == kernel_size )
{
kx = 0;
ky++;
}
else
{
kx++;
}
}
Few problems:
Your Gaussian misses brackets (even though you already have plenty..) around 2 * pow( sigma, 2 ). Now you multiply by variance instead of divide.
But what your problem is, is that your gaussian is centered at kx = ky = 0, as you let it run from 0 to kernel_size, instead of from -kernel_limit to kernel_limit. This results in the diagonal blurring. Something like the following should work better
kx = -kernel_limit;
ky = -kernel_limit;
int kernel_size_sq = kernel_size * kernel_size;
for( int i = 0; i < kernel_size_sq; i++ )
{
double sigma_sq = sigma * sigma;
double kx_sq = kx * kx;
double ky_sq = ky * ky;
kernel[i] = 1.0 / ( 2 * pi * sigma_sq) * exp(-(kx_sq + ky_sq) / (2 * sigma_sq));
if(kx == kernel_limit )
{
kx = -kernel_limit;
ky++;
}
else
{
kx++;
}
}
Also note how I got rid of your lisp-ness and some improvements: use some intermediate variables for clarity (compiler will optimize them away if anyway you ask it to); simple multiplication is faster than pow(x, 2); pow(e, x) == exp(x).
I'd like to create a not squared set of images using ccfits. I can make a single one in the primaryHDU, like this:
long axes[2] = { jmax, imax };
std::auto_ptr<CCfits::FITS> pFits(0);
pFits.reset ( new CCfits::FITS ( "fitfile.fits", FLOAT_IMG, 2, axes ) );
std::valarray<double> h2a0array ( jmax * imax );
for ( int i = 0 ; i < imax ; i++
for ( int j = 0 ; j < jmax ; j++ )
h2a0array [ j + jmax * i ] = i + j;
pFits->pHDU().write ( fpixel, imax * jmax, h2a0array );
But I don't know how to add other not-squared images to my FITS file. I guess I have to use the CCFITS::addImage function, but can only obtain squared images using it:
long fpixel ( 1 );
std::vector<long> extAx ( 2, dim );
CCfits::ExtHDU* imageExt2 = pFits->addImage ( "h2a0array", FLOAT_IMG, extAx );
imageExt2->write ( fpixel, imax * jmax, h2a0array );
The extAx vector contains only two values, the first is the dimension (1D, 2D, 3D) of the image to add to the FITS file, the second is its size. I don't know any other way to add an image to a FITS file. If someone does, your help is strongly welcome!
Thanks,
Arnaud.
The vector of the last argument of addImage can have any dimension
and different axis lengths in the dimensions. There is no requirement that
the axis lengths are the same ("square" as you seem to call it):
vector<long> extAx ;
extAx.push_back(imax) ;
extAx.push_back(jmax) ;
extAx.push_back(kmax) ;
pFits->addImage("h2a0array", FLOAT_IMG, extAx );