Пример #1
0
int main(int argc, char *argv[])
{
    int time = getTimeMill();
    QCoreApplication a(argc, argv);
    
    QString dirPath = (argc > 1) ? a.arguments()[1] : 
            a.applicationDirPath();
    QString patternPath = (argc > 2) ? a.arguments()[2] :
            QString("input.jpg");
    QImage pattern(patternPath);
    if (pattern.isNull()) {
        pattern = QImage("input.jpg");
    }
    if (pattern.isNull())
        cout << "No pattern image." << endl;
    else {
        gpattern = GImage(pattern);
        GPyramid pyr(gpattern, 1.6f, 0.5f, 3);
        poivec p = getDOGDetection(pyr);
        p = calculateOrientations(pyr, p);
        pdescs = getDescriptors(pyr, p);
        processDir(dirPath);
    }
    
    time = getTimeMill() - time;
    cout << "Completed in " << time << "ms." << endl;
    return 0;
//    return a.exec();
}
Пример #2
0
void processFile(QString &path) {
    QImage img(path);
    if (img.isNull())
        return;
    GImage gimg = GImage(img);
    GPyramid pyr(gimg, 1.6f, 0.5f, 3);
    auto p = getDOGDetection(pyr);
    p = calculateOrientations(pyr, p);
    auto descs = getDescriptors(pyr, p);
    auto m = getMatchingPOIs(pdescs, descs, 
                             numeric_limits<float>::max());
    int k = getHough(m.first, m.second, gimg.width, gimg.height, 
                     1e-3f, 1e3f, 100, 100, 22, 10).second;
    if (k >= 4)
        cout << path.toStdString() << endl;
}
Пример #3
0
//------------------------------------------------------------------------------
void StereoCtFWarping::addImage(const ImageGpu32fC1::Ptr& image)
{
  // generate image pyramid
  ImagePyramid32fC1::Ptr pyr(new ImagePyramid32fC1(image, params_->ctf.scale_factor, 4));

  // update number of levels
  if (params_->ctf.levels > pyr->numLevels())
    params_->ctf.levels = pyr->numLevels();
  if (params_->ctf.coarsest_level > params_->ctf.levels - 1)
    params_->ctf.coarsest_level = params_->ctf.levels - 1;

  images_.push_back(image);
  image_pyramids_.push_back(pyr);

  LOG(INFO) << "we have now " << images_.size() << " images and "
            <<  image_pyramids_.size() << " pyramids in the CTF instance. "
             << "params_->ctf.levels: " << params_->ctf.levels
             << " (" << params_->ctf.coarsest_level
             << " -> " << params_->ctf.finest_level << ")";
}
Пример #4
0
GPU_PERF_TEST(ImagePyramid_getLayer, cv::gpu::DeviceInfo, cv::Size, MatType)
{
    cv::gpu::DeviceInfo devInfo = GET_PARAM(0);
    cv::gpu::setDevice(devInfo.deviceID());

    cv::Size size = GET_PARAM(1);
    int type = GET_PARAM(2);

    cv::Mat src_host(size, type);
    fill(src_host, 0, 255);

    cv::gpu::GpuMat src(src_host);
    cv::gpu::GpuMat dst;

    cv::gpu::ImagePyramid pyr(src, 3);

    pyr.getLayer(dst, cv::Size(size.width / 2 + 10, size.height / 2 + 10));

    TEST_CYCLE()
    {
        pyr.getLayer(dst, cv::Size(size.width / 2 + 10, size.height / 2 + 10));
    }
}
Пример #5
0
int main(int argc, char** argv )
{
  try {
    if(argc != 2) {
      printf( "Usage: %s <image name.[pgm,ppm,jpeg,png,bmp]>\n", argv[0] );
      return -1;
    }
    //! [vpImage construction]
    vpImage<unsigned char> I;
    //! [vpImage construction]

    try {
      vpImageIo::read(I, argv[1]);
    }
    catch(...) {
      std::cout << "Cannot read image \"" << argv[1] << "\"" << std::endl;
      return -1;
    }

    display(I, "Original image");

    //! [Gaussian blur]
    vpImage<double> F;
    vpImageFilter::gaussianBlur(I, F);
    //! [Gaussian blur]
    display(F, "Blur (default)");

    vpImageFilter::gaussianBlur(I, F, 7, 2);
    display(F, "Blur (var=2)");

    //! [Gradients x]
    vpImage<double> dIx;
    vpImageFilter::getGradX(I, dIx);
    //! [Gradients x]
    display(dIx, "Gradient dIx");

    //! [Gradients y]
    vpImage<double> dIy;
    vpImageFilter::getGradY(I, dIy);
    //! [Gradients y]
    display(dIy, "Gradient dIy");

    //! [Canny]
#if (VISP_HAVE_OPENCV_VERSION >= 0x020100)
    vpImage<unsigned char> C;
    vpImageFilter::canny(I, C, 5, 15, 3);
    display(C, "Canny");
#endif
    //! [Canny]

    //! [Convolution kernel]
    vpMatrix K(3,3); // Sobel kernel along x
    K[0][0] = 1; K[0][1] = 0; K[0][2] = -1;
    K[1][0] = 2; K[1][1] = 0; K[1][2] = -2;
    K[2][0] = 1; K[2][1] = 0; K[2][2] = -1;
    //! [Convolution kernel]
    //! [Convolution]
    vpImage<double> Gx;
    vpImageFilter::filter(I, Gx, K);
    //! [Convolution]
    display(Gx, "Sobel x");

    //! [Gaussian pyramid]
    size_t nlevel = 3;
    std::vector< vpImage<unsigned char> > pyr(nlevel);
    pyr[0] = I;
    for (size_t i=1; i < nlevel; i++) {
      vpImageFilter::getGaussPyramidal(pyr[i-1], pyr[i]);
      display(pyr[i], "Pyramid");
    }
    //! [Gaussian pyramid]
    return 0;
  }
  catch(vpException &e) {
    std::cout << "Catch an exception: " << e << std::endl;
    return 1;
  }
}
Пример #6
0
void TauWriter::operate()
{
  try {
    QFileInfo file_info(GuiMainWindow::pointer()->getFilename());
    readOutputFileName(file_info.completeBaseName() + ".grid");
    if (isValid()) {
      QString file_name = getFileName();
      NcFile *nc_file = new NcFile(file_name.toAscii(), NcFile::Replace);
      if (!nc_file->is_valid()) {
        EG_ERR_RETURN("unable to open NetCFD file for writing");
      }

      // point coordinates
      size_t Np = m_Grid->GetNumberOfPoints();
      vector<double> x(Np),y(Np),z(Np);
      for (vtkIdType id_node = 0; id_node < m_Grid->GetNumberOfPoints(); ++id_node) {
        vec3_t xv;
        m_Grid->GetPoint(id_node, xv.data());
        x[id_node] = xv[0];
        y[id_node] = xv[1];
        z[id_node] = xv[2];
      }
      NcDim *no_of_points = nc_file->add_dim("no_of_points", Np);
      NcVar *points_xc = nc_file->add_var("points_xc", ncDouble, no_of_points);
      NcVar *points_yc = nc_file->add_var("points_yc", ncDouble, no_of_points);
      NcVar *points_zc = nc_file->add_var("points_zc", ncDouble, no_of_points);
      points_xc->put(&x[0],Np);
      points_yc->put(&y[0],Np);
      points_zc->put(&z[0],Np);

      // boundary faces
      size_t Nbe   = 0;;
      size_t Nquad = 0;
      size_t Ntri  = 0;
      for (vtkIdType id_cell = 0; id_cell < m_Grid->GetNumberOfCells(); ++id_cell) {
        if (isSurface(id_cell, m_Grid)) {
          ++Nbe;
          if (m_Grid->GetCellType(id_cell) == VTK_TRIANGLE) {
            ++Ntri;
          } else if (m_Grid->GetCellType(id_cell) == VTK_QUAD) {
            ++Nquad;
          } else {
            EG_ERR_RETURN("unsupported boundary element type encountered");
          }
        }
      }
      NcDim *no_of_surfaceelements = nc_file->add_dim("no_of_surfaceelements", Nbe);
      NcVar *boundarymarker_of_surfaces = nc_file->add_var("boundarymarker_of_surfaces", ncInt, no_of_surfaceelements);
      vector<int> bm(Nbe,0), tri(3*Ntri), quad(4*Nquad);
      int i_bm = 0;
      QSet<int> bc_set = getAllBoundaryCodes(m_Grid);
      QVector<int> bcs(bc_set.size());
      qCopy(bc_set.begin(), bc_set.end(), bcs.begin());
      EG_VTKDCC(vtkIntArray, cell_code, m_Grid, "cell_code");
      if (Ntri) {
        NcDim *no_of_surfacetriangles = nc_file->add_dim("no_of_surfacetriangles", Ntri);
        NcDim *points_per_surfacetriangle = nc_file->add_dim("points_per_surfacetriangle", 3);
        NcVar *points_of_surfacetriangles = nc_file->add_var("points_of_surfacetriangles", ncInt, no_of_surfacetriangles, points_per_surfacetriangle);
        int i_tri = 0;
        for (vtkIdType id_cell = 0; id_cell < m_Grid->GetNumberOfCells(); ++id_cell) {
          if (isSurface(id_cell, m_Grid)) {
            if (m_Grid->GetCellType(id_cell) == VTK_TRIANGLE) {
              for (int i_bc = 0; i_bc < bcs.size(); ++i_bc) {
                if (bcs[i_bc] == cell_code->GetValue(id_cell)) {
                  bm[i_bm] = i_bc+1;
                  break;
                }
              }
              vtkIdType N_pts, *pts;
              m_Grid->GetCellPoints(id_cell, N_pts, pts);
              tri[i_tri + 0] = pts[0];
              tri[i_tri + 1] = pts[1];
              tri[i_tri + 2] = pts[2];
              ++i_bm;
              i_tri += 3;
            }
          }
        }
        points_of_surfacetriangles->put(&tri[0],Ntri,3);
      }
      if (Nquad) {
        NcDim *no_of_surfacequadrilaterals     = nc_file->add_dim("no_of_surfacequadrilaterals",Nquad);
        NcDim *points_per_surfacequadrilateral = nc_file->add_dim("points_per_surfacequadrilateral",4);
        NcVar *points_of_surfacequadrilaterals = nc_file->add_var("points_of_surfacequadrilaterals",ncInt, no_of_surfacequadrilaterals, points_per_surfacequadrilateral);
        int i_quad = 0;
        for (vtkIdType id_cell = 0; id_cell < m_Grid->GetNumberOfCells(); ++id_cell) {
          if (isSurface(id_cell, m_Grid)) {
            if (m_Grid->GetCellType(id_cell) == VTK_QUAD) {
              for (int i_bc = 0; i_bc < bcs.size(); ++i_bc) {
                if (bcs[i_bc] == cell_code->GetValue(id_cell)) {
                  bm[i_bm] = i_bc+1;
                  break;
                }
              }
              vtkIdType N_pts, *pts;
              m_Grid->GetCellPoints(id_cell, N_pts, pts);
              quad[i_quad + 0] = pts[0];
              quad[i_quad + 1] = pts[1];
              quad[i_quad + 2] = pts[2];
              quad[i_quad + 3] = pts[3];
              ++i_bm;
              i_quad += 4;
            }
          }
        }
        points_of_surfacequadrilaterals->put(&quad[0],Nquad,4);
      }
      boundarymarker_of_surfaces->put(&bm[0],Nbe);
      NcDim *no_of_markers = nc_file->add_dim("no_of_markers", bcs.size());


      int Ntet = 0;
      int Npri = 0;
      int Nhex = 0;
      int Npyr = 0;
      for (vtkIdType id_cell = 0; id_cell < m_Grid->GetNumberOfCells(); ++id_cell) {
        if (m_Grid->GetCellType(id_cell) == VTK_TETRA)      ++Ntet;
        if (m_Grid->GetCellType(id_cell) == VTK_PYRAMID)    ++Npyr;
        if (m_Grid->GetCellType(id_cell) == VTK_WEDGE)      ++Npri;
        if (m_Grid->GetCellType(id_cell) == VTK_HEXAHEDRON) ++Nhex;
      }

      vector<int> tet(Ntet*4),pyr(Npyr*5),pri(Npri*6),hex(Nhex*8);
      int i_tet = 0;
      int i_pyr = 0;
      int i_pri = 0;
      int i_hex = 0;
      if (Ntet) {
        NcDim *no_of_tetraeders = nc_file->add_dim("no_of_tetraeders",Ntet);
        NcDim *points_per_tetraeder = nc_file->add_dim("points_per_tetraeder",4);
        NcVar *points_of_tetraeders = nc_file->add_var("points_of_tetraeders",ncInt, no_of_tetraeders, points_per_tetraeder);
        for (vtkIdType id_cell = 0; id_cell < m_Grid->GetNumberOfCells(); ++id_cell) {
          if (m_Grid->GetCellType(id_cell) == VTK_TETRA) {
            vtkIdType *pts, N_pts;
            m_Grid->GetCellPoints(id_cell, N_pts, pts);
            tet[i_tet + 0] = pts[0];
            tet[i_tet + 1] = pts[1];
            tet[i_tet + 2] = pts[2];
            tet[i_tet + 3] = pts[3];
            i_tet += 4;
          }
        }
        points_of_tetraeders->put(&tet[0],Ntet,4);
      }
      if (Npyr) {
        NcDim *no_of_pyramids = nc_file->add_dim("no_of_pyramids",Npyr);
        NcDim *points_per_pyramid = nc_file->add_dim("points_per_pyramid",5);
        NcVar *points_of_pyramids = nc_file->add_var("points_of_pyramids",ncInt, no_of_pyramids, points_per_pyramid);
        for (vtkIdType id_cell = 0; id_cell < m_Grid->GetNumberOfCells(); ++id_cell) {
          if (m_Grid->GetCellType(id_cell) == VTK_PYRAMID) {
            vtkIdType *pts, N_pts;
            m_Grid->GetCellPoints(id_cell, N_pts, pts);
            pyr[i_pyr + 0] = pts[0];
            pyr[i_pyr + 1] = pts[1];
            pyr[i_pyr + 2] = pts[2];
            pyr[i_pyr + 3] = pts[3];
            pyr[i_pyr + 4] = pts[4];
            i_pyr += 5;
          }
        }
        points_of_pyramids->put(&pyr[0],Npyr,5);
      }
      if (Npri) {
        NcDim *no_of_prisms = nc_file->add_dim("no_of_prisms",Npri);
        NcDim *points_per_prism = nc_file->add_dim("points_per_prism",6);
        NcVar *points_of_prisms = nc_file->add_var("points_of_prisms",ncInt, no_of_prisms,  points_per_prism);
        for (vtkIdType id_cell = 0; id_cell < m_Grid->GetNumberOfCells(); ++id_cell) {
          if (m_Grid->GetCellType(id_cell) == VTK_WEDGE) {
            vtkIdType *pts, N_pts;
            m_Grid->GetCellPoints(id_cell, N_pts, pts);
            pri[i_pri + 0] = pts[0];
            pri[i_pri + 1] = pts[2];
            pri[i_pri + 2] = pts[1];
            pri[i_pri + 3] = pts[3];
            pri[i_pri + 4] = pts[5];
            pri[i_pri + 5] = pts[4];
            i_pri += 6;
          }
        }
        points_of_prisms->put(&pri[0],Npri,6);
      }
      if (Nhex) {
        NcDim *no_of_hexaeders = nc_file->add_dim("no_of_hexaeders",Nhex);
        NcDim *points_per_hexaeder = nc_file->add_dim("points_per_hexaeder",8);
        NcVar *points_of_hexaeders = nc_file->add_var("points_of_hexaeders",ncInt, no_of_hexaeders, points_per_hexaeder);
        for (vtkIdType id_cell = 0; id_cell < m_Grid->GetNumberOfCells(); ++id_cell) {
          if (m_Grid->GetCellType(id_cell) == VTK_HEXAHEDRON) {
            vtkIdType *pts, N_pts;
            m_Grid->GetCellPoints(id_cell, N_pts, pts);
            hex[i_hex + 0] = pts[4];
            hex[i_hex + 1] = pts[7];
            hex[i_hex + 2] = pts[6];
            hex[i_hex + 3] = pts[5];
            hex[i_hex + 4] = pts[0];
            hex[i_hex + 5] = pts[3];
            hex[i_hex + 6] = pts[2];
            hex[i_hex + 7] = pts[1];
            i_hex += 8;
          }
        }
        points_of_hexaeders->put(&hex[0],Nhex,8);
      }

      delete nc_file;
    }
  } catch (Error err) {
    err.display();
  }
}
Пример #7
0
void* WorldBuilder::unpack(void* buf)
{
  // unpack world database from network transfer
  // read style header
  uint16_t code, len;
  buf = nboUnpackUShort(buf, len);
  buf = nboUnpackUShort(buf, code);
  if (code != WorldCodeHeader) return NULL;

  // read style
  uint16_t gameStyle, maxPlayers, maxShots, maxFlags,serverMapVersion;
  buf = nboUnpackUShort(buf, serverMapVersion);
  if (serverMapVersion != mapVersion)
    return NULL;

  float worldSize;
  buf = nboUnpackFloat(buf, worldSize);
  BZDB.set(StateDatabase::BZDB_WORLDSIZE, string_util::format("%f", worldSize));
  buf = nboUnpackUShort(buf, gameStyle);
  setGameStyle(short(gameStyle));
  buf = nboUnpackUShort(buf, maxPlayers);
  setMaxPlayers(int(maxPlayers));
  buf = nboUnpackUShort(buf, maxShots);
  setMaxShots(int(maxShots));
  buf = nboUnpackUShort(buf, maxFlags);
  setMaxFlags(int(maxFlags));
  buf = nboUnpackFloat(buf, world->linearAcceleration);
  buf = nboUnpackFloat(buf, world->angularAcceleration);
  uint16_t shakeTimeout = 0, shakeWins;
  buf = nboUnpackUShort(buf, shakeTimeout);
  setShakeTimeout(0.1f * float(shakeTimeout));
  buf = nboUnpackUShort(buf, shakeWins);
  setShakeWins(shakeWins);
  uint32_t epochOffset;
  buf = nboUnpackUInt(buf, epochOffset);
  setEpochOffset(epochOffset);

  // read geometry
  buf = nboUnpackUShort(buf, len);
  buf = nboUnpackUShort(buf, code);
  while (code != WorldCodeEnd) {
    switch (code) {
      case WorldCodeBox: {
	float data[7];
	unsigned char tempflags;

	if (len != WorldCodeBoxSize)
	  return NULL;

	memset(data, 0, sizeof(float) * 7);
	buf = nboUnpackFloat(buf, data[0]);
	buf = nboUnpackFloat(buf, data[1]);
	buf = nboUnpackFloat(buf, data[2]);
	buf = nboUnpackFloat(buf, data[3]);
	buf = nboUnpackFloat(buf, data[4]);
	buf = nboUnpackFloat(buf, data[5]);
	buf = nboUnpackFloat(buf, data[6]);
	buf = nboUnpackUByte(buf, tempflags);
	BoxBuilding box(data, data[3], data[4], data[5], data[6],
			(tempflags & _DRIVE_THRU)!=0, (tempflags & _SHOOT_THRU)!=0);
	append(box);
	break;
      }
      case WorldCodePyramid: {
	float data[7];
	unsigned char tempflags;

	if (len != WorldCodePyramidSize)
	  return NULL;

	buf = nboUnpackFloat(buf, data[0]);
	buf = nboUnpackFloat(buf, data[1]);
	buf = nboUnpackFloat(buf, data[2]);
	buf = nboUnpackFloat(buf, data[3]);
	buf = nboUnpackFloat(buf, data[4]);
	buf = nboUnpackFloat(buf, data[5]);
	buf = nboUnpackFloat(buf, data[6]);
	buf = nboUnpackUByte(buf, tempflags);

	PyramidBuilding pyr(data, data[3], data[4], data[5], data[6],
			    (tempflags & _DRIVE_THRU)!=0, (tempflags & _SHOOT_THRU)!=0);
	if (tempflags & _FLIP_Z)
	  pyr.setZFlip();

	append(pyr);
	break;
      }
      case WorldCodeTeleporter: {
	float data[8];
	unsigned char tempflags;

	if (len != WorldCodeTeleporterSize)
	  return NULL;

	buf = nboUnpackFloat(buf, data[0]);
	buf = nboUnpackFloat(buf, data[1]);
	buf = nboUnpackFloat(buf, data[2]);
	buf = nboUnpackFloat(buf, data[3]);
	buf = nboUnpackFloat(buf, data[4]);
	buf = nboUnpackFloat(buf, data[5]);
	buf = nboUnpackFloat(buf, data[6]);
	buf = nboUnpackFloat(buf, data[7]);
	buf = nboUnpackUByte(buf, tempflags);
	Teleporter tele(data, data[3], data[4], data[5], data[6],data[7],
			(tempflags & _DRIVE_THRU)!=0, (tempflags & _SHOOT_THRU)!=0);
	append(tele);
	break;
      }
      case WorldCodeLink: {
	uint16_t data[2];

	if (len != WorldCodeLinkSize)
	  return NULL;

	buf = nboUnpackUShort(buf, data[0]);
	buf = nboUnpackUShort(buf, data[1]);
	setTeleporterTarget(int(data[0]), int(data[1]));
	break;
      }
      case WorldCodeWall: {
	float data[6];

	if (len != WorldCodeWallSize)
	  return NULL;

	buf = nboUnpackFloat(buf, data[0]);
	buf = nboUnpackFloat(buf, data[1]);
	buf = nboUnpackFloat(buf, data[2]);
	buf = nboUnpackFloat(buf, data[3]);
	buf = nboUnpackFloat(buf, data[4]);
	buf = nboUnpackFloat(buf, data[5]);
	WallObstacle wall(data, data[3], data[4], data[5]);
	append(wall);
	break;
      }
      case WorldCodeBase: {
	uint16_t team;
	float data[10];

	if (len != WorldCodeBaseSize)
	  return NULL;

	buf = nboUnpackUShort(buf, team);
	buf = nboUnpackFloat(buf, data[0]);
	buf = nboUnpackFloat(buf, data[1]);
	buf = nboUnpackFloat(buf, data[2]);
	buf = nboUnpackFloat(buf, data[3]);
	buf = nboUnpackFloat(buf, data[4]);
	buf = nboUnpackFloat(buf, data[5]);
	buf = nboUnpackFloat(buf, data[6]);
	buf = nboUnpackFloat(buf, data[7]);
	buf = nboUnpackFloat(buf, data[8]);
	buf = nboUnpackFloat(buf, data[9]);
	BaseBuilding base(data, data[3], data +4, team);
	append(base);
	setBase(TeamColor(team), data, data[3], data[4], data[5], data[6]);
	break;
      }
      case WorldCodeWeapon: {
	Weapon weapon;
        uint16_t delays; 

	buf = FlagType::unpack(buf, weapon.type);
	buf = nboUnpackFloat(buf, weapon.pos[0]);
	buf = nboUnpackFloat(buf, weapon.pos[1]);
	buf = nboUnpackFloat(buf, weapon.pos[2]);
	buf = nboUnpackFloat(buf, weapon.dir);
	buf = nboUnpackFloat(buf, weapon.initDelay);
	buf = nboUnpackUShort(buf, delays);
	
	uint16_t weapon_len = WorldCodeWeaponSize + (delays * sizeof(float));
	if (len != weapon_len) {
	  return NULL;
	}
	
	int i;
	for (i = 0; i < delays; i++) {
	  float delay;
  	  buf = nboUnpackFloat(buf, delay);
  	  weapon.delay.push_back(delay);
  	}
	append(weapon);
	break;
      }
      case WorldCodeZone: {
        EntryZone zone;
        uint16_t flags, teams, safety;

	buf = nboUnpackFloat(buf, zone.pos[0]);
	buf = nboUnpackFloat(buf, zone.pos[1]);
	buf = nboUnpackFloat(buf, zone.pos[2]);
	buf = nboUnpackFloat(buf, zone.size[0]);
	buf = nboUnpackFloat(buf, zone.size[1]);
	buf = nboUnpackFloat(buf, zone.size[2]);
	buf = nboUnpackFloat(buf, zone.rot);
	buf = nboUnpackUShort(buf, flags);
	buf = nboUnpackUShort(buf, teams);
	buf = nboUnpackUShort(buf, safety);

        uint16_t zone_len = WorldCodeZoneSize;
        zone_len += FlagType::packSize * flags;
        zone_len += sizeof(uint16_t) * teams;
        zone_len += sizeof(uint16_t) * safety;
	if (len != zone_len) {
	  return NULL;
	}

        int i;
	for (i = 0; i < flags; i++) {
	  FlagType *type;
  	  buf = FlagType::unpack (buf, type);
  	  zone.flags.push_back(type);
  	}
	for (i = 0; i < teams; i++) {
	  uint16_t team;
  	  buf = nboUnpackUShort(buf, team);
  	  zone.teams.push_back((TeamColor)team);
  	}
	for (i = 0; i < safety; i++) {
	  uint16_t safety;
  	  buf = nboUnpackUShort(buf, safety);
  	  zone.safety.push_back((TeamColor)safety);
  	}
	append(zone);
	break;
      }
      default:
	return NULL;
    }
    buf = nboUnpackUShort(buf, len);
    buf = nboUnpackUShort(buf, code);
  }

  return buf;
}