class_docstr: Find duplicates using CNN and/or generate CNN encodings given a single image or a directory of images.
  
  The module can be used for 2 purposes: Encoding generation and duplicate detection.
  - Encodings generation:
  To propagate an image through a Convolutional Neural Network architecture and generate encodings. The generated
  encodings can be used at a later time for deduplication. Using the method 'encode_image', the CNN encodings for a
  single image can be obtained while the 'encode_images' method can be used to get encodings for all images in a
  directory.
  
  - Duplicate detection:
  Find duplicates either using the encoding mapping generated previously using 'encode_images' or using a Path to the
  directory that contains the images that need to be deduplicated. 'find_duplicates' and 'find_duplicates_to_remove'
  methods are provided to accomplish these tasks.
class_docstr_tok: ["Find","duplicates","using","CNN","and\/or","generate","CNN","encodings","given","a","single","image","or","a","directory","of","images",".","The","module","can","be","used","for","2","purposes",":","Encoding","generation","and","duplicate","detection",".","-","Encodings","generation",":","To","propagate","an","image","through","a","Convolutional","Neural","Network","architecture","and","generate","encodings",".","The","generated","encodings","can","be","used","at","a","later","time","for","deduplication",".","Using","the","method","'encode_image","'",",","the","CNN","encodings","for","a","single","image","can","be","obtained","while","the","'encode_images","'","method","can","be","used","to","get","encodings","for","all","images","in","a","directory",".","-","Duplicate","detection",":","Find","duplicates","either","using","the","encoding","mapping","generated","previously","using","'encode_images","'","or","using","a","Path","to","the","directory","that","contains","the","images","that","need","to","be","deduplicated",".","'find_duplicates","'","and","'find_duplicates_to_remove'","methods","are","provided","to","accomplish","these","tasks","."]
docstr: Generate CNN encodings for all images in a given directory of images.
  Args:
      image_dir: Path to the image directory.
      recursive: Optional, find images recursively in a nested image directory structure.
      num_workers: Optional, number of cpu cores to use for multiprocessing encoding generation (supported only on linux platform), set to 0 by default. 0 disables multiprocessing.
  
  Returns:
      A dictionary that contains a mapping of filenames and corresponding numpy array of CNN encodings.
docstr_tok: ["Generate","CNN","encodings","for","all","images","in","a","given","directory","of","images",".","Args",":","image_dir",":","Path","to","the","image","directory",".","recursive",":","Optional",",","find","images","recursively","in","a","nested","image","directory","structure",".","num_workers",":","Optional",",","number","of","cpu","cores","to","use","for","multiprocessing","encoding","generation","(","supported","only","on","linux","platform",")",",","set","to","0","by","default",".","0","disables","multiprocessing",".","Returns",":","A","dictionary","that","contains","a","mapping","of","filenames","and","corresponding","numpy","array","of","CNN","encodings","."]
code: def _get_cnn_features_batch(
      self,
      image_dir: PurePath,
      recursive: Optional[bool] = False,
      num_workers: int = 0,
  ) -> Dict[str, np.ndarray]:
      """
      Generate CNN encodings for all images in a given directory of images.
      Args:
          image_dir: Path to the image directory.
          recursive: Optional, find images recursively in a nested image directory structure.
          num_workers: Optional, number of cpu cores to use for multiprocessing encoding generation (supported only on linux platform), set to 0 by default. 0 disables multiprocessing.
  
      Returns:
          A dictionary that contains a mapping of filenames and corresponding numpy array of CNN encodings.
      """
      self.logger.info("Start: Image encoding generation")
      self.dataloader = img_dataloader(
          image_dir=image_dir,
          batch_size=self.batch_size,
          basenet_preprocess=self.apply_preprocess,
          recursive=recursive,
          num_workers=num_workers,
      )
  
      feat_arr, all_filenames = [], []
      bad_im_count = 0
  
      with torch.no_grad():
          for ims, filenames, bad_images in self.dataloader:
              arr = self.model(ims.to(self.device))
              feat_arr.extend(arr)
              all_filenames.extend(filenames)
              if bad_images:
                  bad_im_count += 1
  
      if bad_im_count:
          self.logger.info(
              f"Found {bad_im_count} bad images, ignoring for encoding generation .."
          )
  
      feat_vec = torch.stack(feat_arr).squeeze()
      feat_vec = (
          feat_vec.detach().numpy()
          if self.device.type == "cpu"
          else feat_vec.detach().cpu().numpy()
      )
      valid_image_files = [
          filename for filename in all_filenames if filename
      ]
      self.logger.info("End: Image encoding generation")
  
      filenames = generate_relative_names(image_dir, valid_image_files)
      if (
          len(feat_vec.shape) == 1
      ):  # can happen when encode_images is called on a directory containing a single image
          self.encoding_map = {filenames[0]: feat_vec}
      else:
          self.encoding_map = {
              j: feat_vec[i, :] for i, j in enumerate(filenames)
          }
      return self.encoding_map
  
imports: from pathlib import Path, PurePath
  import sys
  from typing import Dict, List, Optional, Union
  import warnings
  from multiprocessing import cpu_count
  import numpy
  from PIL import Image
  import torch
  from imagededup.handlers.search.retrieval import get_cosine_similarity
  from imagededup.utils.data_generator import img_dataloader
  from imagededup.utils.models import CustomModel, MobilenetV3, DEFAULT_MODEL_NAME
  from imagededup.utils.general_utils import generate_relative_names, get_files_to_remove, save_json
  from imagededup.utils.image_utils import expand_image_array_cnn, load_image, preprocess_image
  from imagededup.utils.logger import return_logger
label_desc: Use image node_id 5 for calling the CNN obj's underlying member method code with example usage: obj._get_cnn_features_batch(image_dir, recursive, num_workers) and returns: self