// Fields("hostPatchIdentifier", "detectedLogoRect", "parentIdentifier"));
  private void processNewTemplate(Tuple tuple) {
    Serializable.PatchIdentifier receivedPatchIdentifier =
        (Serializable.PatchIdentifier) tuple.getValueByField(FIELD_HOST_PATCH_IDENTIFIER);
    // TODO: This container could become very large, need to clear it after some time
    // Modified by Tom, use LinkedHashMap for receivedUpdatesFrom, it will automatically remove the
    // oldest
    // element when its size beyond some threshold.
    if (!receivedUpdatesFrom.containsKey(receivedPatchIdentifier)) {
      receivedUpdatesFrom.put(receivedPatchIdentifier, Boolean.TRUE);
      Serializable.Rect roi = (Serializable.Rect) tuple.getValueByField(FIELD_DETECTED_LOGO_RECT);
      Serializable.PatchIdentifier parent =
          (Serializable.PatchIdentifier) tuple.getValueByField(FIELD_PARENT_PATCH_IDENTIFIER);
      int logoIndex = tuple.getIntegerByField(FIELD_LOGO_INDEX);

      int frameId = receivedPatchIdentifier.frameId;
      if (frameMap.containsKey(frameId)) {
        Serializable.Mat mat = frameMap.get(frameId);

        detectors.get(logoIndex).addTemplateByRect(receivedPatchIdentifier, mat, roi);
        detectors.get(logoIndex).incrementPriority(parent, 1);
      } else {
        if (!templateQueue.containsKey(frameId)) templateQueue.put(frameId, new LinkedList<>());
        templateQueue
            .get(frameId)
            .add(new LogoTemplateUpdateBeta(receivedPatchIdentifier, roi, parent, logoIndex));
      }

    } else {
      if (Debug.topologyDebugOutput)
        System.out.println("PatchProcessorBolt: Received duplicate message");
    }
  }
  // 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);
    }
  }