利用随机函数确定(x,y),以其为中心,选择矩形区域矢量场,进行LIC卷积,得到风场纹理图像,再贴图到地球上。
// LiuLppm.cpp : 定义控制台应用程序的入口点。
//
//#include "stdafx.h"
#include <String>
#include <string.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include "netcdfcpp.h"
#include <cv.h>
#include <ml.h>
#include <highgui.h>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
using namespace std;
using namespace cv;
#define SQUARE_FLOW_FIELD_SZ 400
#define DISCRETE_FILTER_SIZE 2048
#define LOWPASS_FILTR_LENGTH 10.00000f
#define LINE_SQUARE_CLIP_MAX 100000.0f
#define VECTOR_COMPONENT_MIN 0.050000f
#define x_width 70
#define y_height 180
int x_size = x_width;
int y_size = y_height;
void SyntheszSaddle( int x0,int y0, double* pVectr);
void NormalizVectrs(int x_size, int y_size, double* pVectr,float* vecSize);
void GenBoxFiltrLUT(int LUTsiz, float* p_LUT0, float* p_LUT1);
void MakeWhiteNoise(int n_xres, int n_yres, float* pNoise);
void FlowImagingLIC(int n_xres, int n_yres, double* pVectr, float* pNoise,
float* pImage, float* p_LUT0, float* p_LUT1, float krnlen);
void WriteImage2PPM(int n_xres, int n_yres, float* pImage, char* f_name);
void color(int n_xres, int n_yres,float *pImage,float* vecSize);
double maxvecmag;
void main()
{
float m = 0;
float n = 0;
int n_xres = 721;
int n_yres = 281;
double* pVectr = (double* ) malloc( sizeof(double ) * n_xres * n_yres * 2 );
float* p_LUT0 = (float* ) malloc( sizeof(float ) * DISCRETE_FILTER_SIZE);
float* p_LUT1 = (float* ) malloc( sizeof(float ) * DISCRETE_FILTER_SIZE);
float* pNoise = (float* ) malloc( sizeof(float) * n_xres * n_yres );
float* pImage = (float* ) malloc( sizeof(float) * n_xres * n_yres );
float* vecSize = (float* ) malloc( sizeof(float) * n_xres*n_yres );
int x0 = 0;
int y0 = 0;
//首先随进产生视点坐标位置
// x0 = rand()722-x_size/2;
// y0 = rand()%282-y_size/2;
x0 =( 721%rand())*(rand()%30)-x_size/2;
y0 = 281%rand()-y_size/2;
cout<<x0<<endl;
cout<<y0<<endl;
//截取矢量场的某一部分
SyntheszSaddle(x0,y0, pVectr);
NormalizVectrs(x_size,y_size, pVectr,vecSize);
MakeWhiteNoise(x_size, y_size, pNoise);
GenBoxFiltrLUT(DISCRETE_FILTER_SIZE, p_LUT0, p_LUT1);
FlowImagingLIC(x_size,y_size, pVectr, pNoise, pImage, p_LUT0, p_LUT1, LOWPASS_FILTR_LENGTH);
color(x_size,y_size,pImage,vecSize);
//WriteImage2PPM(x_size, y_size, pImage, "LIC.ppm");
free(pVectr); pVectr = NULL;
free(p_LUT0); p_LUT0 = NULL;
free(p_LUT1); p_LUT1 = NULL;
free(pNoise); pNoise = NULL;
free(pImage); pImage = NULL;
}
/// synthesize a saddle-shaped vector field ///
void SyntheszSaddle( int x0,int y0, double* pVectr)
{
// static const int LatNum = 560;
// static const int LonNum =1440;
NcFile dataReadFile("data/global.nc",NcFile::ReadOnly);
if (!dataReadFile.is_valid())
{
std::cout<<"couldn't open file!"<<std::endl;
}
int LonNum=0;
int LatNum=0;
for (int i = 0;i<=dataReadFile.num_dims()-1;i++)
{
// String.Format(String+"dimid=%d, name = %s length=%d/n",dataReadFile.get_dim(i).id(),
// dataReadFile.get_dim(i)->name(),dataReadFile.get_dim(i)->size());
// cout<<"lat="<<dataReadFile.get_dim(i)->name()<<" "<<dataReadFile.get_dim(i)->size()<<endl;
if (i==0)
{
LonNum =dataReadFile.get_dim(i)->size();
}
else if (i==1)
{
LatNum=dataReadFile.get_dim(i)->size();
}
}
// double *lat = new double[LatNum];
// double *lon = new double[LonNum];
//读取Variables变量数据
/*for (int i = 0; i<dataReadFile.num_vars();i++)
{
cout<<dataReadFile.get_var(i)->id()<<" "<<dataReadFile.get_var(i)->name()<<" "<<dataReadFile.get_var(i)->num_dims()<<" "<<endl;
}*/
//定义二维数组
/*float ** temp=new float*[LatNum];
for (int i = 0;i<LatNum;i++)
{
temp[i]=new float[LonNum];
} */
//如何读取二维经纬度交点上的数值*****************************************
// float *rhs=new float[LonNum*LatNum];
// long array[2];
// array[0] = LatNum;
// array[1] = LonNum;
//
// dataReadFile.get_var("june")->get(rhs,array);
//
// for (int i = 0;i<LatNum;i++)
// {
// for (int j=0;j<LonNum;j++)
// {
// dataReadFile.get_var("latitude")->get(lat,LatNum);
// dataReadFile.get_var("longitude")->get(lon,LonNum);
// //cout<<"<"<<lat[i]<<","<<lon[j]<<")"<<rhs[i*LonNum+j]<<endl;
// if (rhs[i*LonNum+j] != -9999)
// {
// cout<<i<<" "<<j<<endl;
// cout<<"<"<<lat[i]<<","<<lon[j]<<")"<<rhs[i*LonNum+j]<<endl;
// }
// }
// }
static const int Time = 1;
static const int TMP = Time*LonNum*LonNum;
double *Tmp_UX = new double[TMP];
double *Tmp_VY = new double[TMP];
double *Tmp_LAT = new double[TMP];
double *Tmp_LON = new double[TMP];
NcVar *dataTmp_LAT = dataReadFile.get_var("LAT");
NcVar *dataTmp_LON = dataReadFile.get_var("LONN359_361");
NcVar *dataTmp_UX = dataReadFile.get_var("UX");
NcVar *dataTmp_VY = dataReadFile.get_var("VY");
dataTmp_LAT->get(Tmp_LAT,LatNum,LatNum);
dataTmp_LON->get(Tmp_LON,LonNum,LonNum);
dataTmp_UX->get(Tmp_UX,Time,LatNum,LonNum);
dataTmp_VY->get(Tmp_VY,Time,LatNum,LonNum);
// for(int j = y0; j < (y0+y_size); j ++)
// for(int i =x0; i < (x0+x_size); i ++)
for (int j = 0;j<y_size;j++)
for(int i = 0;i <x_size;i++)
{
//int index = ( (y0+y_size - 1 - j) * x_size + i ) << 1;
//int index = j*n_yres+i;
int index = (j*x_size+i)<<1;
pVectr[index ] = Tmp_UX[(y0+j)*LonNum+(x0+i)];
pVectr[index +1 ]= Tmp_VY[(y0+j)*LonNum+(x0+i)];
}
}
/// normalize the vector field ///
void NormalizVectrs(int x_size, int y_size, double* pVectr,float* vecSize)
{
for(int j = 0; j < y_size; j ++)
for(int i = 0; i < x_size; i ++)
{
int index = (j * x_size + i) << 1;
float vcMag = float( sqrt( double(pVectr[index] * pVectr[index] + pVectr[index + 1] * pVectr[index + 1]) ) );
vecSize[j * x_size + i]=vcMag;
if (vcMag<100&&vcMag>maxvecmag)
{
maxvecmag=vcMag;
}
float scale = (vcMag == 0.0f) ? 0.0f : 1.0f / vcMag;
pVectr[index ] *= scale*5.5;//????????????????????????????????????????????????????????????原来问题出在这
pVectr[index + 1] *= scale*5.5;
}
}
void color(int n_xres,int n_yres,float *pImage,float* vecSize)
{
IplImage * licImage = cvCreateImage(cvSize(n_xres,n_yres),IPL_DEPTH_8U,3);
IplImage* img = cvLoadImage("11.jpg",1);
int k = 0;
double magind;
double mag;
double newMag;
double x = 0.1;//x为非线性映射因子,且x!=1
CvScalar colorTable[500];
CvScalar s,s1;
for (int i = 0;i < img->width;i++)
{
s = cvGet2D(img,1,i);
colorTable[i] =s;
}
for (int j=0;j<n_yres;j++)
{
for (int i= 0;i<n_xres;i++)
{
if (k>=img->width)
{
k=0;
}
double scale= pImage[j * n_xres + i];
mag = vecSize[j * n_xres + i];
//********矢量大小归一化******
if (mag<100)
{
magind = (mag/maxvecmag);
}
//非线性颜色增强LIC
newMag =(pow(x,magind)-1)/(x-1);
s = cvGet2D(licImage,j,i);
//渐变颜色映射表
int k = int(newMag*446);
s1.val[0]=colorTable[k].val[0]*(k+1-newMag*446)+colorTable[k+1].val[0]*(newMag*446-k);
s1.val[1]=colorTable[k].val[1]*(k+1-newMag*446)+colorTable[k+1].val[1]*(newMag*446-k);
s1.val[2]=colorTable[k].val[2]*(k+1-newMag*446)+colorTable[k+1].val[2]*(newMag*446-k);
s1.val[0]*=scale;
s1.val[1]*=scale;
s1.val[2]*=scale;
/*cout<<"s1.val[3]="<<s1.val[3]<<endl;*/
cvSet2D(licImage,j,i,s1);
}
}
//Mat AlphaImage= imread("s.jpg");
//cv::Mat AlphaImage = imread("licImage",1);
cvNamedWindow("lic_three channles",0);
cvShowImage("lic_three channles",licImage);
cvWaitKey(0);
system("pause");
cvDestroyWindow("lic_three channles");
cvReleaseImage(&licImage);
}/// make white noise as the LIC input texture ///
void MakeWhiteNoise(int n_xres, int n_yres, float* pNoise)
{
for(int j = 0; j < n_yres; j ++)
for(int i = 0; i < n_xres; i ++)
{
int r = rand();
r = ( (r & 0xff) + ( (r & 0xff00) >> 8 ) ) & 0xff;
pNoise[j * n_xres + i] = (unsigned char) r;
}
}
/// generate box filter LUTs ///
void GenBoxFiltrLUT(int LUTsiz, float* p_LUT0, float* p_LUT1)
{
for(int i = 0; i < LUTsiz; i ++) p_LUT0[i] = p_LUT1[i] = i;
}
/// write the LIC image to a PPM file ///
void WriteImage2PPM(int n_xres, int n_yres, float* pImage, char* f_name)
{
FILE* o_file;
if( ( o_file = fopen(f_name, "w") ) == NULL )
{
printf("Can't open output file\n");
return;
}
fprintf(o_file, "P6\n%d %d\n255\n", n_xres, n_yres);
for(int j = 0; j < n_yres; j ++)
for(int i = 0; i < n_xres; i ++)
{
unsigned char unchar = pImage[j * n_xres + i];
fprintf(o_file, "%c%c%c", unchar, unchar, unchar);
}
fclose (o_file); o_file = NULL;
}
/// flow imaging (visualization) through Line Integral Convolution ///
void FlowImagingLIC(int n_xres, int n_yres, double* pVectr, float* pNoise, float* pImage,
float* p_LUT0, float* p_LUT1, float krnlen)
{
int vec_id; ///ID in the VECtor buffer (for the input flow field)
int advDir; ///ADVection DIRection (0: positive; 1: negative)
int advcts; ///number of ADVeCTion stepS per direction (a step counter)
int ADVCTS = int(krnlen * 3); ///MAXIMUM number of advection steps per direction to break dead loops //跳出死循环的条件
float vctr_x; ///x-component of the Vector at the forefront point
float vctr_y; ///y-component of the Vector at the forefront point
float clp0_x; ///x-coordinate of CLiP point 0 (current)
float clp0_y; ///y-coordinate of CLiP point 0 (current)
float clp1_x; ///x-coordinate of CLiP point 1 (next )
float clp1_y; ///y-coordinate of CLiP point 1 (next )
float samp_x; ///x-coordinate of the Sample in the current pixel
float samp_y; ///y-coordinate of the Sample in the current pixel
float tmpLen; ///Temporary Length of a trial clipped-segment实验剪辑片段的临时长度
float segLen; ///Segment Length
float curLen; ///Current Length of the streamline
float prvLen; ///Previous Length of the streamline
float W_ACUM; ///Accumulated Weight from the seed to the current streamline forefront
float texVal; ///Texture Value
float smpWgt; ///Weight of the current Sample
float t_acum[2]; ///two Accumulated composite Textures for the two directions, perspectively 两个方向的纹理卷积累加和
float w_acum[2]; ///two Accumulated Weighting values for the two directions, perspectively 两个方向的权重和
float* wgtLUT = NULL; ///WeiGhT Look Up Table pointing to the target filter LUT权重查找表
float len2ID = (DISCRETE_FILTER_SIZE - 1) / krnlen; ///map a curve Length To an ID in the LUT
double scale;//颜色映射表比例
double maxmag;
double magind;
double mag;
double x = 0.1;//x为非线性映射因子,且x!=1
IplImage * licImage = cvCreateImage(cvSize(y_size,x_size),IPL_DEPTH_8U,3);
CvScalar s;
///for each pixel in the 2D output LIC image///对输出图像的每一个像素
for(int j = 0; j < y_size; j ++)
{
for(int i = 0; i < x_size; i ++)
{
///init the composite texture accumulators and the weight accumulators///每一个像素点为起始点,初始化一次权重和卷积和
t_acum[0] = t_acum[1] = w_acum[0] = w_acum[1] = 0.0f;//初始化正反方向卷积和及权重和
///for either advection direction///分别计算正反方向的卷积和及权重和
for(advDir = 0; advDir < 2; advDir ++)
{
///init the step counter, curve-length measurer, and streamline seed///
//初始化当前方向上前进的步数和当前流线的总长
advcts = 0;//前进的步数
curLen = 0.0f;
clp0_x = i + 0.5f;//当前点的坐标
clp0_y = j + 0.5f;
///access the target filter LUT///LUT显示查找表
wgtLUT = (advDir == 0) ? p_LUT0 : p_LUT1;//当前噪声点所对应的权重系数
///until the streamline is advected long enough or a tightly spiralling center / focus is encountered///
while( curLen < krnlen && advcts < ADVCTS ) //??????
{
///access the vector at the sample///
vec_id = ( int(clp0_y) * x_size + int(clp0_x) ) << 1;//vec_id相当于index
vctr_x = pVectr[vec_id ];//clp0_y相当于当前像素列坐标,clp0_x相当于当前像素的横坐标
vctr_y = pVectr[vec_id + 1];
///in case of a critical point///遇到零向量,结束循环
if( vctr_x == 0.0f && vctr_y == 0.0f )
{
t_acum[advDir] = (advcts == 0) ? 0.0f : t_acum[advDir]; ///this line is indeed unnecessary
w_acum[advDir] = (advcts == 0) ? 1.0f : w_acum[advDir];
break;
}
///negate the vector for the backward-advection case///相反的方向取相反的方向
vctr_x = (advDir == 0) ? vctr_x : -vctr_x;//因为矢量是用x,y方向的值合成的,所以反向的值就是负的
vctr_y = (advDir == 0) ? vctr_y : -vctr_y;
//这儿可以就计算矢量大小、归一化运算????????????前面已经归一化了
//。。。。。。//
// mag= sqrt(vctr_x*vctr_x+vctr_y*vctr_y);
// if (mag>maxmag)
// {
// maxmag=mag;
// }
///clip the segment against the pixel boundaries --- find the shorter from the two clipped segments///
///replace all if-statements whenever possible as they might affect the computational speed///影响算法计算速度
segLen = LINE_SQUARE_CLIP_MAX;
segLen = (vctr_x < -VECTOR_COMPONENT_MIN) ? ( int( clp0_x ) - clp0_x ) / vctr_x : segLen;//int(0.5)=0
segLen = (vctr_x > VECTOR_COMPONENT_MIN) ? ( int( int(clp0_x) + 1.5f ) - clp0_x ) / vctr_x : segLen;
segLen = (vctr_y < -VECTOR_COMPONENT_MIN) ?
( ( ( tmpLen = ( int( clp0_y) - clp0_y ) / vctr_y ) < segLen ) ? tmpLen : segLen )
: segLen;
segLen = (vctr_y > VECTOR_COMPONENT_MIN) ?
( ( ( tmpLen = ( int( int(clp0_y) + 1.5f ) - clp0_y ) / vctr_y ) < segLen ) ? tmpLen : segLen )
: segLen;
///update the curve-length measurers///
prvLen = curLen;
curLen+= segLen;//segLen是单步步长
segLen+= 0.00001f;//步长???
// segLen+= 0.0001f;//步长???
///check if the filter has reached either end///
segLen = (curLen > krnlen) ? ( (curLen = krnlen) - prvLen ) : segLen;
///obtain the next clip point///
clp1_x = clp0_x + vctr_x * segLen;
clp1_y = clp0_y + vctr_y * segLen;
///obtain the middle point of the segment as the texture-contributing sample///
samp_x = (clp0_x + clp1_x) * 0.5f;
samp_y = (clp0_y + clp1_y) * 0.5f;
///obtain the texture value of the sample///
texVal = pNoise[ int(samp_y) * x_size + int(samp_x) ];
///update the accumulated weight and the accumulated composite texture (texture x weight)///
W_ACUM = wgtLUT[ int(curLen * len2ID) ];
smpWgt = W_ACUM - w_acum[advDir];
w_acum[advDir] = W_ACUM;
t_acum[advDir] += texVal * smpWgt;//当前噪声点的权重系数
///update the step counter and the "current" clip point///
advcts ++;
clp0_x = clp1_x;
clp0_y = clp1_y;
///check if the streamline has gone beyond the flow field///
if( clp0_x < 0.0f || clp0_x >= x_size || clp0_y < 0.0f || clp0_y >= y_size) break;
}
}
///normalize the accumulated composite texture///
texVal = (t_acum[0] + t_acum[1]) / (w_acum[0] + w_acum[1]);
//cout<<t_acum[0] + t_acum[1]<<endl;
///clamp the texture value against the displayable intensity range [0, 255]
texVal = (texVal < 0.0f) ? 0.0f : texVal/255;
texVal = (texVal > 255.0f) ? 255.0f : texVal;
pImage[j * x_size + i] = (float) texVal;
//cout<<pImage[j * x_size + i]<<endl;
}
}
}