/*----------Global--------------------*/ void globalRange(PivData *pivData, FilterOptions filterOptions) { double u,v; int width = pivData->width(); int height = pivData->height(); double umin = filterOptions.umin(); double umax = filterOptions.umax(); double vmin = filterOptions.vmin(); double vmax = filterOptions.vmax(); /* Rejecting any point in the PivData where the displacement exceeds any of the user-defined global min/max values */ int i, j; for (i = 0; i < height; i++) { for (j = 0; j < width; j++) { if (pivData->isValid(i,j)) { u = pivData->data(i,j).u; v = pivData->data(i,j).v; if (u > umax || u < umin || v > vmax || v < vmin ) { pivData->setFilter(i,j,true); } } } } }
void MainWindow::qualityChanged() { FilterOptions filterOptions = settings->filterOptions(); filterOptions.enableSNR(filterSNRCheck->isChecked()); snrEdit->setEnabled(filterSNRCheck->isChecked()); filterOptions.setSnrThresh(snrEdit->text().toDouble()); filterOptions.enableImageIntensity(filterIntCheck->isChecked()); intensityEdit->setEnabled(filterIntCheck->isChecked()); filterOptions.setImageThresh(intensityEdit->text().toDouble()); settings->setFilterOptions(filterOptions); QTimer::singleShot(10000, this, SLOT(setDataQualityTab())); }
/*----------Image Intensity--------------------*/ void imageIntensity(PivData *pivData, FilterOptions filterOptions) { double imageIntensity; int width = pivData->width(); int height = pivData->height(); double imageThresh = filterOptions.imageThresh(); /* Rejecting any point in the PivData where the image intensity is below the user defined value. */ int i, j; for (i = 0; i < height; i++) { for (j = 0; j < width; j++) { if (pivData->isValid(i,j)) { imageIntensity = pivData->data(i,j).intensity; if (imageIntensity < imageThresh) { pivData->setFilter(i,j,true); } } } } }
/*----------SNR-----------------------*/ void snr(PivData *pivData, FilterOptions filterOptions) { double snr_i; int width = pivData->width(); int height = pivData->height(); double snrThresh = filterOptions.snrThresh(); /* Rejecting any point in the PivData where the signal- to-noise ratio is below the user defined value. */ int i, j; for (i = 0; i < height; i++) { for (j = 0; j < width; j++) { if (pivData->isValid(i,j)) { snr_i = pivData->data(i,j).snr; if (snr_i < snrThresh) { pivData->setFilter(i,j,true); } } } } }
void Analysis::filterData(PivData *pivData, FilterOptions filterOptions) { // Checking each filtering option and calling external filter functions (included from filters.h) if (filterOptions.snr()) snr(pivData,filterOptions); if (filterOptions.imageIntensity()) imageIntensity(pivData,filterOptions); if (filterOptions.globalRange()) globalRange(pivData,filterOptions); if (filterOptions.globalStd()) globalStd(pivData,filterOptions); if (filterOptions.local()) localDetect(pivData,filterOptions); if (filterOptions.interpolate()) meanInterpolate(pivData, filterOptions); if (filterOptions.smoothing()) gaussianBlur(pivData, filterOptions); }
static size_t serialize(struct DirectionalFilterOptions *self, unsigned char *buffer, size_t size) { FilterOptions *incoming = getIncomingFilterOptions(self); FilterOptions *outgoing = getOutgoingFilterOptions(self); size_t incomingSize = incoming->serialize(incoming, NULL, 0); size_t outgoingSize = outgoing->serialize(outgoing, NULL, 0); size_t expectedSize = incomingSize + outgoingSize; if (buffer != NULL && size >= expectedSize) { incoming->serialize(incoming, buffer, incomingSize); outgoing->serialize(outgoing, buffer + incomingSize, outgoingSize); } return expectedSize; }
void MainWindow::filterChanged() { FilterOptions filterOptions; filterOptions = settings->filterOptions(); // Global filterOptions.enableGlobalRange(globalRangeCheck->isChecked()); filterOptions.enableGlobalStd(globalStDevCheck->isChecked()); // Local filterOptions.enableLocal(localCheck->isChecked()); // Interpolate filterOptions.enableInterpolate(interpolateCheck->isChecked()); // Smoothing filterOptions.enableSmoothing(smoothCheck->isChecked()); settings->setFilterOptions(filterOptions); setFilterTab(); }
/*---------- Smoothing --------------*/ void gaussianBlur(PivData *pivData, FilterOptions filterOptions) { int width = pivData->width(); int height = pivData->height(); int i, j, k, k1, k2; double x, y; double *uTemp, *vTemp; uTemp = new double [width*height + 1]; vTemp = new double [width*height + 1]; double radius = filterOptions.smoothRadius(); int N = filterOptions.smoothNxN(); int halfN = floor(double(N - 1) / 2.0); double *kernel = new double [N*N+1]; double sumU, sumV; PivPointData pointData; // Creation of the kernel k = 0; x = 0.0; for (y = -double(halfN); y <= double(halfN); y = y + 1.0) { for (x = -double(halfN); x <= double(halfN); x = x + 1.0) { kernel[k] = 0.5 / pi / radius / radius * exp(-(x*x + y*y) / 2.0 / radius / radius); k++; } } // Convolution for (i = 0; i < height; i++) { for (j = 0; j < width; j++) { sumU = 0.0; sumV = 0.0; for (k1 = -halfN; k1 <= halfN; k1++) { for (k2 = -halfN; k2 <= halfN; k2++) { sumU += pivData->data(i-k1,j-k2).u * kernel[(halfN+k1)*N+(halfN+k2)]; sumV += pivData->data(i-k1,j-k2).v * kernel[(halfN+k1)*N+(halfN+k2)]; } } // Store values to temporary arrays to avoid propogation effects uTemp[i*width+j] = sumU; vTemp[i*width+j] = sumV; } } // Reassign temporary arrays to original PivData object for (i = 0; i < height; i++) { for (j = 0; j < width; j++) { pointData = pivData->data(i,j); pointData.u = uTemp[i*width+j]; pointData.v = vTemp[i*width+j]; pivData->setData(i,j,pointData); } } delete [] kernel; delete [] uTemp; delete [] vTemp; }
/*---------Interpolate---------------*/ void meanInterpolate(PivData *pivData, FilterOptions filterOptions) { int width = pivData->width(); int height = pivData->height(); double *uTemp, *vTemp; uTemp = new double [width*height + 1]; vTemp = new double [width*height + 1]; int N = filterOptions.intNxN(); int halfN = floor(double(N - 1) / 2.0); int i, j, m, n; double mxU, mxV; int count; PivPointData pointData; // Creating temporary velocity field from original PivData object for (i = 0; i < height; i++) { for (j = 0; j < width; j++) { uTemp[i*width+j] = pivData->data(i,j).u; vTemp[i*width+j] = pivData->data(i,j).v; } } for (i = 0; i < height; i++) { for (j = 0; j < width; j++) { // If the current vector is flagged as erroneous if (pivData->filtered(i,j)) { count = 0; mxU = 0.0; mxV = 0.0; for (m = -halfN; m <= halfN; m++) { for (n = -halfN; n <= halfN; n++) { // Calculate the local average from valid points if (!pivData->filtered(i+m,j+n) && pivData->isValid(i+m,j+n)) { mxU += pivData->data(i+m,j+n).u; mxV += pivData->data(i+m,j+n).v; count++; } } } // Assign the current vector the value of the local mean if (count > 0) { uTemp[i*width + j] = mxU / double(count); vTemp[i*width + j] = mxV / double(count); } } } } // Reassign the temporary (new) data to the original object for (i = 0; i < height; i++) { for (j = 0; j < width; j++) { pointData = pivData->data(i,j); pointData.u = uTemp[i*width+j]; pointData.v = vTemp[i*width+j]; pivData->setData(i,j,pointData); } } // Cleaning up delete [] uTemp; delete [] vTemp; }
/*------------Local-------------------*/ void localDetect(PivData *pivData, FilterOptions filterOptions) { double u, v; int width = pivData->width(); int height = pivData->height(); int i, j, m, n, count; int N = filterOptions.localNxN(); int halfN = floor(double(N - 1) / 2.0); double uTol = filterOptions.uTol(); double vTol = filterOptions.vTol(); // First need to calculate the central estimator of the local neighbourhood switch(filterOptions.localMethod()) { // Calculation of the local mean case OpenPIV::LocalMean: double mxU, mxV; for (i = 0; i < height; i++) { for (j = 0; j < width; j++) { u = pivData->data(i,j).u; v = pivData->data(i,j).v; mxU = 0.0; mxV = 0.0; count = 0; for (m = -halfN; m <= halfN; m++) { for (n = -halfN; n <= halfN; n++) { if (!pivData->filtered(i+m,j+n)) { mxU += pivData->data(i+m,j+n).u; mxV += pivData->data(i+m,j+n).v; count++; } } } if (count > 0) { mxU = mxU / double(count); mxV = mxV / double(count); } else { mxU = 0.0; mxV = 0.0; } /* Rejecting any point in the PivData where the displacment exceeds the tolerance of the local mean. */ if (u > (mxU + uTol) || u < (mxU - uTol) || v > (mxV + vTol) || v < (mxV - vTol)) { pivData->setFilter(i,j,true); } } } break; // Calculation of the local median case OpenPIV::LocalMedian: double medU, medV; QList<double> listU; QList<double> listV; for (i = 0; i < height; i++) { for (j = 0; j < width; j++) { u = pivData->data(i,j).u; v = pivData->data(i,j).v; listU.clear(); listV.clear(); for (m = -halfN; m <= halfN; m++) { for (n = -halfN; n <= halfN; n++) { if (!pivData->filtered(i+m,j+n)) { listU << pivData->data(i+m,j+n).u; listV << pivData->data(i+m,j+n).v; } } } qSort(listU.begin(), listU.end()); qSort(listV.begin(), listV.end()); medU = listU.value(int(ceil(double(listU.size())/2.0))); medV = listV.value(int(ceil(double(listV.size())/2.0))); /* Rejecting any point in the PivData where the displacment exceeds the tolerance of the local median. */ if (u > (medU + uTol) || u < (medU - uTol) || v > (medV + vTol) || v < (medV - vTol)) { pivData->setFilter(i,j,true); } } } break; } }
void globalStd(PivData *pivData, FilterOptions filterOptions) { double u,v; double mxU = 0.0; double mxV = 0.0; double sxU = 0.0; double sxV = 0.0; int width = pivData->width(); int height = pivData->height(); double nSigma = filterOptions.nStd(); // First, compute the global average int i, j; int count = 0; for (i = 0; i < height; i++) { for (j = 0; j < width; j++) { if (pivData->isValid(i,j)) { u = pivData->data(i,j).u; v = pivData->data(i,j).v; mxU += u; mxV += v; count++; } } } if (count > 0) { mxU = mxU / double(count); mxV = mxV / double(count); } else { mxU = 0.0; mxV = 0.0; } // Next, compute the standard deviation count = 0; for (i = 0; i < height; i++) { for (j = 0; j < width; j++) { if (pivData->isValid(i,j)) { u = pivData->data(i,j).u; v = pivData->data(i,j).v; sxU += (u - mxU) * (u - mxU); sxV += (v - mxV) * (v - mxV); count++; } } } if (count > 0) { sxU = sqrt(sxU / double(count)); sxV = sqrt(sxV / double(count)); } else { sxU = 0.0; sxV = 0.0; } /* Rejecting any point in the PivData where the displacment is farther away than nSigma times the global standard deviation from the global average. */ for (i = 0; i < height; i++) { for (j = 0; j < width; j++) { if (pivData->isValid(i,j)) { u = pivData->data(i,j).u; v = pivData->data(i,j).v; if (u > (mxU + nSigma*sxU) || u < (mxU - nSigma*sxU) || v > (mxV + nSigma*sxV) || v < (mxV - nSigma*sxV)) { pivData->setFilter(i,j,true); } } } } }
void MainWindow::setFilterValues() { //std::cout << "in setFilterValues\n"; FilterOptions filterOptions; filterOptions = settings->filterOptions(); // Global double temp; if (filterOptions.globalRange()) { double umin = minUedit->text().toDouble(); double umax = maxUedit->text().toDouble(); if (umin > umax) { temp = umin; umin = umax; umax = temp; } double vmin = minVedit->text().toDouble(); double vmax = maxVedit->text().toDouble(); if (vmin > vmax) { temp = vmin; vmin = vmax; vmax = temp; } filterOptions.setRange(umin,umax,vmin,vmax); } if (filterOptions.globalStd()) filterOptions.setNStd(nStdDevSpin->value()); // Local double u, v; if (filterOptions.local()) { filterOptions.setLocalMethod(localMethodCombo->currentIndex()); filterOptions.setLocalNxN((localNxNCombo->currentIndex()+1)*2+1); u = localUedit->text().toDouble(); v = localVedit->text().toDouble(); filterOptions.setLocalTolerance(u, v); } // Interpolate if (filterOptions.interpolate()) { filterOptions.setIntMethod(interpolateMethodCombo->currentIndex()); filterOptions.setLocalNxN((interpolateNxNCombo->currentIndex()+1)*2+1); } // Smoothing if (filterOptions.smoothing()) { filterOptions.setSmoothRadius(smoothRadiusEdit->text().toDouble()); filterOptions.setSmoothNxN((smoothNxNCombo->currentIndex()+1)*2+1); } // Write and delay changes settings->setFilterOptions(filterOptions); QTimer::singleShot(10000, this, SLOT(setFilterTab())); }
void MainWindow::setFilterTab() { FilterOptions filterOptions = settings->filterOptions(); // Global minUedit->setText(QString("%1").arg(filterOptions.umin())); maxUedit->setText(QString("%1").arg(filterOptions.umax())); minVedit->setText(QString("%1").arg(filterOptions.vmin())); maxVedit->setText(QString("%1").arg(filterOptions.vmax())); minUedit->setEnabled(filterOptions.globalRange()); maxUedit->setEnabled(filterOptions.globalRange()); minVedit->setEnabled(filterOptions.globalRange()); maxVedit->setEnabled(filterOptions.globalRange()); nStdDevSpin->setValue(filterOptions.nStd()); nStdDevSpin->setEnabled(filterOptions.globalStd()); // Local localMethodCombo->setEnabled(filterOptions.local()); localMethodCombo->setCurrentIndex(filterOptions.localMethod()); localNxNCombo->setEnabled(filterOptions.local()); localNxNCombo->setCurrentIndex((filterOptions.localNxN()-1)/2-1); localUedit->setEnabled(filterOptions.local()); localVedit->setEnabled(filterOptions.local()); localUedit->setText(QString("%1").arg(filterOptions.uTol())); localVedit->setText(QString("%1").arg(filterOptions.vTol())); // Interpolate interpolateMethodCombo->setEnabled(filterOptions.interpolate()); interpolateMethodCombo->setCurrentIndex(filterOptions.intMethod()); interpolateNxNCombo->setEnabled(filterOptions.interpolate()); interpolateNxNCombo->setCurrentIndex((filterOptions.intNxN()-1)/2-1); // Smoothing smoothNxNCombo->setEnabled(filterOptions.smoothing()); smoothNxNCombo->setCurrentIndex((filterOptions.smoothNxN()-1)/2-1); smoothRadiusEdit->setEnabled(filterOptions.smoothing()); smoothRadiusEdit->setText(QString("%1").arg(filterOptions.smoothRadius())); }