cv::Mat blurPatch(const cv::Mat &_patch, cv::Point2f one, cv::Point2f two) { cv::Mat blurredWindow = _patch.clone(); //std::cout << "Start Blurring" << std::endl; cv::Mat patch = _patch.clone(); patch.convertTo(patch, cv::DataType<double>::type); cv::Mat kernel = evaluateKernel(one,two); cv::Point2f anchor = cv::Point( -1, -1 ); int delta = 0, ddepth = -1; filter2D(patch, patch, ddepth, kernel, anchor, delta, cv::BORDER_DEFAULT); patch.convertTo(patch, CV_8U); //std::cout << "Stop Blurring" << std::endl; // hconcat(blurredWindow, patch, blurredWindow); // imshow("Blurring", blurredWindow); // cv::waitKey(1); return patch; }
//------------------------------------------------------------------------------ void Solver::computeAcceleration (unsigned char res) { IDList::const_iterator i = mFluidParticles[res]->ActiveIDs.begin(); IDList::const_iterator e = mFluidParticles[res]->ActiveIDs.end(); for (; i != e; i++) { float *pos = &mFluidParticles[res]->Positions[2*(*i)]; float *vel = &mVelocities[res][2*(*i)]; float *acc = &mAccelerations[res][2*(*i)]; float den = mDensities[res][*i]; float pre = mPressures[res][*i]; // std::cout << mDensities[LOW][*i] << std::endl; float ene[2]; ene[0] = 0.0f; ene[1] = 0.0f; float psiSum = 0.0f; // reset acc acc[0] = 0.0f; acc[1] = 0.0f; // reserve mem for tension force float accT[2]; accT[0] = 0.0f; accT[1] = 0.0f; // reserve mem for boundary force float accB[2]; accB[0] = 0.0f; accB[1] = 0.0f; //====================================================================== // Compute force contribution from the same domain //====================================================================== // get neighbor ids mFluidHashTable[res]->Query(Vector2f(pos)); const IDList& neighbors = mFluidHashTable[res]->GetResult(); IDList::const_iterator j = neighbors.begin(); IDList::const_iterator je = neighbors.end(); for (; j != je; j++) { float *posj = &mFluidParticles[res]->Positions[2*(*j)]; float *velj = &mVelocities[res][2*(*j)]; float denj = mDensities[res][*j]; float prej = mPressures[res][*j]; float dist = computeDistance(pos, posj); float xij[2]; xij[0] = pos[0] - posj[0]; xij[1] = pos[1] - posj[1]; float vij[2]; vij[0] = vel[0] - velj[0]; vij[1] = vel[1] - velj[1]; if (dist < mConfiguration.EffectiveRadius[res]) { // compute SPH pressure coefficient float coeff = (pre/(den*den) + prej/(denj*denj)); float vx = computeDotProduct(xij, vij); float h = mConfiguration.EffectiveRadius[res]; // check if artificial viscosity shoud be applied if (vx < 0.0f) { // add artificial velocity to the SPH Force coefficient float x2 = dist*dist; float nu = -2.0f*mConfiguration.Alpha*h* mConfiguration.SpeedSound/(den + denj); coeff += nu*vx/(x2 + 0.01f*h*h); } // evaluate kernel gradient and add contribution of particle j // to acc Vector2f grad = evaluateKernelGradient(Vector2f(xij), dist, h); acc[0] += mBlendValues[res][*j]*coeff*grad.X; acc[1] += mBlendValues[res][*j]*coeff*grad.Y; // compute tension force and add to the acc float kernelT = mBlendValues[res][*j]*evaluateKernel(dist, h); accT[0] -= mConfiguration.TensionCoefficient*xij[0]*kernelT; accT[1] -= mConfiguration.TensionCoefficient*xij[1]*kernelT; float w2 = mConfiguration.FluidParticleMass[res]/ mConfiguration.FluidParticleMass[LOW]; float mw = w2*mexicanHat2D ( xij[0]/mConfiguration.EffectiveRadius[LOW], xij[1]/mConfiguration.EffectiveRadius[LOW] ); ene[0] += velj[0]*mw; ene[1] += velj[1]*mw; psiSum += mw; mStates[res][*i] |= (mStates[res][*j] << 1) & 0x04; } } //====================================================================== // Compute force contribution from the contemp. domain //====================================================================== float accC[2]; accC[0] = 0.0f; accC[1] = 0.0f; float accCT[2]; accCT[0] = 0.0f; accCT[1] = 0.0f; unsigned char resc = (res + 1) % 2; mFluidHashTable[resc]->Query ( Vector2f(pos), mConfiguration.EffectiveRadius[LOW] ); const IDList& neighborsc = mFluidHashTable[resc]->GetResult(); IDList::const_iterator jc = neighborsc.begin(); IDList::const_iterator jce = neighborsc.end(); for (; jc != jce; jc++) { float *posj = &mFluidParticles[resc]->Positions[2*(*jc)]; float *velj = &mVelocities[resc][2*(*jc)]; float denj = mDensities[resc][*jc]; float prej = mPressures[resc][*jc]; float dist = computeDistance(pos, posj); float xij[2]; xij[0] = pos[0] - posj[0]; xij[1] = pos[1] - posj[1]; float vij[2]; vij[0] = vel[0] - velj[0]; vij[1] = vel[1] - velj[1]; if (dist < mConfiguration.EffectiveRadius[LOW]) { // compute SPH pressure coefficient float coeff = (pre/(den*den) + prej/(denj*denj)); float vx = computeDotProduct(xij, vij); float h = mConfiguration.EffectiveRadius[res]; float hc = mConfiguration.EffectiveRadius[resc]; if (vx < 0.0f) { // add artificial velocity to the SPH Force coefficient float x2 = dist*dist; float nu = -2.0f*mConfiguration.Alpha*h* mConfiguration.SpeedSound/(den + denj); coeff += nu*vx/(x2 + 0.01f*h*h); } Vector2f grad = evaluateKernelGradient ( Vector2f(xij), dist, h ); Vector2f gradc = evaluateKernelGradient ( Vector2f(xij), dist, hc ); accC[0] += mBlendValues[resc][*jc]*coeff* (grad.X + gradc.X)*0.5f; accC[1] += mBlendValues[resc][*jc]*coeff* (grad.Y + gradc.Y)*0.5f; float wt = evaluateKernel(dist, h); float wct = evaluateKernel(dist, hc); accCT[0] -= mConfiguration.TensionCoefficient*xij[0]* (wt + wct)/2.0f*mBlendValues[resc][*jc]; accCT[1] -= mConfiguration.TensionCoefficient*xij[1]* (wt + wct)/2.0f*mBlendValues[resc][*jc]; float w3 = 1.0f; if (res == HIGH && dist > mConfiguration.EffectiveRadius[HIGH]) { w3 = 0.0f; } float w2 = mConfiguration.FluidParticleMass[res]/ mConfiguration.FluidParticleMass[LOW]; float mw = w3*w2*mexicanHat2D ( xij[0]/mConfiguration.EffectiveRadius[LOW], xij[1]/mConfiguration.EffectiveRadius[LOW] ); ene[0] += velj[0]*mw; ene[1] += velj[1]*mw; psiSum += mw; mStates[res][*i] |= (mStates[res][*jc] << 1) & 0x04; } } //====================================================================== // compute penalty force of the boundary //====================================================================== mBoundaryHashTable->Query(Vector2f(pos)); const IDList& bneighbors = mBoundaryHashTable->GetResult(); IDList::const_iterator k = bneighbors.begin(); IDList::const_iterator ke = bneighbors.end(); for (; k != ke; k++) { float *posk = &mBoundaryParticles->Positions[2*(*k)]; float xik[2]; xik[0] = pos[0] - posk[0]; xik[1] = pos[1] - posk[1]; float dist = computeNorm(xik); if (dist < mConfiguration.EffectiveRadius[LOW]) { float w = evaluateBoundaryWeight ( dist, mConfiguration.EffectiveRadius[LOW], mConfiguration.SpeedSound ); float c = mConfiguration.BoundaryParticleMass/ (mConfiguration.FluidParticleMass[LOW] + mConfiguration.BoundaryParticleMass); float d = c*w; accB[0] += d*xik[0]; accB[1] += d*xik[1]; } } //====================================================================== // Update acceleration of particle i //====================================================================== acc[0] *= -mConfiguration.FluidParticleMass[res]; acc[1] *= -mConfiguration.FluidParticleMass[res]; accC[0] *= -mConfiguration.FluidParticleMass[resc]; accC[1] *= -mConfiguration.FluidParticleMass[resc]; accCT[0] *= (mConfiguration.FluidParticleMass[resc]/ mConfiguration.FluidParticleMass[res]); accCT[1] *= (mConfiguration.FluidParticleMass[resc]/ mConfiguration.FluidParticleMass[res]); acc[0] += accT[0]; acc[1] += accT[1]; acc[0] += accC[0]; acc[1] += accC[1]; acc[0] += accCT[0]; acc[1] += accCT[1]; acc[0] += accB[0]; acc[1] += accB[1]; acc[1] -= 9.81f; float energy = 1.0f/(psiSum*psiSum*mConfiguration.EffectiveRadius[res])* (ene[0]*ene[0] + ene[1]*ene[1]); if (pos[0] > 0.5f) { //mFluidParticles[res]->Colors[*i] = 1.0f; mStates[res][*i] |= 0x08; } else { //mFluidParticles[res]->Colors[*i] = 0.0f; } mFluidParticles[res]->Colors[*i] = std::min ( abs(energy)/200.0f, 1.0f ); // xicm[0] = pos[0] - xicm[0]/mt; // xicm[1] = pos[1] - xicm[1]/mt; // // float col = std::min // ( // computeNorm(xicm), 0.003f // )/0.003f; // // std::cout << col << std::endl; // // mFluidParticles[res]->Colors[*i] = col; } }
//------------------------------------------------------------------------------ void Solver::computeDensity (unsigned char res) { IDList::const_iterator i = mFluidParticles[res]->ActiveIDs.begin(); IDList::const_iterator e = mFluidParticles[res]->ActiveIDs.end(); for (; i != e; i++) { float xicm[2]; xicm[0] = 0.0f; xicm[1] = 0.0f; float mt = 0.0f; //====================================================================== // compute densities in the same domain //====================================================================== float *pos = &mFluidParticles[res]->Positions[2*(*i)]; // get neighbor ids mFluidHashTable[res]->Query(Vector2f(pos)); const IDList& neighbors = mFluidHashTable[res]->GetResult(); // float density = 0.0f; IDList::const_iterator j = neighbors.begin(); IDList::const_iterator je = neighbors.end(); // iterate through neighbors and add up their contribution to // the density of particle i for (; j != je; j++) { float *posj = &mFluidParticles[res]->Positions[2*(*j)]; float posij[2]; posij[0] = pos[0] - posj[0]; posij[1] = pos[1] - posj[1]; float dist = std::sqrt(posij[0]*posij[0] + posij[1]*posij[1]); if (dist < mConfiguration.EffectiveRadius[res]) { density += mBlendValues[res][*j]*evaluateKernel ( dist, mConfiguration.EffectiveRadius[res] ); float mass = mConfiguration.FluidParticleMass[res]; xicm[0] += mass*posj[0]; xicm[1] += mass*posj[1]; mt += mass; } } density *= mConfiguration.FluidParticleMass[res]; //====================================================================== // compute densities in the complementary domain //====================================================================== unsigned char resc = (res + 1) % 2; float densityc = 0.0f; // get neighbor ids // (in the contemp. domain, we always have a search radius of the // low effective radius) mFluidHashTable[resc]->Query ( Vector2f(pos), mConfiguration.EffectiveRadius[LOW] ); const IDList& neighborsc = mFluidHashTable[resc]->GetResult(); IDList::const_iterator jc = neighborsc.begin(); IDList::const_iterator jce = neighborsc.end(); for (; jc != jce; jc++) { float *posjc = &mFluidParticles[resc]->Positions[2*(*jc)]; float posijc[2]; posijc[0] = pos[0] - posjc[0]; posijc[1] = pos[1] - posjc[1]; float distc = std::sqrt(posijc[0]*posijc[0] + posijc[1]*posijc[1]); if (distc < mConfiguration.EffectiveRadius[LOW]) { float w = evaluateKernel ( distc, mConfiguration.EffectiveRadius[res] ); float wc = evaluateKernel ( distc, mConfiguration.EffectiveRadius[resc] ); densityc += mBlendValues[resc][*jc]*0.5f*(w + wc); float mass = mConfiguration.FluidParticleMass[resc]; xicm[0] += mass*posjc[0]; xicm[1] += mass*posjc[1]; mt += mass; } } densityc *= mConfiguration.FluidParticleMass[resc]; //====================================================================== // Update density and pressure of particle i //====================================================================== // add contr. of contemp. domain density += densityc; mDensities[res][*i] = density; float a = density/mConfiguration.RestDensity; float a3 = a*a*a; mPressures[res][*i] = mConfiguration.TaitCoefficient*(a3*a3*a - 1.0f); xicm[0] = pos[0] - xicm[0]/mt; xicm[1] = pos[1] - xicm[1]/mt; //====================================================================== // find out if particle is a surface particle //====================================================================== float col = std::min ( computeNorm(xicm), 0.003f )/0.003f; //std::cout << col << std::endl; mFluidParticles[res]->Colors[*i] = col; if (col >= 1.0f) { mStates[res][*i] |= 0x02; } else { mStates[res][*i] &= 0xF9; // reset surf and nsurf bit } } }
cv::Mat deblurPatch(const cv::Mat &_patch, cv::Point2f one, cv::Point2f two) { ////std::cout << "Start Deblurring" << one << std::endl << two << std::endl; cv::Mat blurredWindow = _patch.clone(); cv::Mat patch = _patch.clone(); patch.convertTo(patch, cv::DataType<double>::type); cv::Mat kernel = evaluateKernel(one,two); // //std::cout << " kernel" << kernel << std::endl; cv::Mat kernel_hat = kernel.clone(), result = patch.clone(); cv::Mat est_conv = result.clone(), relative_blur = patch.clone(), error_est = patch.clone(); cv::Mat patch_hat = patch.clone(), k_est_conv = kernel.clone(), k_relative_blur = kernel.clone(), k_error_est = kernel.clone(); int rows = kernel.rows, cols = kernel.cols, maxIter = 3; int pRows = patch.rows, pCols = patch.cols; cv::Point2f anchor = cv::Point( -1, -1 ); int delta = 0, ddepth = -1; double eps = DBL_MIN; for(int l=0; l<maxIter; l++) { //Improvement for(int i=0; i<pRows; i++) for(int j=0; j<pCols; j++) patch_hat.at<double>(i,j) = patch.at<double>(pRows-i-1,pCols-j-1); filter2D(kernel, k_est_conv, ddepth, patch, anchor, delta, cv::BORDER_DEFAULT); for(int i=0; i<rows; i++) for(int j=0; j<cols; j++) { //if(est_conv.at<double>(i,j) < eps) // est_conv.at<double>(i,j) = 10*eps; k_relative_blur.at<double>(i,j) = kernel.at<double>(i,j) / k_est_conv.at<double>(i,j); } filter2D(k_relative_blur, k_error_est, ddepth, patch_hat); for(int i=0; i<rows; i++) for(int j=0; j<cols; j++) { kernel.at<double>(i,j) = kernel.at<double>(i,j) * k_error_est.at<double>(i,j); } // Classical LR for(int i=0; i<rows; i++) for(int j=0; j<cols; j++) kernel_hat.at<double>(i,j) = kernel.at<double>(rows-i-1,cols-j-1); filter2D(result, est_conv, ddepth, kernel); for(int i=0; i<pRows; i++) for(int j=0; j<pCols; j++) { //if(est_conv.at<double>(i,j) < eps) // est_conv.at<double>(i,j) = 10*eps; relative_blur.at<double>(i,j) = patch.at<double>(i,j) / est_conv.at<double>(i,j); } filter2D(relative_blur, error_est, ddepth, kernel_hat, anchor, delta, cv::BORDER_DEFAULT); for(int i=0; i<pRows; i++) for(int j=0; j<pCols; j++) { result.at<double>(i,j) = result.at<double>(i,j) * error_est.at<double>(i,j); } } result.convertTo(result, CV_8U); hconcat(blurredWindow, result, blurredWindow); imshow("Deblurring", blurredWindow); //std::cout << "Stop Deblurring" << std::endl; return result; }