// Fields("patchIdentifier", "patchCount"));
  private void processPatch(Tuple tuple) {
    Serializable.PatchIdentifier patchIdentifier =
        (Serializable.PatchIdentifier) tuple.getValueByField(FIELD_PATCH_IDENTIFIER);
    int patchCount = tuple.getIntegerByField(FIELD_PATCH_COUNT);
    int frameId = patchIdentifier.frameId;
    if (frameMap.containsKey(frameId)) {
      List<Serializable.Rect> detectedLogoList = new ArrayList<>();
      SIFTfeatures sifTfeatures =
          new SIFTfeatures(
              sift, frameMap.get(frameId).toJavaCVMat(), patchIdentifier.roi.toJavaCVRect(), true);

      for (int logoIndex = 0; logoIndex < detectors.size(); logoIndex++) {
        StormVideoLogoDetectorGamma detector = detectors.get(logoIndex);
        // detector.detectLogosInRoi(frameMap.get(frameId).toJavaCVMat(),
        // patchIdentifier.roi.toJavaCVRect());
        detector.detectLogosByFeatures(sifTfeatures);

        Serializable.Rect detectedLogo = detector.getFoundRect();
        if (detectedLogo != null) {
          collector.emit(
              LOGO_TEMPLATE_UPDATE_STREAM,
              new Values(patchIdentifier, detectedLogo, detector.getParentIdentifier(), logoIndex));
        }
        detectedLogoList.add(detectedLogo);
      }
      collector.emit(
          DETECTED_LOGO_STREAM,
          tuple,
          new Values(frameId, patchIdentifier, detectedLogoList, patchCount));
    } else {
      if (!patchQueue.containsKey(frameId)) patchQueue.put(frameId, new LinkedList<>());
      patchQueue.get(frameId).add(patchIdentifier);
    }
  }
  //  Fields("frameId", "frameMat", "patchCount"));
  private void processFrame(Tuple tuple) {
    int frameId = tuple.getIntegerByField(FIELD_FRAME_ID);
    Serializable.Mat mat = (Serializable.Mat) tuple.getValueByField(FIELD_FRAME_MAT);
    int patchCount = tuple.getIntegerByField(FIELD_PATCH_COUNT);
    if (frameMap.containsKey(frameId)) {
      if (Debug.topologyDebugOutput)
        System.err.println(this.getClass() + "#" + "processFrame(): Received duplicate frame");
    } else {
      frameMap.put(frameId, mat);
    }
    if (patchQueue.containsKey(frameId)) {
      Queue<Serializable.PatchIdentifier> queue = patchQueue.get(frameId);
      while (!queue.isEmpty()) {
        Serializable.PatchIdentifier hostPatch = queue.poll();

        List<Serializable.Rect> detectedLogoList = new ArrayList<>();
        SIFTfeatures sifTfeatures =
            new SIFTfeatures(sift, mat.toJavaCVMat(), hostPatch.roi.toJavaCVRect(), true);

        for (int logoIndex = 0; logoIndex < detectors.size(); logoIndex++) {
          StormVideoLogoDetectorGamma detector = detectors.get(logoIndex);
          // detector.detectLogosInRoi(mat.toJavaCVMat(), hostPatch.roi.toJavaCVRect());
          detector.detectLogosByFeatures(sifTfeatures);

          Serializable.Rect detectedLogo = detector.getFoundRect();
          if (detectedLogo != null) {
            collector.emit(
                LOGO_TEMPLATE_UPDATE_STREAM,
                new Values(hostPatch, detectedLogo, detector.getParentIdentifier(), logoIndex));
          }
          detectedLogoList.add(detectedLogo);
        }
        collector.emit(
            DETECTED_LOGO_STREAM,
            tuple,
            new Values(frameId, hostPatch, detectedLogoList, patchCount));
      }
    } else {
      // patchQueue.put(frameId, new LinkedList<>());
    }
    if (templateQueue.containsKey(frameId)) {
      Queue<LogoTemplateUpdateBeta> queue = templateQueue.get(frameId);
      while (!queue.isEmpty()) {
        LogoTemplateUpdateBeta update = queue.poll();
        Serializable.Rect roi = update.detectedLogoRect;
        Serializable.PatchIdentifier hostPatchIdentifier = update.hostPatchIdentifier;
        Serializable.PatchIdentifier parent = update.parentIdentifier;
        int logoIndex = update.logoIndex;
        /// detector.addTemplateByRect(hostPatchIdentifier, mat, roi);
        /// detector.incrementPriority(parent, 1);
        detectors.get(logoIndex).addTemplateByRect(hostPatchIdentifier, mat, roi);
        detectors.get(logoIndex).incrementPriority(parent, 1);
      }
    } else {
      // templateQueue.put(frameId, new LinkedList<>());
    }
  }