Exemplo n.º 1
0
Particle::Particle()
{//initialize the posistion and velocity
    std::uniform_real_distribution<double> wdist(-(width/2.0f),(width/2.0f));
    std::uniform_real_distribution<double> hdist(-(height/2.0f),(height/2.0f));
    
    xbest = xpos = wdist(rng);
    ybest = ypos = hdist(rng);
    xvel = yvel = 0.0f;
}
Exemplo n.º 2
0
QColor TracksItem::generateColor() {
    static std::random_device rd;
    std::default_random_engine re(rd());
    std::uniform_real_distribution<qreal> hdist(0, 1);
    std::normal_distribution<qreal> sdist(1/3.0, 1/24.0);
    std::normal_distribution<qreal> ldist(0.5, 1/12.0);
    qreal h = hdist(re);
    qreal s = std::max<qreal>(std::min<qreal>(sdist(re), 5.0/24), 11.0/24);
    qreal l = std::max<qreal>(std::min<qreal>(ldist(re), 0.75), 0.25);
    return QColor::fromHslF(h, s, l).toRgb();
}
Exemplo n.º 3
0
 /*!
  *  \brief  hyperbolic translation transformation generator between two conformal points
  */
 Pair hgen(const Pnt& pa, const Pnt& pb, double amt){
   double dist = hdist(pa,pb);         //<-- h distance
   auto hline = pa ^ pb ^ EP;          //<-- h line (circle)
   auto par_versor = (EP <= hline).runit();      //<-- h trans generator (pair)
  // par_versor /= par_versor.rnorm();   //<-- normalized ...
   return par_versor * dist * amt * .5;//<-- and ready to be applied
 }
