Ejemplo n.º 1
0
void ComputeUnaryPairwiseSums(CFVoxel *fgU, CFVoxel *bgU, 
							  CTypedPtrArray<CPtrArray, CFVoxel*> &pw, cvPoint3iArray &pwnc, int idx,
							  CVoxel *segm, double &usum, double &pwsum)
{
	int imX = segm->m_nX;
	int imY = segm->m_nY;
	int imZ = segm->m_nZ;
	usum = 0;
	pwsum = 0;
	gtype fgusum, bgusum;
	fgusum = bgusum = 0;
	int x, y, z, i, n, l;
	int nn = (int) pwnc.GetSize();
	cv::Point3i dpt(imX, imY, imZ);
	for ( z = 0, i = 0; z < imZ; z++ ) {
		for ( y = 0; y < imY; y++ ) {
			for ( x = 0; x < imX; x++, i++ ) {
				// get label of current pixel
				l = segm->m_pData[i];
				//////////////////////////////////////////////////////////////////////////
				// sum unary and pairwise energy from labels and potentials
				// UNARY energy
				// if voxel is assigned as background, add bgUnaries
				if ( l == 0 )
					bgusum += bgU->m_pfData[i];
				// else, add fgUnaries
				else 
					fgusum += fgU->m_pfData[i];

				// PAIRWISE energy
				// for all neighbors 
				cv::Point3i cpt(x,y,z);
				for ( n = 0; n < nn; n++ ) {
					cv::Point3i pt = cpt+pwnc[n];
					if ( ZERO_3DPT <= pt && pt < dpt  && 
						l != segm->m_pData[pt.m_z*imX*imY+pt.m_y*imX+pt.m_x] ) {
						//CFVoxel* tmpPW = pw[idx*nn + n];
						pwsum += pw[idx*nn + n]->GetAt(x,y,z);
					}
						
				}
			} // end for x
		} // end for y
	} 
	usum = fgusum+bgusum;
}
Ejemplo n.º 2
0
void vpTemplateTracker::computeOptimalBrentGain(const vpImage<unsigned char> &I,vpColVector &tp,double tMI,vpColVector &direction,double &alpha)
{
  vpColVector **ptp;
  ptp=new vpColVector*[4];
  vpColVector p0(nbParam);
  p0=tp;

  //valeur necessaire si conditionnel
  vpColVector dpt(Warp->getNbParam());
  vpColVector adpt(Warp->getNbParam());

  vpColVector p1(nbParam);
  if(useCompositionnal)
  {
    if(useInverse)
      Warp->getParamInverse(direction,dpt);
    else
      dpt=direction;
    Warp->pRondp(tp,dpt,p1);
  }
  else
  {
    p1=tp+direction;
  }

  vpColVector p2(nbParam);
  if(useCompositionnal)
  {
    adpt=alpha*direction;
    if(useInverse)
      Warp->getParamInverse(adpt,dpt);
    else
      dpt=adpt;
    Warp->pRondp(tp,dpt,p2);
  }
  else
  {
    p2=tp+alpha*direction;
  }
  vpColVector p3(nbParam);
  ptp[0]=&p0;
  ptp[1]=&p1;
  ptp[2]=&p2;
  ptp[3]=&p3;


  double *Cost=new double[4];
  //Cost[0]=getCost(I,p0);
  Cost[0]=tMI;
  Cost[1]=getCost(I,p1);
  Cost[2]=getCost(I,p2);


  double *talpha=new double[4];
  talpha[0]=0;
  talpha[1]=1.;
  talpha[2]=alpha;

  //for(int i=0;i<3;i++)
  //	std::cout<<"alpha["<<i<<"] = "<<talpha[i]<<"   Cost["<<i<<"] = "<<Cost[i]<<std::endl;

  //Utilise trois estimï¿œes de paraboles succesive ...
  //A changer pour rendre adaptable
  for(unsigned int opt=0;opt<nbIterBrent;opt++)
  {
    //double a=talpha[0];
    //double b=talpha[1];
    //double c=talpha[2];
    //double Cost0=Cost[0];
    //double Cost1=Cost[1];
    //double Cost2=Cost[2];

    vpMatrix A(3,3);
    for(unsigned int i=0;i<3;i++){A[i][0]=talpha[i]*talpha[i];A[i][1]=talpha[i];A[i][2]=1.;}
    //std::cout<<"A="<<A<<std::endl;
    vpColVector B(3);for(unsigned int i=0;i<3;i++)B[i]=Cost[i];
    vpColVector parabol(3);parabol=(A.t()*A).inverseByLU()*A.t()*B;
    //vpColVector parabol(3);parabol=A.pseudoInverse()*B;

    //si convexe
    if(parabol[0]>0)
    {
      talpha[3]=-0.5*parabol[1]/parabol[0];
      //std::cout<<"parabol = "<<parabol<<std::endl;
      //std::cout<<"convexe talpha = "<<talpha[3]<<std::endl;
    }
    else//si concave
    {
      int tindic_x_min=0;
      int tindic_x_max=0;
      for(int i=1;i<3;i++)
      {
        if(talpha[i]<talpha[tindic_x_min])
          tindic_x_min=i;
        if(talpha[i]>talpha[tindic_x_max])
          tindic_x_max=i;
      }

      if(Cost[tindic_x_max]<Cost[tindic_x_min])
      {
        //talpha[3]=talpha[tindic_x_max]+1.;
        talpha[3]=talpha[tindic_x_max]+1.;
        /*if(talpha[tindic_x_min]>talpha[tindic_x_max])
          talpha[3]=talpha[tindic_x_min]+1.;
        else
          talpha[3]=talpha[tindic_x_min]-1.;*/
      }
      else
      {
        //talpha[3]=talpha[tindic_x_min]-1.;
        talpha[3]=talpha[tindic_x_min]-1.;
        /*if(talpha[tindic_x_min]<talpha[tindic_x_max])
          talpha[3]=talpha[tindic_x_max]+1.;
        else
          talpha[3]=talpha[tindic_x_max]-1.;*/
      }
      //std::cout<<"concave talpha="<<talpha[3]<<std::endl;
    }
    //std::cout<<"talpha="<<talpha[3]<<std::endl;
    int indic_x_min=0;
    int indic_x_max=0;
    for(int i=1;i<3;i++)
    {
      if(talpha[i]<talpha[indic_x_min])
        indic_x_min=i;
      if(talpha[i]>talpha[indic_x_max])
        indic_x_max=i;
    }
    //std::cout<<"talpha = "<<talpha[3]<<std::endl;
    if(talpha[3]>talpha[indic_x_max])
      if((talpha[3]-talpha[indic_x_max])>alpha)talpha[3]=talpha[indic_x_max]+4.;
    if(talpha[3]<talpha[indic_x_min])
      if((talpha[indic_x_min]-talpha[3])>alpha)talpha[3]=talpha[indic_x_min]-4.;

    /*if(((b-a)*(Cost1-Cost2)-(b-c)*(Cost1-Cost0))==0)
    {Cost[3]=1000;break;}

    //calcul du gain correspondant au minimum de la parabole estimï¿œe
    talpha[3]=b-0.5*((b-a)*(b-a)*(Cost1-Cost2)-(b-c)*(b-c)*(Cost1-Cost0))/((b-a)*(Cost1-Cost2)-(b-c)*(Cost1-Cost0));
    int indic_x_min=0;
    int indic_x_max=0;
    for(int i=1;i<3;i++)
    {
      if(talpha[i]<talpha[indic_x_min])
        indic_x_min=i;
      if(talpha[i]>talpha[indic_x_max])
        indic_x_max=i;
    }
    std::cout<<"talpha = "<<talpha[3]<<std::endl;
    if(talpha[3]>talpha[indic_x_max])
      if((talpha[3]-talpha[indic_x_max])>alpha)talpha[3]=talpha[indic_x_max]+alpha;
    if(talpha[3]<talpha[indic_x_min])
      if((talpha[indic_x_min]-talpha[3])>alpha)talpha[3]=talpha[indic_x_min]-alpha;*/

    //p3=tp-talpha[3]*direction;
    if(useCompositionnal)
    {
      adpt=talpha[3]*direction;
      if(useInverse)
        Warp->getParamInverse(adpt,dpt);
      else
        dpt=adpt;
      Warp->pRondp(tp,dpt,p3);
    }
    else
    {
      p3=tp+talpha[3]*direction;
    }

    Cost[3]=getCost(I,p3);
    //std::cout<<"new cost="<<Cost[3]<<std::endl;

    int indice_f_max=0;
    for(int i=1;i<4;i++)
      if(Cost[i]>Cost[indice_f_max])
        indice_f_max=i;
    if(indice_f_max!=3)
    {
      *ptp[indice_f_max]=*ptp[3];
      Cost[indice_f_max]=Cost[3];
      talpha[indice_f_max]=talpha[3];
    }
    else
      break;
  }

  int indice_f_min=0;
  for(int i=0;i<4;i++)
    if(Cost[i]<Cost[indice_f_min])
      indice_f_min=i;

  alpha=talpha[indice_f_min];

  if(alpha<1)alpha=1.;

  delete[] ptp;
  delete[] Cost;
  delete[] talpha;
}
ossimProjection* ossimGdalProjectionFactory::createProjection(const ossimFilename& filename,
                                                             ossim_uint32 entryIdx)const
{
   ossimKeywordlist kwl;
   if(ossimString(filename).trim().empty()) return 0;
//    ossimRefPtr<ossimImageHandler> h = new ossimGdalTileSource;
   GDALDatasetH  h = GDALOpen(filename.c_str(), GA_ReadOnly);
   GDALDriverH   driverH = 0;
   ossimProjection* proj = 0;
   if(h)
   {
      driverH = GDALGetDatasetDriver( h );
      ossimString driverName( driverH ? GDALGetDriverShortName( driverH ) : "" );
      // use OSSIM's projection loader for NITF
      //
      if(driverName == "NITF")
      {
         GDALClose(h);
         return 0;
      }
      if(entryIdx != 0)
      {
         char** papszMetadata = GDALGetMetadata( h, "SUBDATASETS" );

         //---
         // ??? (drb) Should this be:
         // if ( entryIdx >= CSLCount(papszMetadata) ) close...
         //---
         if( papszMetadata&&(CSLCount(papszMetadata) < static_cast<ossim_int32>(entryIdx)) )
         {
            ossimNotify(ossimNotifyLevel_WARN) << "ossimGdalProjectionFactory::createProjection: We don't support multi entry handlers through the factory yet, only through the handler!";
            GDALClose(h);
            return 0;
         }
         else
         {
            GDALClose(h);
            return 0;
         }
      }

      ossimString wkt(GDALGetProjectionRef( h ));
      double geoTransform[6];
      bool transOk = GDALGetGeoTransform( h, geoTransform ) == CE_None;
      bool wktTranslatorOk = wkt.empty()?false:wktTranslator.toOssimKwl(wkt, kwl);
      if(!wktTranslatorOk)
      {
         ossim_uint32 gcpCount = GDALGetGCPCount(h);
         if(gcpCount > 3)
         {
            ossim_uint32 idx = 0;
            const GDAL_GCP* gcpList = GDALGetGCPs(h);
            ossimTieGptSet tieSet;
            if(gcpList)
            {
               for(idx = 0; idx < gcpCount; ++idx)
               {
                  ossimDpt dpt(gcpList[idx].dfGCPPixel,
                               gcpList[idx].dfGCPLine);
                  ossimGpt gpt(gcpList[idx].dfGCPY,
                               gcpList[idx].dfGCPX,
                               gcpList[idx].dfGCPZ);
                  tieSet.addTiePoint(new ossimTieGpt(gpt, dpt, .5));
               }

               //ossimPolynomProjection* tempProj = new ossimPolynomProjection;
               ossimBilinearProjection* tempProj = new ossimBilinearProjection;
			   //tempProj->setupOptimizer("1 x y x2 xy y2 x3 y3 xy2 x2y z xz yz");
               tempProj->optimizeFit(tieSet);
               proj = tempProj;
            }
         }
      }
      if ( transOk && proj==0 )
      {
         ossimString proj_type(kwl.find(ossimKeywordNames::TYPE_KW));
         ossimString datum_type(kwl.find(ossimKeywordNames::DATUM_KW));
         ossimString units(kwl.find(ossimKeywordNames::UNITS_KW));
         if ( proj_type.trim().empty() &&
              (driverName == "MrSID" || driverName == "JP2MrSID") )
         {
            bool bClose = true;
            // ESH 04/2008, #54: if no rotation factors use geographic system
            if( geoTransform[2] == 0.0 && geoTransform[4] == 0.0 )
            {
               ossimString projTag( GDALGetMetadataItem( h, "IMG__PROJECTION_NAME", "" ) );
               if ( projTag.contains("Geographic") )
               {
                  bClose = false;

                  kwl.add(ossimKeywordNames::TYPE_KW,
                          "ossimEquDistCylProjection", true);
                  proj_type = kwl.find( ossimKeywordNames::TYPE_KW );

                  // Assign units if set in Metadata
                  ossimString unitTag( GDALGetMetadataItem( h, "IMG__HORIZONTAL_UNITS", "" ) );
                  if ( unitTag.contains("dd") ) // decimal degrees
                  {
                     units = "degrees";
                  }
                  else if ( unitTag.contains("dm") ) // decimal minutes
                  {
                     units = "minutes";
                  }
                  else if ( unitTag.contains("ds") ) // decimal seconds
                  {
                     units = "seconds";
                  }
               }
            }

            if ( bClose == true )
            {
               GDALClose(h);
               return 0;
            }
         }

         // Pixel-is-point of pixel-is area affects the location of the tiepoint since OSSIM is
         // always pixel-is-point so 1/2 pixel shift may be necessary:
         if((driverName == "MrSID") || (driverName == "JP2MrSID") || (driverName == "AIG"))
         {
            const char* rasterTypeStr = GDALGetMetadataItem( h, "GEOTIFF_CHAR__GTRasterTypeGeoKey", "" );
            ossimString rasterTypeTag( rasterTypeStr );

            // If the raster type is pixel_is_area, shift the tie point by
            // half a pixel to locate it at the pixel center.
            if ((driverName == "AIG") || (rasterTypeTag.contains("RasterPixelIsArea")))
            {
               geoTransform[0] += fabs(geoTransform[1]) / 2.0;
               geoTransform[3] -= fabs(geoTransform[5]) / 2.0;
            }
         }
         else
         {
            // Conventionally, HFA stores the pixel alignment type for each band. Here assume all
            // bands are the same. Consider only the first band:
            GDALRasterBandH bBand = GDALGetRasterBand( h, 1 );
            char** papszMetadata = GDALGetMetadata( bBand, NULL );
            if (CSLCount(papszMetadata) > 0)
            {
               for(int i = 0; papszMetadata[i] != NULL; i++ )
               {
                  ossimString metaStr = papszMetadata[i];
                  metaStr.upcase();
                  if (metaStr.contains("AREA_OR_POINT"))
                  {
                     ossimString pixel_is_point_or_area = metaStr.split("=")[1];
                     pixel_is_point_or_area.upcase();
                     if (pixel_is_point_or_area.contains("AREA"))
                     {
                        // Need to shift the tie point so that pixel is point:
                        geoTransform[0] += fabs(geoTransform[1]) / 2.0;
                        geoTransform[3] -= fabs(geoTransform[5]) / 2.0;
                     }
                     break;
                  }
               }
            }
         }

         kwl.remove(ossimKeywordNames::UNITS_KW);
         ossimDpt gsd(fabs(geoTransform[1]), fabs(geoTransform[5]));
         ossimDpt tie(geoTransform[0], geoTransform[3]);

         ossimUnitType savedUnitType =
            static_cast<ossimUnitType>(ossimUnitTypeLut::instance()->getEntryNumber(units));
         ossimUnitType unitType = savedUnitType;
         if(unitType == OSSIM_UNIT_UNKNOWN)
            unitType = OSSIM_METERS;

         if((proj_type == "ossimLlxyProjection") || (proj_type == "ossimEquDistCylProjection"))
         {
            // ESH 09/2008 -- Add the orig_lat and central_lon if the image
            // is using geographic coordsys.  This is used to convert the
            // gsd to linear units.

            // Half the number of pixels in lon/lat directions
            int nPixelsLon = GDALGetRasterXSize(h)/2.0;
            int nPixelsLat = GDALGetRasterYSize(h)/2.0;

            // Shift from image corner to center in lon/lat
            double shiftLon =  nPixelsLon * fabs(gsd.x);
            double shiftLat = -nPixelsLat * fabs(gsd.y);

            // lon/lat of center pixel of the image
            double centerLon = tie.x + shiftLon;
            double centerLat = tie.y + shiftLat;

            kwl.add(ossimKeywordNames::ORIGIN_LATITUDE_KW,
                    centerLat,
                    true);
            kwl.add(ossimKeywordNames::CENTRAL_MERIDIAN_KW,
                    centerLon,
                    true);

            kwl.add(ossimKeywordNames::TIE_POINT_LAT_KW,
                    tie.y,
                    true);
            kwl.add(ossimKeywordNames::TIE_POINT_LON_KW,
                    tie.x,
                    true);

            kwl.add(ossimKeywordNames::DECIMAL_DEGREES_PER_PIXEL_LAT,
                    gsd.y,
                    true);
            kwl.add(ossimKeywordNames::DECIMAL_DEGREES_PER_PIXEL_LON,
                    gsd.x,
                    true);

            if(savedUnitType == OSSIM_UNIT_UNKNOWN)
            {
               unitType = OSSIM_DEGREES;
            }
         }

         kwl.add(ossimKeywordNames::PIXEL_SCALE_XY_KW,
                 gsd.toString(),
                 true);
         kwl.add(ossimKeywordNames::PIXEL_SCALE_UNITS_KW,
                 units,
                 true);
         kwl.add(ossimKeywordNames::TIE_POINT_XY_KW,
                 tie.toString(),
                 true);
         kwl.add(ossimKeywordNames::TIE_POINT_UNITS_KW,
                 units,
                 true);

         std::stringstream mString;
         // store as a 4x4 matrix
         mString << ossimString::toString(geoTransform[1], 20)
                 << " " << ossimString::toString(geoTransform[2], 20)
                 << " " << 0 << " "
                 << ossimString::toString(geoTransform[0], 20)
                 << " " << ossimString::toString(geoTransform[4], 20)
                 << " " << ossimString::toString(geoTransform[5], 20)
                 << " " << 0 << " "
                 << ossimString::toString(geoTransform[3], 20)
                 << " " << 0 << " " << 0 << " " << 1 << " " << 0
                 << " " << 0 << " " << 0 << " " << 0 << " " << 1;

         kwl.add(ossimKeywordNames::IMAGE_MODEL_TRANSFORM_MATRIX_KW, mString.str().c_str(), true);

         //---
         // SPECIAL CASE:  ArcGrid in British National Grid
         //---
         if(driverName == "AIG" && datum_type == "OSGB_1936")
         {
            ossimFilename prj_file = filename.path() + "/prj.adf";

            if(prj_file.exists())
            {
               ossimKeywordlist prj_kwl(' ');
               prj_kwl.addFile(prj_file);

               ossimString proj = prj_kwl.find("Projection");

               // Reset projection and Datum correctly for BNG.
               if(proj.upcase().contains("GREATBRITAIN"))
               {

                  kwl.add(ossimKeywordNames::TYPE_KW,
                          "ossimBngProjection", true);

                  ossimString datum  = prj_kwl.find("Datum");

                  if(datum != "")
                  {
                     if(datum == "OGB_A")
                        datum = "OGB-A";
                     else if(datum == "OGB_B")
                        datum = "OGB-B";
                     else if(datum == "OGB_C")
                        datum = "OGB-C";
                     else if(datum == "OGB_D")
                        datum = "OGB-D";
                     else if(datum == "OGB_M")
                        datum = "OGB-M";
                     else if(datum == "OGB_7")
                        datum = "OGB-7";

                     kwl.add(ossimKeywordNames::DATUM_KW,
                             datum, true);
                  }
               }
            }
         }
     }
	 if(traceDebug())
	 {
		 ossimNotify(ossimNotifyLevel_DEBUG) << "ossimGdalProjectionFactory: createProjection KWL = \n " << kwl << std::endl;
	 }
      GDALClose(h);
      proj = ossimProjectionFactoryRegistry::instance()->createProjection(kwl);
  }

   return proj;
}
// ######################################################################
void CenterSurroundHistogramSegmenter::computeCStemplates()
{
  itsCStemplates.clear();
  itsCSpoints.clear();

  int width  = DEFAULT_WIDTH;
  int height = DEFAULT_HEIGHT;
  int mindim = width < height ? width : height;

  // compute for each scale: .1, .2, .3 of minimum of dimension
  // max was .7 NOTE: .4 is probably better
  std::vector<float> scales;
  for(float i = 0.1F; i <= 0.3F; i+=0.1F) scales.push_back(i);

  // compute ratio: .5, .75, 1.0, 1.5, 2.0
  std::vector<float> ratios;
  //for(float i = 0.5F; i <= 2.0F; i+=0.25F) ratios.push_back(i);
  ratios.push_back(0.5F);
  ratios.push_back(0.75F);
  ratios.push_back(1.0F);
  ratios.push_back(1.5F);
  ratios.push_back(2.0F);

  // cos and sin of 45 degree 
  // for the diagonal center surround shapes
  float cang = cos(M_PI/4.0F);
  float sang = sin(M_PI/4.0F);

  // for each scale and ratios
  for(uint i = 0; i < scales.size(); i++)
    {
      int h2 = int(scales[i]*mindim)/GRID_SIZE/2;
      LDEBUG("h2[%d]: %f --> %d ", i, scales[i]*mindim, h2);

      int prevw2 = -1;
      for(uint j = 0; j < ratios.size(); j++)
        {
          // get width, height, dimensions 
          // of the center and surround rectangles
          int w2 = int(h2*ratios[j]);
          if(w2 == prevw2) continue;  prevw2 = w2;
          int w   = 2*w2 + 1;        int h   = 2*h2 + 1;
          int sw2 = 2*w2;            int sh2 = 2*h2;
          int sw  = 2*sw2 + 1;       int sh  = 2*sh2 + 1;
          LDEBUG("w2[%d]: %f --> %d",j, h2*ratios[j], w2);
          
          // compute and store the offsets as well
          int ow = w2/2; if(ow == 0) ow = 1;
          int oh = h2/2; if(oh == 0) oh = 1;
          
          // here the off sets are spaced a quarter
          // the length of each dimension
          std::vector<int> offw; 
          offw.push_back(0); offw.push_back( ow); offw.push_back(-ow);
          if(w2 != 1){ offw.push_back( w2); offw.push_back(-w2); } 

          std::vector<int> offh; 
          offh.push_back(0); offh.push_back( oh); offh.push_back(-oh);
          if(h2 != 1){ offh.push_back( h2); offh.push_back(-h2); } 

          Dims cd(w,h); Dims sd(sw,sh);
          Point2D<int> offc( -w2,  -h2);
          Point2D<int> offs(-sw2, -sh2);
          LDEBUG("Dims: c:%d %d s:%d %d: off: %d %d", 
                 w, h, sw, sh, -w2, -h2);

          for(uint ii = 0; ii < offw.size(); ii++)
            for(uint jj = 0; jj < offh.size(); jj++)
              {
                Point2D<int> pt(offw[ii], offh[jj]);

                Rectangle rc(pt+offc, cd);
                Rectangle rs(pt+offs, sd);
                itsCStemplates.push_back
                  (std::pair<Rectangle,Rectangle>(rc,rs));
              }

          // now we rotate the rectangle 45 degrees 
          // and add it to the csPoints
          int sdiag = int(sqrt(sw*sw + sh*sh)+ 0.5F) + 1;
          Point2D<int> dpt(sdiag,sdiag);

          // here we rotate the image representation of the template
          Image<float> tcimg(2*sdiag,2*sdiag,ZEROS);
          drawFilledRect(tcimg, Rectangle(dpt+offc, cd), 1.0F);
          Image<float> rtcimg = rotate(tcimg, sdiag, sdiag, M_PI/4.0F);

          Image<float> tsimg(2*sdiag,2*sdiag,ZEROS);
          drawFilledRect(tsimg, Rectangle(dpt+offs, sd), 1.0F);
          Image<float> rtsimg = rotate(tsimg, sdiag, sdiag, M_PI/4.0F);

          // only select rotated point values 
          // that are above 0.5F
          std::vector<Point2D<int> > tempC;
          for(int jj = 0; jj < rtcimg.getHeight(); jj++)
            for(int ii = 0; ii < rtcimg.getWidth(); ii++)
              {
                float val = rtcimg.getVal(ii,jj);
                if(val > 0.5F) 
                  tempC.push_back(Point2D<int>(ii,jj)-dpt);
              }

          std::vector<Point2D<int> > tempS;
          for(int jj = 0; jj < rtsimg.getHeight(); jj++)
            for(int ii = 0; ii < rtsimg.getWidth(); ii++)
              {
                float cval = rtcimg.getVal(ii,jj);
                float sval = rtsimg.getVal(ii,jj);
                if(cval < 0.5F && sval > 0.5F) 
                  tempS.push_back(Point2D<int>(ii,jj)-dpt);
              }
          
          // rotate the offset points as well
          for(uint ii = 0; ii < offw.size(); ii++)
            for(uint jj = 0; jj < offh.size(); jj++)
              {
                float rx = round( offw[ii]*cang - offh[jj]*sang);
                float ry = round( offw[ii]*sang + offh[jj]*cang);
                Point2D<int> pt(int(rx+0.0F), int(ry+0.0F));

                LDEBUG("rotated (%3d %3d) --> %5.3f %5.3f --> pt: %3d %3d", 
                       offw[ii], offh[jj], rx, ry, pt.i, pt.j);

                std::vector<Point2D<int> > rtempC;
                for(uint cc = 0; cc < tempC.size(); cc++)
                  rtempC.push_back(tempC[cc]+pt);

                std::vector<Point2D<int> > rtempS;
                for(uint ss = 0; ss < tempS.size(); ss++)
                  rtempS.push_back(tempS[ss]+pt);

                itsCSpoints.push_back
                  (std::pair<std::vector<Point2D<int> >,
                   std::vector<Point2D<int> > >(rtempC,rtempS));
              }

          // Image<float> disp(4*sdiag*GRID_SIZE, 2*sdiag*GRID_SIZE, ZEROS);
          // if(itsWin.is_invalid())
          //   itsWin.reset(new XWinManaged(disp.getDims(), 0, 0, "CSHse"));
          // else itsWin->setDims(disp.getDims());
          // inplacePaste(disp, zoomXY(tcimg,GRID_SIZE), Point2D<int>(0,0));
          // inplacePaste(disp, zoomXY(rtcimg,GRID_SIZE), 
          //              Point2D<int>(2*sdiag*GRID_SIZE,0));
          // itsWin->drawImage(disp,0,0);
          // Raster::waitForKey();          

          // inplacePaste(disp, zoomXY(tsimg,GRID_SIZE), Point2D<int>(0,0));
          // inplacePaste(disp, zoomXY(rtsimg,GRID_SIZE), 
          //              Point2D<int>(2*sdiag*GRID_SIZE,0));
          // itsWin->drawImage(disp,0,0);
          // Raster::waitForKey(); 
        }
    }

  LDEBUG("done with templates: %" ZU , itsCStemplates.size());
  LDEBUG("done with points:    %" ZU , itsCSpoints.size());
}