void makeWaveMap(Mat& image) { float simulPeriod = 10.0; // Period of simulation static float time = 0.0; const float dt = 0.05; // Time step float poolDepth = 20.0; int maxImageSize = image.cols > image.rows ? image.cols : image.rows; for (int i = 0; i < image.rows; i++) { for (int j = 0; j < image.cols; j++) { float radius = sqrt((i - image.rows/2)*(i - image.rows/2) + \ (j - image.cols/2)*(j - image.cols/2)); float z = (1.0 + waveFunction(radius, time, maxImageSize))*poolDepth; image.at<uchar>(i, j) = saturate_cast<uchar>(z); } } time+= dt; time*= (time < simulPeriod); }
void makeWaveMapLUT(Mat& image) { float simulPeriod = 10.0; // Period of simulation static float time = 0.0; const float dt = 0.05; // Time step float poolDepth = 20.0; int nLUT = image.cols > image.rows ? image.cols : image.rows; int maxImageSize = nLUT; float waveFuncLUT[nLUT]; for (int i = 0; i < nLUT; i++) { float radius = saturate_cast<float>(i); waveFuncLUT[i] = waveFunction(radius, time, maxImageSize); } for (int i = 0; i < image.rows; i++) { for (int j = 0; j < image.cols; j++) { float radius = sqrt((i - image.rows/2)*(i - image.rows/2) + \ (j - image.cols/2)*(j - image.cols/2)); int iRad = cvRound(radius); float dR = radius - saturate_cast<float>(iRad); float wF = waveFuncLUT[iRad] + (waveFuncLUT[iRad+1] - waveFuncLUT[iRad])*dR; float z = (1.0 + wF)*poolDepth; image.at<uchar>(i, j) = saturate_cast<uchar>(z); } } time+= dt; time*= (time < simulPeriod); }
void blendWaveAndImage(Mat& sourceImage, Mat& targetImage, Mat& waveMap) { static float rFactor = 1.33; // refraction factor of water for (int i = 1; i < sourceImage.rows-1; i++) { for (int j = 1; j < sourceImage.cols-1; j++) { float alpha, beta; float xDiff = waveMap.at<uchar>(i+1, j) - waveMap.at<uchar>(i, j); float yDiff = waveMap.at<uchar>(i, j+1) - waveMap.at<uchar>(i, j); alpha = atan(xDiff); beta = asin(sin(alpha)/rFactor); int xDisplace = cvRound(tan(alpha - beta)*waveMap.at<uchar>(i, j)); alpha = atan(yDiff); beta = asin(sin(alpha)/rFactor); int yDisplace = cvRound(tan(alpha - beta)*waveMap.at<uchar>(i, j)); Vec3b Intensity = sourceImage.at<Vec3b>(i,j); /* Check whether displacement fits the image size */ int dispNi = i + xDisplace; int dispNj = j + yDisplace; dispNi = (dispNi > sourceImage.rows || dispNi < 0 ? i : dispNi); dispNj = (dispNj > sourceImage.cols || dispNj < 0 ? j : dispNj); Intensity = sourceImage.at<Vec3b>(dispNi, dispNj); targetImage.at<Vec3b>(i,j) = Intensity; } } }
void blendWaveAndImageLUT(Mat& sourceImage, Mat& targetImage, Mat& waveMap) { static float rFactor = 1.33; // refraction factor of water static float dispLUT[512]; //Lookup table for displacement static int nDispPoint = 512; for (int i = 0; i < nDispPoint; i++) { float diff = saturate_cast<float>(i - 255); float alpha = atan(diff); float beta = asin(sin(alpha)/rFactor); dispLUT[i] = tan(alpha - beta); } nDispPoint = 0; for (int i = 1; i < sourceImage.rows-1; i++) { for (int j = 1; j < sourceImage.cols-1; j++) { int xDiff = waveMap.at<uchar>(i+1, j) - waveMap.at<uchar>(i, j); int yDiff = waveMap.at<uchar>(i, j+1) - waveMap.at<uchar>(i, j); int xDisplace = cvRound(dispLUT[xDiff+255]*waveMap.at<uchar>(i, j)); int yDisplace = cvRound(dispLUT[yDiff+255]*waveMap.at<uchar>(i, j)); Vec3b Intensity = sourceImage.at<Vec3b>(i,j); /* Check whether displacement fits the image size */ int dispNi = i + xDisplace; int dispNj = j + yDisplace; dispNi = (dispNi > sourceImage.rows || dispNi < 0 ? i : dispNi); dispNj = (dispNj > sourceImage.cols || dispNj < 0 ? j : dispNj); Intensity = sourceImage.at<Vec3b>(dispNi, dispNj); targetImage.at<Vec3b>(i,j) = Intensity; } } }
Source: https://habr.com/ru/post/261477/