Exemplo n.º 4
0
void LBSP::calcDescImgDiff(const cv::Mat& oDesc1, const cv::Mat& oDesc2, cv::Mat& oOutput, bool bForceMergeChannels) {
    CV_DbgAssert(oDesc1.size()==oDesc2.size() && oDesc1.type()==oDesc2.type());
    CV_DbgAssert(DESC_SIZE==2); // @@@ also relies on a constant desc size
    CV_DbgAssert(oDesc1.type()==CV_16UC1 || oDesc1.type()==CV_16UC3);
    CV_DbgAssert(CV_MAT_DEPTH(oDesc1.type())==CV_16U);
    CV_DbgAssert(DESC_SIZE*8<=UCHAR_MAX);
    CV_DbgAssert(oDesc1.step.p[0]==oDesc2.step.p[0] && oDesc1.step.p[1]==oDesc2.step.p[1]);
    const float fScaleFactor = (float)UCHAR_MAX/(DESC_SIZE*8);
    const size_t nChannels = CV_MAT_CN(oDesc1.type());
    const size_t _step_row = oDesc1.step.p[0];
    if(nChannels==1) {
        oOutput.create(oDesc1.size(),CV_8UC1);
        oOutput = cv::Scalar(0);
        for(int i=0; i<oDesc1.rows; ++i) {
            const size_t idx = _step_row*i;
            const ushort* const desc1_ptr = (ushort*)(oDesc1.data+idx);
            const ushort* const desc2_ptr = (ushort*)(oDesc2.data+idx);
            for(int j=0; j<oDesc1.cols; ++j)
                oOutput.at<uchar>(i,j) = (uchar)(fScaleFactor*hdist(desc1_ptr[j],desc2_ptr[j]));
        }
    }
    else { //nChannels==3
        if(bForceMergeChannels)
            oOutput.create(oDesc1.size(),CV_8UC1);
        else
            oOutput.create(oDesc1.size(),CV_8UC3);
        oOutput = cv::Scalar::all(0);
        for(int i=0; i<oDesc1.rows; ++i) {
            const size_t idx =  _step_row*i;
            const ushort* const desc1_ptr = (ushort*)(oDesc1.data+idx);
            const ushort* const desc2_ptr = (ushort*)(oDesc2.data+idx);
            uchar* output_ptr = oOutput.data + oOutput.step.p[0]*i;
            for(int j=0; j<oDesc1.cols; ++j) {
                for(size_t n=0;n<3; ++n) {
                    const size_t idx2 = 3*j+n;
                    if(bForceMergeChannels)
                        output_ptr[j] += (uchar)((fScaleFactor*hdist(desc1_ptr[idx2],desc2_ptr[idx2]))/3);
                    else
                        output_ptr[idx2] = (uchar)(fScaleFactor*hdist(desc1_ptr[idx2],desc2_ptr[idx2]));
                }
            }
        }
    }
}
Exemplo n.º 5
0
static void on_highlight_char(fz_context *ctx, void *arg, fz_stext_line *line, fz_stext_char *ch)
{
	struct highlight *hits = arg;
	float vfuzz = ch->size * hits->vfuzz;
	float hfuzz = ch->size * hits->hfuzz;

	if (hits->len > 0)
	{
		fz_quad *end = &hits->box[hits->len-1];
		if (hdist(&line->dir, &end->lr, &ch->quad.ll) < hfuzz
			&& vdist(&line->dir, &end->lr, &ch->quad.ll) < vfuzz
			&& hdist(&line->dir, &end->ur, &ch->quad.ul) < hfuzz
			&& vdist(&line->dir, &end->ur, &ch->quad.ul) < vfuzz)
		{
			end->ur = ch->quad.ur;
			end->lr = ch->quad.lr;
			return;
		}
	}

	if (hits->len < hits->cap)
		hits->box[hits->len++] = ch->quad;
}
void BackgroundSubtractorLOBSTER::operator()(cv::InputArray _image, cv::OutputArray _fgmask, double learningRate) {
	CV_Assert(m_bInitialized);
	CV_Assert(learningRate>0);
	cv::Mat oInputImg = _image.getMat();
	CV_Assert(oInputImg.type()==m_nImgType && oInputImg.size()==m_oImgSize);
	CV_Assert(oInputImg.isContinuous());
	_fgmask.create(m_oImgSize,CV_8UC1);
	cv::Mat oCurrFGMask = _fgmask.getMat();
	oCurrFGMask = cv::Scalar_<uchar>(0);
	const size_t nLearningRate = (size_t)ceil(learningRate);
	if(m_nImgChannels==1) {
		for(size_t nModelIter=0; nModelIter<m_nTotRelevantPxCount; ++nModelIter) {
			const size_t nPxIter = m_aPxIdxLUT[nModelIter];
			const size_t nDescIter = nPxIter*2;
			const int nCurrImgCoord_X = m_aPxInfoLUT[nPxIter].nImgCoord_X;
			const int nCurrImgCoord_Y = m_aPxInfoLUT[nPxIter].nImgCoord_Y;
			const uchar nCurrColor = oInputImg.data[nPxIter];
			size_t nGoodSamplesCount=0, nModelIdx=0;
			ushort nCurrInputDesc;
			while(nGoodSamplesCount<m_nRequiredBGSamples && nModelIdx<m_nBGSamples) {
				const uchar nBGColor = m_voBGColorSamples[nModelIdx].data[nPxIter];
				{
					const size_t nColorDist = L1dist(nCurrColor,nBGColor);
					if(nColorDist>m_nColorDistThreshold/2)
						goto failedcheck1ch;
					LBSP::computeGrayscaleDescriptor(oInputImg,nBGColor,nCurrImgCoord_X,nCurrImgCoord_Y,m_anLBSPThreshold_8bitLUT[nBGColor],nCurrInputDesc);
					const size_t nDescDist = hdist(nCurrInputDesc,*((ushort*)(m_voBGDescSamples[nModelIdx].data+nDescIter)));
					if(nDescDist>m_nDescDistThreshold)
						goto failedcheck1ch;
					nGoodSamplesCount++;
				}
				failedcheck1ch:
				nModelIdx++;
			}
			if(nGoodSamplesCount<m_nRequiredBGSamples)
				oCurrFGMask.data[nPxIter] = UCHAR_MAX;
			else {
				if((rand()%nLearningRate)==0) {
					const size_t nSampleModelIdx = rand()%m_nBGSamples;
					ushort& nRandInputDesc = *((ushort*)(m_voBGDescSamples[nSampleModelIdx].data+nDescIter));
					LBSP::computeGrayscaleDescriptor(oInputImg,nCurrColor,nCurrImgCoord_X,nCurrImgCoord_Y,m_anLBSPThreshold_8bitLUT[nCurrColor],nRandInputDesc);
					m_voBGColorSamples[nSampleModelIdx].data[nPxIter] = nCurrColor;
				}
				if((rand()%nLearningRate)==0) {
					int nSampleImgCoord_Y, nSampleImgCoord_X;
					getRandNeighborPosition_3x3(nSampleImgCoord_X,nSampleImgCoord_Y,nCurrImgCoord_X,nCurrImgCoord_Y,LBSP::PATCH_SIZE/2,m_oImgSize);
					const size_t nSampleModelIdx = rand()%m_nBGSamples;
					ushort& nRandInputDesc = m_voBGDescSamples[nSampleModelIdx].at<ushort>(nSampleImgCoord_Y,nSampleImgCoord_X);
					LBSP::computeGrayscaleDescriptor(oInputImg,nCurrColor,nCurrImgCoord_X,nCurrImgCoord_Y,m_anLBSPThreshold_8bitLUT[nCurrColor],nRandInputDesc);
					m_voBGColorSamples[nSampleModelIdx].at<uchar>(nSampleImgCoord_Y,nSampleImgCoord_X) = nCurrColor;
				}
			}
		}
	}
	else { //m_nImgChannels==3
		const size_t nCurrDescDistThreshold = m_nDescDistThreshold*3;
		const size_t nCurrColorDistThreshold = m_nColorDistThreshold*3;
		const size_t nCurrSCDescDistThreshold = nCurrDescDistThreshold/2;
		const size_t nCurrSCColorDistThreshold = nCurrColorDistThreshold/2;
		const size_t desc_row_step = m_voBGDescSamples[0].step.p[0];
		const size_t img_row_step = m_voBGColorSamples[0].step.p[0];
		for(size_t nModelIter=0; nModelIter<m_nTotRelevantPxCount; ++nModelIter) {
			const size_t nPxIter = m_aPxIdxLUT[nModelIter];
			const int nCurrImgCoord_X = m_aPxInfoLUT[nPxIter].nImgCoord_X;
			const int nCurrImgCoord_Y = m_aPxInfoLUT[nPxIter].nImgCoord_Y;
			const size_t nPxIterRGB = nPxIter*3;
			const size_t nDescIterRGB = nPxIterRGB*2;
			const uchar* const anCurrColor = oInputImg.data+nPxIterRGB;
			size_t nGoodSamplesCount=0, nModelIdx=0;
			ushort anCurrInputDesc[3];
			while(nGoodSamplesCount<m_nRequiredBGSamples && nModelIdx<m_nBGSamples) {
				const ushort* const anBGDesc = (ushort*)(m_voBGDescSamples[nModelIdx].data+nDescIterRGB);
				const uchar* const anBGColor = m_voBGColorSamples[nModelIdx].data+nPxIterRGB;
				size_t nTotColorDist = 0;
				size_t nTotDescDist = 0;
				for(size_t c=0;c<3; ++c) {
					const size_t nColorDist = L1dist(anCurrColor[c],anBGColor[c]);
					if(nColorDist>nCurrSCColorDistThreshold)
						goto failedcheck3ch;
					LBSP::computeSingleRGBDescriptor(oInputImg,anBGColor[c],nCurrImgCoord_X,nCurrImgCoord_Y,c,m_anLBSPThreshold_8bitLUT[anBGColor[c]],anCurrInputDesc[c]);
					const size_t nDescDist = hdist(anCurrInputDesc[c],anBGDesc[c]);
					if(nDescDist>nCurrSCDescDistThreshold)
						goto failedcheck3ch;
					nTotColorDist += nColorDist;
					nTotDescDist += nDescDist;
				}
				if(nTotDescDist<=nCurrDescDistThreshold && nTotColorDist<=nCurrColorDistThreshold)
					nGoodSamplesCount++;
				failedcheck3ch:
				nModelIdx++;
			}
			if(nGoodSamplesCount<m_nRequiredBGSamples)
				oCurrFGMask.data[nPxIter] = UCHAR_MAX;
			else {
				if((rand()%nLearningRate)==0) {
					const size_t nSampleModelIdx = rand()%m_nBGSamples;
					ushort* anRandInputDesc = ((ushort*)(m_voBGDescSamples[nSampleModelIdx].data+nDescIterRGB));
					const size_t anCurrIntraLBSPThresholds[3] = {m_anLBSPThreshold_8bitLUT[anCurrColor[0]],m_anLBSPThreshold_8bitLUT[anCurrColor[1]],m_anLBSPThreshold_8bitLUT[anCurrColor[2]]};
					LBSP::computeRGBDescriptor(oInputImg,anCurrColor,nCurrImgCoord_X,nCurrImgCoord_Y,anCurrIntraLBSPThresholds,anRandInputDesc);
					for(size_t c=0; c<3; ++c)
						*(m_voBGColorSamples[nSampleModelIdx].data+nPxIterRGB+c) = anCurrColor[c];
				}
				if((rand()%nLearningRate)==0) {
					int nSampleImgCoord_Y, nSampleImgCoord_X;
					getRandNeighborPosition_3x3(nSampleImgCoord_X,nSampleImgCoord_Y,nCurrImgCoord_X,nCurrImgCoord_Y,LBSP::PATCH_SIZE/2,m_oImgSize);
					const size_t nSampleModelIdx = rand()%m_nBGSamples;
					ushort* anRandInputDesc = ((ushort*)(m_voBGDescSamples[nSampleModelIdx].data + desc_row_step*nSampleImgCoord_Y + 6*nSampleImgCoord_X));
					const size_t anCurrIntraLBSPThresholds[3] = {m_anLBSPThreshold_8bitLUT[anCurrColor[0]],m_anLBSPThreshold_8bitLUT[anCurrColor[1]],m_anLBSPThreshold_8bitLUT[anCurrColor[2]]};
					LBSP::computeRGBDescriptor(oInputImg,anCurrColor,nCurrImgCoord_X,nCurrImgCoord_Y,anCurrIntraLBSPThresholds,anRandInputDesc);
					for(size_t c=0; c<3; ++c)
						*(m_voBGColorSamples[nSampleModelIdx].data + img_row_step*nSampleImgCoord_Y + 3*nSampleImgCoord_X + c) = anCurrColor[c];
				}
			}
		}
	}
	cv::medianBlur(oCurrFGMask,m_oLastFGMask,m_nDefaultMedianBlurKernelSize);
	m_oLastFGMask.copyTo(oCurrFGMask);
}
Exemplo n.º 7
0
// Veh_Integral
void Vehicle::Update()
{
   double wind_dir, hdng, rand_wind=0.0;
	double headrot[4];
	double senspostang[2], vehsenspos[2];
   double chemDensity;
   Point3D vpos;
	double u_wind[3];
	int    i_v,iii,jjj, j;
	static int detect_yet;
   double Sim_Time;
   
   if(ed == NULL) return; // if no enviromental data then return
   Sim_Time = ed->GetSimTime();

   // save last pos
   GetPos(last_p);

	// Simulate the batch of vehicles
    for(i_v = 0; i_v < NUM_VEH; i_v++)
    {
      if(!(veh[i_v].src_fnd_flg))  // if not done
      {
         // following are the lines where the vehicle simulation interfaces
         // with the wind and concentration sensor models.  The wind speed
         // and concentration can be evaluated at any position of interest

         hdng = veh[i_v].omega;
         headrot[0] = cos(hdng);
         headrot[1] = -sin(hdng);
         headrot[2] = sin(hdng);
         headrot[3] = cos(hdng);

         double sensposbody[2];
         for(j = 0; j < NUM_SENS; j++)
         {
            sensposbody[0] = 0;
            sensposbody[1] = 0; // (-ns+j)*lngth/ns;
            m_mul(senspostang, headrot, sensposbody, 2, 2, 1);
            m_add(vehsenspos, &(veh[i_v].x), senspostang, 2, 1);
            
            
            //veh[i_v].snsd[j] = chem->ReadConc(vehsenspos, u_wind);
            {
               vpos.x = vehsenspos[0];
               vpos.y = vehsenspos[1];
               vpos.z = 0.0; // vehsenspos[2]
               ed->ApplyWind(vpos, u_wind);
               chemDensity = ed->GetChemDensity(vpos);
               
               veh[i_v].snsd[j] = chemDensity; 
               vehsenspos[0] = vpos.x;
               vehsenspos[1] = vpos.y;
               //vehsenspos[2] = vpos.z;
            }
         }

         if (i_v==0) rand_wind = 5.0*nrand();
         wind_dir = atan2(u_wind[1],u_wind[0])*180/PI + rand_wind;

         // following is the call to the strategy
         strat->in[0] = veh[i_v].x;
         strat->in[1] = (-1)*veh[i_v].y; // invert because of axis flip
         strat->in[2] = sqrt(u_wind[0]*u_wind[0] + u_wind[1]*u_wind[1]);
         strat->in[3] = wind_dir;
         strat->in[4] = Sim_Time;
         strat->in[5] = veh[i_v].u;
         strat->in[6] = veh[i_v].omega;

         // added by JES. copy global to fit older code
         double src_loc[2];
         src_loc[0] = srcloc.x;
         src_loc[1] = srcloc.y;
         //

         for(j = 7; j < 7 + NUM_SENS; j++)
         {
            strat->in[j] = veh[i_v].snsd[j-7];
         }

         strat->out[0]= veh[i_v].vel_c;       // Initialize output values
         strat->out[1]= veh[i_v].omega_c;     // Initialize output values
         strat->out[2]= veh[i_v].src_fnd_flg; // Initialize output values

         //-------------------------Call Strategy----------------------------------------------
         MyStratFunc(strat->in, 
			            strat->out, 
					      &(strat->mem[N_STRAT_MEM*i_v]), 
                     dt, 
                     radius, 
                     threshold,
                     Sim_Time,
                     currentBehaviorName
                    );
         //-------------------------Return from strategy----------------------------------------------

         veh[i_v].vel_c   = strat->out[0];
         veh[i_v].omega_c = strat->out[1];

         // The source found flag once set is set for the run
         veh[i_v].src_fnd_flg   =  ((strat->out[2])||(veh[i_v].src_fnd_flg));

         x_left=0.0;
         y_top=-50;
         d_x=1;
         d_y=1;

         if( veh[i_v].snsd[0] > threshold)
         {
            veh[i_v].det_tm = Sim_Time;         // store most recent detection time

            if(veh[i_v].plm_find_tm > Sim_Time)
               veh[i_v].plm_find_tm = Sim_Time;   // record time of first detection
         }

         if( ( hdist(&(veh[i_v].x), src_loc) < radius) && // near the source
             ( veh[i_v].src_find_tm > Sim_Time) )         // for the first time
         {
            veh[i_v].src_find_tm = Sim_Time; // store the frst tm near src
            fnd_cnt++;
         }   // if near source

         if( (veh[i_v].src_fnd_flg) &&
             (veh[i_v].src_dclr_tm > Sim_Time) )
         {
            // Graphics --------------------------------------------
            if( (batch_not == 1) &&
                (i_v ==0 ) )
            {
               for(iii = 0; iii < GRID_X; iii++)
               {
                  for(jjj = 0; jjj < GRID_Y; jjj++) 
                  {
                     bck_grnd[iii][jjj] = (float)(strat->mem[1000+iii*100+jjj]);
                  }
               }

               // RESET!
               veh[i_v].x = vehicle_pos_x; // ((double)random(100))*(x_max-x_min)/100.0 + x_min;
               veh[i_v].y = vehicle_pos_y; // ((double)random(100))*(y_max-y_min)/100.0 + y_min;
               veh[i_v].z = vehicle_pos_z; // ((double)random(100))*(z_max-z_min)/100.0 + z_min;
               veh[i_v].omega_c = nrand()*180.0;
               veh[i_v].dsd = 0.0;
               veh[i_v].dsf = 0.0;
               veh[i_v].dpf = 0.0;
               veh[i_v].det_tm = -100;
               veh[i_v].plm_find_tm = 1e8;
               veh[i_v].src_find_tm = 1e8;
               veh[i_v].src_dclr_tm = 1e8;
               veh[i_v].src_dclr_d  = 0.0;
               veh[i_v].snsd[NS + 1] = 0;  
               veh[i_v].src_fnd_flg = 0;

               
            }
            // --------------------------------------------
            else
            {
               veh[i_v].src_dclr_tm = Sim_Time;  // store tm of first src found flag
               veh[i_v].src_dclr_d = hdist(&(veh[i_v].x), src_loc);
               veh[i_v].x_real=veh[i_v].x;
               veh[i_v].y_real=veh[i_v].y;
               veh[i_v].vel_c  = 0;            // stop this vehicle
               done_cnt++;                     // veh is done
            }

         }  //  if src fnd flag

         vehicle_model(&(veh[i_v]), Sim_Time);        // advance vehicle to next time

         //Graphics --------------------------------------------
         if((batch_not==1)&&(i_v==0))
         {  // Have we detected anything this interval

            detect_yet = ( (veh[i_v].snsd[0] > threshold) || (detect_yet) );
            veh_plot_cnt++;  // track interval

            if(veh_plot_cnt >= VEH_MAX_PLT_CNT)
            {
               veh_plot_cnt = 0;

               if(vh_count < VH_M)
               {
                  det_flag[vh_count] 		 = detect_yet;
                  detect_yet 			   	 = 0;
                  veh_omega_flag[vh_count] = veh[0].omega*PI/180.0;
                  vh_x[vh_count] 			 = veh[0].x;
                  vh_y[vh_count] 			 = veh[0].y;
                  vh_count++;
               }
               else
               {
                  vehicle_update();
                  det_flag[VH_M-1] 			= detect_yet;
                  detect_yet 					= 0;
                  veh_omega_flag[VH_M-1]	= veh[0].omega*PI/180.0;
                  vh_x[VH_M-1] 				= veh[0].x;
                  vh_y[VH_M-1] 				= veh[0].y;
               }

            } // veh_plot_cnt
         }   // not batch
         // --------------------------------------------

      }   // if not vehicle done
   }   // for each vehicle

   init_flag = 0;
}
Exemplo n.º 8
0
/**
 * Program entry-point.
 *
 */
int main(int argc, char **argv) {
    // parse arguments
    while (true) {
        int index = -1;

        getopt_long(argc, argv, "", options, &index);
        if (index == -1) {
            if (argc != optind + 2) {
                usage();
                return 1;
            }

            input_file = argv[optind++];
            if (access(input_file, R_OK)) {
                fprintf(stderr, "Error: input file not readable: %s\n", input_file);
                return 2;
            }

            output_file = argv[optind++];
            if (access(output_file, W_OK) && errno == EACCES) {
                fprintf(stderr, "Error: output file not writable: %s\n", output_file);
                return 2;
            }
            break;
        }

        switch (index) {
        case OPTION_WIDTH:
            sample_width = atoi(optarg);
            break;
        case OPTION_HEIGHT:
            sample_height = atoi(optarg);
            break;
        case OPTION_COUNT:
            sample_count = atoi(optarg);
            break;

        case OPTION_ROTATE_STDDEV_X:
            rotate_stddev_x = atof(optarg) / 180.0 * M_PI;
            break;
        case OPTION_ROTATE_STDDEV_Y:
            rotate_stddev_y = atof(optarg) / 180.0 * M_PI;
            break;
        case OPTION_ROTATE_STDDEV_Z:
            rotate_stddev_z = atof(optarg) / 180.0 * M_PI;
            break;

        case OPTION_LUMINOSITY_STDDEV:
            luminosity_stddev = atof(optarg);
            break;

        case OPTION_BACKGROUNDS:
            backgrounds_file = optarg;
            if (access(backgrounds_file, R_OK)) {
                fprintf(stderr, "Error: backgrounds file not readable: %s\n", backgrounds_file);
                return 2;
            }
            break;

        default:
            usage();
            return 1;
        }
    }

    // read input files
    std::vector<std::string> samples;

    if (!parseFiles(input_file, samples)) {
        fprintf(stderr, "Error: cannot parse file listing: %s\n", input_file);
        return 2;
    }

    // read background files
    std::vector<std::string> backgrounds;

    if (backgrounds_file != NULL && !parseFiles(backgrounds_file, backgrounds)) {
        fprintf(stderr, "Error: cannot parse file listing: %s\n", backgrounds_file);
        return 2;
    }

    // create output file
    FILE *fp = fopen(output_file, "wb");

    if (fp == NULL) {
        fprintf(stderr, "Error: cannot open output file for writing: %s\n", output_file);
        return 2;
    }
    icvWriteVecHeader(fp, sample_count, sample_width, sample_height);

    // generate distortions
    std::default_random_engine generator(time(NULL));
    std::normal_distribution<double> xdist(0.0, rotate_stddev_x / 3.0);
    std::normal_distribution<double> ydist(0.0, rotate_stddev_y / 3.0);
    std::normal_distribution<double> zdist(0.0, rotate_stddev_z / 3.0);
    std::normal_distribution<double> ldist(0.0, luminosity_stddev / 3.0);
    cv::Mat el = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(5, 5));
    int variations = MAX(1, (int)floor((double)sample_count / (double)samples.size()));
    int idx = 0;
    int i = 0;

    while (i < sample_count) {
        // suffle the input lists
        if (idx % samples.size() == 0) {
            std::shuffle(samples.begin(), samples.end(), generator);
            std::shuffle(backgrounds.begin(), backgrounds.end(), generator);
        }

        // read sample image
        auto const &sample_file(samples[idx % samples.size()]);
        cv::Mat sample = cv::imread(sample_file);
        double sampleRatio = (double)sample.cols / (double)sample.rows;
        double outputRatio = (double)sample_width / (double)sample_height;

        // normalize sample
        cv::Mat greySample = sample;
        double min, max;

        if (sample.channels() != 1) {
            cv::cvtColor(sample, greySample, cv::COLOR_RGB2GRAY);
        }
        cv::minMaxIdx(greySample, &min, &max);
        greySample -= min;
        greySample /= (max - min) / 255.0;

        // generate mask
        cv::Mat mask(cv::Mat::ones(greySample.rows, greySample.cols, greySample.type()));

        // enlarge canvas to fit output ratio
        cv::Mat resizedSample, resizedMask;

        if (backgrounds.size() > 0 && sampleRatio < outputRatio) {
            int width = (int)((double)greySample.rows * outputRatio);
            cv::Rect area(
                (width - greySample.cols) / 2,
                0,
                greySample.cols,
                greySample.rows
            );

            resizedSample = cv::Mat::zeros(greySample.rows, width, greySample.type());
            resizedMask = cv::Mat::zeros(greySample.rows, width, greySample.type());
            greySample.copyTo(resizedSample(area));
            mask.copyTo(resizedMask(area));
        } else if (backgrounds.size() > 0 && sampleRatio > outputRatio) {
            int height = (int)((double)greySample.cols / outputRatio);
            cv::Rect area(
                0,
                (height - greySample.rows) / 2,
                greySample.cols,
                greySample.rows
            );

            resizedSample = cv::Mat::zeros(height, greySample.cols, greySample.type());
            resizedMask = cv::Mat::zeros(height, greySample.cols, greySample.type());
            greySample.copyTo(resizedSample(area));
            mask.copyTo(resizedMask(area));
        } else {
            resizedSample = greySample;
            resizedMask = mask;
        }

        // apply distortions
        cv::Mat target(resizedSample.rows, resizedSample.cols, resizedSample.type());
        cv::Mat targetMask(resizedSample.rows, resizedSample.cols, resizedSample.type());
        double halfWidth = resizedSample.cols / 2.0;
        double halfHeight = resizedSample.rows / 2.0;
        cv::Mat rotationVector(3, 1, CV_64FC1);
        cv::Mat rotation4(cv::Mat::eye(4, 4, CV_64FC1));
        cv::Mat translate4(cv::Mat::eye(4, 4, CV_64FC1));
        cv::Mat translate3(cv::Mat::eye(3, 3, CV_64FC1));
        cv::Mat scale3(cv::Mat::eye(3, 3, CV_64FC1));
        int dx = (resizedSample.cols - greySample.cols) / 2;
        int dy = (resizedSample.rows - greySample.rows) / 2;
        cv::Point2f points1[4] = {
            cv::Point2f(dx,              dy),
            cv::Point2f(dx,              greySample.rows),
            cv::Point2f(greySample.cols, greySample.rows),
            cv::Point2f(greySample.cols, dy)
        };
        cv::Point2f points2[4];

        translate4.at<double>(0, 3) = -halfWidth;
        translate4.at<double>(1, 3) = -halfHeight;
        for (int k = 0; k < variations; k++) {
            double rx = k > 0 && rotate_stddev_x > 0.0 ? xdist(generator) : 0.0;
            double ry = k > 0 && rotate_stddev_y > 0.0 ? ydist(generator) : 0.0;
            double rz = k > 0 && rotate_stddev_z > 0.0 ? zdist(generator) : 0.0;
            double rl = k > 0 && luminosity_stddev > 0.0 ? ldist(generator) : 0.0;

            // compute rotation in 3d
            rotationVector.at<double>(0) = rx;
            rotationVector.at<double>(1) = ry;
            rotationVector.at<double>(2) = rz;
            cv::Rodrigues(rotationVector, cv::Mat(rotation4, cv::Rect(0, 0, 3, 3)));

            // compute transformation in 3d
            cv::Mat transform4(rotation4 * translate4);
            double minx = DBL_MAX, miny = DBL_MAX;
            double maxx = DBL_MIN, maxy = DBL_MIN;

            for (int j = 0; j < 4; j++) {
                cv::Mat point(4, 1, CV_64FC1);

                point.at<double>(0) = points1[j].x;
                point.at<double>(1) = points1[j].y;
                point.at<double>(2) = 0.0;
                point.at<double>(3) = 1.0;
                point = transform4 * point;
                points2[j].x = point.at<double>(0);
                points2[j].y = point.at<double>(1);

                if (points2[j].x < minx) {
                    minx = points2[j].x;
                }
                if (points2[j].x > maxx) {
                    maxx = points2[j].x;
                }
                if (points2[j].y < miny) {
                    miny = points2[j].y;
                }
                if (points2[j].y > maxy) {
                    maxy = points2[j].y;
                }
            }

            // compute transformation in 2d
            cv::Mat projection3(cv::getPerspectiveTransform(points1, points2));
            double scalex = (resizedSample.cols - dx) / (maxx - minx);
            double scaley = (resizedSample.rows - dy) / (maxy - miny);

            translate3.at<double>(0, 2) = halfWidth;
            translate3.at<double>(1, 2) = halfHeight;

            scale3.at<double>(0, 0) = scalex; //MIN(scalex, scaley);
            scale3.at<double>(1, 1) = scaley; //MIN(scalex, scaley);

            // transform sample and mask in 2d
            cv::Mat transform3(translate3 * scale3 * projection3);

            cv::warpPerspective(resizedSample, target, transform3, target.size());
            cv::warpPerspective(resizedMask, targetMask, transform3, targetMask.size());

            // apply luminosity change
            if (rl != 0.0) {
                rl += 1.0;
                target *= rl;
            }

            // read background image
            cv::Mat greyBackground;

            if (backgrounds.size() > 0) {
                auto const &background_file(backgrounds[i % backgrounds.size()]);
                cv::Mat background = cv::imread(background_file);

                // normalize background image
                if (background.channels() != 1) {
                    cv::cvtColor(background, greyBackground, cv::COLOR_RGB2GRAY);
                } else {
                    greyBackground = background;
                }
                cv::minMaxIdx(greyBackground, &min, &max);
                greyBackground -= min;
                greyBackground /= (max - min) / 255.0;

                // reshape background to fit output ratio
                double backgroundRatio = (double)greyBackground.cols / (double)greyBackground.rows;
                cv::Mat tmp;

                if (backgroundRatio < outputRatio) {
                    int height = (int)((double)greyBackground.cols / outputRatio);
                    std::uniform_int_distribution<int> hdist(0, greyBackground.rows - height);

                    tmp = greyBackground(
                        cv::Rect(
                            0,
                            hdist(generator),
                            greyBackground.cols,
                            height
                        )
                    );
                } else if (backgroundRatio > outputRatio) {
                    int width = (int)((double)greyBackground.rows * outputRatio);
                    std::uniform_int_distribution<int> wdist(0, greyBackground.cols - width);

                    tmp = greyBackground(
                        cv::Rect(
                            wdist(generator),
                            0,
                            width,
                            greyBackground.rows
                        )
                    );
                } else {
                    tmp = greyBackground;
                }
                cv::resize(tmp, greyBackground, resizedSample.size(), 0, 0, cv::INTER_CUBIC);
            } else {
                // random noise background
                greyBackground = cv::Mat(target.rows, target.cols, CV_8UC1);
                cv::randn(greyBackground, 255.0 / 2, 255.0 / 2 / 3);
                cv::GaussianBlur(greyBackground, greyBackground, cv::Size(5, 5), 10);
            }

            // blend background
            cv::Mat sampleMask, backgroundMask, tmp;

            cv::threshold(targetMask, sampleMask, 0.1, 255.0, cv::THRESH_BINARY);
            cv::erode(sampleMask, tmp, el);
            cv::blur(tmp, sampleMask, cv::Size(5, 5));

            cv::threshold(targetMask, backgroundMask, 0.1, 255.0, cv::THRESH_BINARY_INV);
            cv::dilate(backgroundMask, tmp, el);
            cv::blur(tmp, backgroundMask, cv::Size(5, 5));

            cv::multiply(target, sampleMask, target, 1.0 / 255.0);
            cv::multiply(greyBackground, backgroundMask, greyBackground, 1.0 / 255.0);

            target += greyBackground;

            // cv::namedWindow("preview", cv::WINDOW_NORMAL);
            // cv::imshow("preview", target);
            // while ((cv::waitKey(0) & 0xff) != '\n');

            // cv::namedWindow("preview", cv::WINDOW_NORMAL);
            // cv::imshow("preview", greyBackground);
            // while ((cv::waitKey(0) & 0xff) != '\n');

            // sample resize
            cv::Mat finalSample;

            cv::resize(target, finalSample, cv::Size(sample_width, sample_height), 0, 0, cv::INTER_CUBIC);

            // cv::namedWindow("preview", cv::WINDOW_NORMAL);
            // cv::imshow("preview", finalSample);
            // while ((cv::waitKey(0) & 0xff) != '\n');

            // sample save
            CvMat targetfinal_ = finalSample;

            icvWriteVecSample(fp, &targetfinal_);

            i++;
            if (i % 100 == 0) {
                fprintf(stdout, "processed %d images, %d samples\n", idx, i);
                fflush(stdout);
            }
        }
        idx++;
    }

    // close output file
    fclose(fp);
    return 0;
}