title: darknet_images.py doesn't detect any objects. Darknet YOLOv4
body: <p>So I'm running the default darknet_images.py script in pycharm (the one from Alexey's github repo) and when I give the img path, the img shows but the bounding boxes don't. I tried to solve the problem but couldn't find a solution. I found that my predictions variable is empty(in the main() function:
  <code>image, detections = image_detection(image_name, network, class_names, class_colors, args.thresh ) </code>
  Just in case I am missing something, I'll print here the darknet.py code and darknet_images.py code.
  darknet.py:</p>
  <pre><code>#!python3
  &quot;&quot;&quot;
  Python 3 wrapper for identifying objects in images
  Requires DLL compilation
  Both the GPU and no-GPU version should be compiled; the no-GPU version should be renamed &quot;yolo_cpp_dll_nogpu.dll&quot;.
  On a GPU system, you can force CPU evaluation by any of:
  - Set global variable DARKNET_FORCE_CPU to True
  - Set environment variable CUDA_VISIBLE_DEVICES to -1
  - Set environment variable &quot;FORCE_CPU&quot; to &quot;true&quot;
  - Set environment variable &quot;DARKNET_PATH&quot; to path darknet lib .so (for Linux)
  Directly viewing or returning bounding-boxed images requires scikit-image to be installed (`pip install scikit-image`)
  Original *nix 2.7: https://github.com/pjreddie/darknet/blob/0f110834f4e18b30d5f101bf8f1724c34b7b83db/python/darknet.py
  Windows Python 2.7 version: https://github.com/AlexeyAB/darknet/blob/fc496d52bf22a0bb257300d3c79be9cd80e722cb/build/darknet/x64/darknet.py
  @author: Philip Kahn
  @date: 20180503
  &quot;&quot;&quot;
  from ctypes import *
  import math
  import random
  import os
  
  
  class BOX(Structure):
      _fields_ = [(&quot;x&quot;, c_float),
                  (&quot;y&quot;, c_float),
                  (&quot;w&quot;, c_float),
                  (&quot;h&quot;, c_float)]
  
  
  class DETECTION(Structure):
      _fields_ = [(&quot;bbox&quot;, BOX),
                  (&quot;classes&quot;, c_int),
                  (&quot;prob&quot;, POINTER(c_float)),
                  (&quot;mask&quot;, POINTER(c_float)),
                  (&quot;objectness&quot;, c_float),
                  (&quot;sort_class&quot;, c_int),
                  (&quot;uc&quot;, POINTER(c_float)),
                  (&quot;points&quot;, c_int),
                  (&quot;embeddings&quot;, POINTER(c_float)),
                  (&quot;embedding_size&quot;, c_int),
                  (&quot;sim&quot;, c_float),
                  (&quot;track_id&quot;, c_int)]
  
  class DETNUMPAIR(Structure):
      _fields_ = [(&quot;num&quot;, c_int),
                  (&quot;dets&quot;, POINTER(DETECTION))]
  
  
  class IMAGE(Structure):
      _fields_ = [(&quot;w&quot;, c_int),
                  (&quot;h&quot;, c_int),
                  (&quot;c&quot;, c_int),
                  (&quot;data&quot;, POINTER(c_float))]
  
  
  class METADATA(Structure):
      _fields_ = [(&quot;classes&quot;, c_int),
                  (&quot;names&quot;, POINTER(c_char_p))]
  
  
  def network_width(net):
      return lib.network_width(net)
  
  
  def network_height(net):
      return lib.network_height(net)
  
  
  def bbox2points(bbox):
      &quot;&quot;&quot;
      From bounding box yolo format
      to corner points cv2 rectangle
      &quot;&quot;&quot;
      x, y, w, h = bbox
      xmin = int(round(x - (w / 2)))
      xmax = int(round(x + (w / 2)))
      ymin = int(round(y - (h / 2)))
      ymax = int(round(y + (h / 2)))
      return xmin, ymin, xmax, ymax
  
  
  def class_colors(names):
      &quot;&quot;&quot;
      Create a dict with one random BGR color for each
      class name
      &quot;&quot;&quot;
      return {name: (
          random.randint(0, 255),
          random.randint(0, 255),
          random.randint(0, 255)) for name in names}
  
  
  def load_network(config_file, data_file, weights, batch_size=1):
      &quot;&quot;&quot;
      load model description and weights from config files
      args:
          config_file (str): path to .cfg model file
          data_file (str): path to .data model file
          weights (str): path to weights
      returns:
          network: trained model
          class_names
          class_colors
      &quot;&quot;&quot;
      network = load_net_custom(
          config_file.encode(&quot;ascii&quot;),
          weights.encode(&quot;ascii&quot;), 0, batch_size)
      metadata = load_meta(data_file.encode(&quot;ascii&quot;))
      class_names = [metadata.names[i].decode(&quot;ascii&quot;) for i in range(metadata.classes)]
      colors = class_colors(class_names)
      return network, class_names, colors
  
  
  def print_detections(detections, coordinates=False):
      print(&quot;\nObjects:&quot;)
      for label, confidence, bbox in detections:
          x, y, w, h = bbox
          if coordinates:
              print(&quot;{}: {}%    (left_x: {:.0f}   top_y:  {:.0f}   width:   {:.0f}   height:  {:.0f})&quot;.format(label, confidence, x, y, w, h))
          else:
              print(&quot;{}: {}%&quot;.format(label, confidence))
  
  
  def draw_boxes(detections, image, colors):
      import cv2
      for label, confidence, bbox in detections:
          left, top, right, bottom = bbox2points(bbox)
          cv2.rectangle(image, (left, top), (right, bottom), colors[label], 1)
          cv2.putText(image, &quot;{} [{:.2f}]&quot;.format(label, float(confidence)),
                      (left, top - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.5,
                      colors[label], 2)
      return image
  
  
  def decode_detection(detections):
      decoded = []
      for label, confidence, bbox in detections:
          confidence = str(round(confidence * 100, 2))
          decoded.append((str(label), confidence, bbox))
      return decoded
  
  
  def remove_negatives(detections, class_names, num):
      &quot;&quot;&quot;
      Remove all classes with 0% confidence within the detection
      &quot;&quot;&quot;
      predictions = []
      for j in range(num):
          for idx, name in enumerate(class_names):
              if detections[j].prob[idx] &gt; 0:
                  bbox = detections[j].bbox
                  bbox = (bbox.x, bbox.y, bbox.w, bbox.h)
                  predictions.append((name, detections[j].prob[idx], (bbox)))
      return predictions
  
  
  def detect_image(network, class_names, image, thresh=.5, hier_thresh=.5, nms=.45):
      &quot;&quot;&quot;
          Returns a list with highest confidence class and their bbox
      &quot;&quot;&quot;
      pnum = pointer(c_int(0))
      predict_image(network, image)
      detections = get_network_boxes(network, image.w, image.h,
                                     thresh, hier_thresh, None, 0, pnum, 0)
      num = pnum[0]
      if nms:
          do_nms_sort(detections, num, len(class_names), nms)
      predictions = remove_negatives(detections, class_names, num)
      predictions = decode_detection(predictions)
      free_detections(detections, num)
      return sorted(predictions, key=lambda x: x[1])
  
  
  #  lib = CDLL(&quot;/home/pjreddie/documents/darknet/libdarknet.so&quot;, RTLD_GLOBAL)
  #  lib = CDLL(&quot;libdarknet.so&quot;, RTLD_GLOBAL)
  hasGPU = True
  if os.name == &quot;nt&quot;:
      cwd = os.path.dirname(__file__)
      os.environ['PATH'] = cwd + ';' + os.environ['PATH']
      winGPUdll = os.path.join(cwd, &quot;yolo_cpp_dll.dll&quot;)
      winNoGPUdll = os.path.join(cwd, &quot;yolo_cpp_dll_nogpu.dll&quot;)
      envKeys = list()
      for k, v in os.environ.items():
          envKeys.append(k)
      try:
          try:
              tmp = os.environ[&quot;FORCE_CPU&quot;].lower()
              if tmp in [&quot;1&quot;, &quot;true&quot;, &quot;yes&quot;, &quot;on&quot;]:
                  raise ValueError(&quot;ForceCPU&quot;)
              else:
                  print(&quot;Flag value {} not forcing CPU mode&quot;.format(tmp))
          except KeyError:
              # We never set the flag
              if 'CUDA_VISIBLE_DEVICES' in envKeys:
                  if int(os.environ['CUDA_VISIBLE_DEVICES']) &lt; 0:
                      raise ValueError(&quot;ForceCPU&quot;)
              try:
                  global DARKNET_FORCE_CPU
                  if DARKNET_FORCE_CPU:
                      raise ValueError(&quot;ForceCPU&quot;)
              except NameError as cpu_error:
                  print(cpu_error)
          if not os.path.exists(winGPUdll):
              raise ValueError(&quot;NoDLL&quot;)
          lib = CDLL(winGPUdll, RTLD_GLOBAL)
      except (KeyError, ValueError):
          hasGPU = False
          if os.path.exists(winNoGPUdll):
              lib = CDLL(winNoGPUdll, RTLD_GLOBAL)
              print(&quot;Notice: CPU-only mode&quot;)
          else:
              # Try the other way, in case no_gpu was compile but not renamed
              lib = CDLL(winGPUdll, RTLD_GLOBAL)
              print(&quot;Environment variables indicated a CPU run, but we didn't find {}. Trying a GPU run anyway.&quot;.format(winNoGPUdll))
  else:
      lib = CDLL(os.path.join(
          os.environ.get('DARKNET_PATH', './'),
          &quot;libdarknet.so&quot;), RTLD_GLOBAL)
  lib.network_width.argtypes = [c_void_p]
  lib.network_width.restype = c_int
  lib.network_height.argtypes = [c_void_p]
  lib.network_height.restype = c_int
  
  copy_image_from_bytes = lib.copy_image_from_bytes
  copy_image_from_bytes.argtypes = [IMAGE,c_char_p]
  
  predict = lib.network_predict_ptr
  predict.argtypes = [c_void_p, POINTER(c_float)]
  predict.restype = POINTER(c_float)
  
  if hasGPU:
      set_gpu = lib.cuda_set_device
      set_gpu.argtypes = [c_int]
  
  init_cpu = lib.init_cpu
  
  make_image = lib.make_image
  make_image.argtypes = [c_int, c_int, c_int]
  make_image.restype = IMAGE
  
  get_network_boxes = lib.get_network_boxes
  get_network_boxes.argtypes = [c_void_p, c_int, c_int, c_float, c_float, POINTER(c_int), c_int, POINTER(c_int), c_int]
  get_network_boxes.restype = POINTER(DETECTION)
  
  make_network_boxes = lib.make_network_boxes
  make_network_boxes.argtypes = [c_void_p]
  make_network_boxes.restype = POINTER(DETECTION)
  
  free_detections = lib.free_detections
  free_detections.argtypes = [POINTER(DETECTION), c_int]
  
  free_batch_detections = lib.free_batch_detections
  free_batch_detections.argtypes = [POINTER(DETNUMPAIR), c_int]
  
  free_ptrs = lib.free_ptrs
  free_ptrs.argtypes = [POINTER(c_void_p), c_int]
  
  network_predict = lib.network_predict_ptr
  network_predict.argtypes = [c_void_p, POINTER(c_float)]
  
  reset_rnn = lib.reset_rnn
  reset_rnn.argtypes = [c_void_p]
  
  load_net = lib.load_network
  load_net.argtypes = [c_char_p, c_char_p, c_int]
  load_net.restype = c_void_p
  
  load_net_custom = lib.load_network_custom
  load_net_custom.argtypes = [c_char_p, c_char_p, c_int, c_int]
  load_net_custom.restype = c_void_p
  
  free_network_ptr = lib.free_network_ptr
  free_network_ptr.argtypes = [c_void_p]
  free_network_ptr.restype = c_void_p
  
  do_nms_obj = lib.do_nms_obj
  do_nms_obj.argtypes = [POINTER(DETECTION), c_int, c_int, c_float]
  
  do_nms_sort = lib.do_nms_sort
  do_nms_sort.argtypes = [POINTER(DETECTION), c_int, c_int, c_float]
  
  free_image = lib.free_image
  free_image.argtypes = [IMAGE]
  
  letterbox_image = lib.letterbox_image
  letterbox_image.argtypes = [IMAGE, c_int, c_int]
  letterbox_image.restype = IMAGE
  
  load_meta = lib.get_metadata
  lib.get_metadata.argtypes = [c_char_p]
  lib.get_metadata.restype = METADATA
  
  load_image = lib.load_image_color
  load_image.argtypes = [c_char_p, c_int, c_int]
  load_image.restype = IMAGE
  
  rgbgr_image = lib.rgbgr_image
  rgbgr_image.argtypes = [IMAGE]
  
  predict_image = lib.network_predict_image
  predict_image.argtypes = [c_void_p, IMAGE]
  predict_image.restype = POINTER(c_float)
  
  predict_image_letterbox = lib.network_predict_image_letterbox
  predict_image_letterbox.argtypes = [c_void_p, IMAGE]
  predict_image_letterbox.restype = POINTER(c_float)
  
  network_predict_batch = lib.network_predict_batch
  network_predict_batch.argtypes = [c_void_p, IMAGE, c_int, c_int, c_int,
                                    c_float, c_float, POINTER(c_int), c_int, c_int]
  network_predict_batch.restype = POINTER(DETNUMPAIR)
  </code></pre>
  <p>darknet_images.py:</p>
  <pre><code>import argparse
  import os
  import glob
  import random
  import darknet
  import time
  import cv2
  import numpy as np
  import darknet
  
  
  def parser():
      parser = argparse.ArgumentParser(description=&quot;YOLO Object Detection&quot;)
      parser.add_argument(&quot;--input&quot;, type=str, default=&quot;&quot;,
                          help=&quot;image source. It can be a single image, a&quot;
                               &quot;txt with paths to them, or a folder. Image valid&quot;
                               &quot; formats are jpg, jpeg or png.&quot;
                               &quot;If no input is given, &quot;)
      parser.add_argument(&quot;--batch_size&quot;, default=1, type=int,
                          help=&quot;number of images to be processed at the same time&quot;)
      parser.add_argument(&quot;--weights&quot;, default=&quot;yolov4.weights&quot;,
                          help=&quot;yolo weights path&quot;)
      parser.add_argument(&quot;--dont_show&quot;, action='store_true',
                          help=&quot;windown inference display. For headless systems&quot;)
      parser.add_argument(&quot;--ext_output&quot;, action='store_true',
                          help=&quot;display bbox coordinates of detected objects&quot;)
      parser.add_argument(&quot;--save_labels&quot;, action='store_true',
                          help=&quot;save detections bbox for each image in yolo format&quot;)
      parser.add_argument(&quot;--config_file&quot;, default=&quot;./cfg/yolov4.cfg&quot;,
                          help=&quot;path to config file&quot;)
      parser.add_argument(&quot;--data_file&quot;, default=&quot;./cfg/coco.data&quot;,
                          help=&quot;path to data file&quot;)
      parser.add_argument(&quot;--thresh&quot;, type=float, default=.25,
                          help=&quot;remove detections with lower confidence&quot;)
      return parser.parse_args()
  
  
  def check_arguments_errors(args):
      assert 0 &lt; args.thresh &lt; 1, &quot;Threshold should be a float between zero and one (non-inclusive)&quot;
      if not os.path.exists(args.config_file):
          raise(ValueError(&quot;Invalid config path {}&quot;.format(os.path.abspath(args.config_file))))
      if not os.path.exists(args.weights):
          raise(ValueError(&quot;Invalid weight path {}&quot;.format(os.path.abspath(args.weights))))
      if not os.path.exists(args.data_file):
          raise(ValueError(&quot;Invalid data file path {}&quot;.format(os.path.abspath(args.data_file))))
      if args.input and not os.path.exists(args.input):
          raise(ValueError(&quot;Invalid image path {}&quot;.format(os.path.abspath(args.input))))
  
  
  def check_batch_shape(images, batch_size):
      &quot;&quot;&quot;
          Image sizes should be the same width and height
      &quot;&quot;&quot;
      shapes = [image.shape for image in images]
      if len(set(shapes)) &gt; 1:
          raise ValueError(&quot;Images don't have same shape&quot;)
      if len(shapes) &gt; batch_size:
          raise ValueError(&quot;Batch size higher than number of images&quot;)
      return shapes[0]
  
  
  def load_images(images_path):
      &quot;&quot;&quot;
      If image path is given, return it directly
      For txt file, read it and return each line as image path
      In other case, it's a folder, return a list with names of each
      jpg, jpeg and png file
      &quot;&quot;&quot;
      input_path_extension = images_path.split('.')[-1]
      if input_path_extension in ['jpg', 'jpeg', 'png']:
          return [images_path]
      elif input_path_extension == &quot;txt&quot;:
          with open(images_path, &quot;r&quot;) as f:
              return f.read().splitlines()
      else:
          return glob.glob(
              os.path.join(images_path, &quot;*.jpg&quot;)) + \
                 glob.glob(os.path.join(images_path, &quot;*.png&quot;)) + \
                 glob.glob(os.path.join(images_path, &quot;*.jpeg&quot;))
  
  
  def prepare_batch(images, network, channels=3):
      width = darknet.network_width(network)
      height = darknet.network_height(network)
  
      darknet_images = []
      for image in images:
          image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
          image_resized = cv2.resize(image_rgb, (width, height),
                                     interpolation=cv2.INTER_LINEAR)
          custom_image = image_resized.transpose(2, 0, 1)
          darknet_images.append(custom_image)
  
      batch_array = np.concatenate(darknet_images, axis=0)
      batch_array = np.ascontiguousarray(batch_array.flat, dtype=np.float32)/255.0
      darknet_images = batch_array.ctypes.data_as(darknet.POINTER(darknet.c_float))
      return darknet.IMAGE(width, height, channels, darknet_images)
  
  
  def image_detection(image_path, network, class_names, class_colors, thresh):
      # Darknet doesn't accept numpy images.
      # Create one with image we reuse for each detect
      width = darknet.network_width(network)
      height = darknet.network_height(network)
      darknet_image = darknet.make_image(width, height, 3)
  
      image = cv2.imread(image_path)
      image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
      image_resized = cv2.resize(image_rgb, (width, height),
                                 interpolation=cv2.INTER_LINEAR)
  
      darknet.copy_image_from_bytes(darknet_image, image_resized.tobytes())
      detections = darknet.detect_image(network, class_names, darknet_image, thresh=thresh)
      darknet.free_image(darknet_image)
      image = darknet.draw_boxes(detections, image_resized, class_colors)
      return cv2.cvtColor(image, cv2.COLOR_BGR2RGB), detections
  
  
  def batch_detection(network, images, class_names, class_colors,
                      thresh=0.25, hier_thresh=.5, nms=.45, batch_size=4):
      image_height, image_width, _ = check_batch_shape(images, batch_size)
      darknet_images = prepare_batch(images, network)
      batch_detections = darknet.network_predict_batch(network, darknet_images, batch_size, image_width,
                                                       image_height, thresh, hier_thresh, None, 0, 0)
      batch_predictions = []
      for idx in range(batch_size):
          num = batch_detections[idx].num
          detections = batch_detections[idx].dets
          if nms:
              darknet.do_nms_obj(detections, num, len(class_names), nms)
          predictions = darknet.remove_negatives(detections, class_names, num)
          images[idx] = darknet.draw_boxes(predictions, images[idx], class_colors)
          batch_predictions.append(predictions)
      darknet.free_batch_detections(batch_detections, batch_size)
      return images, batch_predictions
  
  
  def image_classification(image, network, class_names):
      width = darknet.network_width(network)
      height = darknet.network_height(network)
      image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
      image_resized = cv2.resize(image_rgb, (width, height),
                                 interpolation=cv2.INTER_LINEAR)
      darknet_image = darknet.make_image(width, height, 3)
      darknet.copy_image_from_bytes(darknet_image, image_resized.tobytes())
      detections = darknet.predict_image(network, darknet_image)
      predictions = [(name, detections[idx]) for idx, name in enumerate(class_names)]
      darknet.free_image(darknet_image)
      return sorted(predictions, key=lambda x: -x[1])
  
  
  def convert2relative(image, bbox):
      &quot;&quot;&quot;
      YOLO format use relative coordinates for annotation
      &quot;&quot;&quot;
      x, y, w, h = bbox
      height, width, _ = image.shape
      return x/width, y/height, w/width, h/height
  
  
  def save_annotations(name, image, detections, class_names):
      &quot;&quot;&quot;
      Files saved with image_name.txt and relative coordinates
      &quot;&quot;&quot;
      file_name = os.path.splitext(name)[0] + &quot;.txt&quot;
      with open(file_name, &quot;w&quot;) as f:
          for label, confidence, bbox in detections:
              x, y, w, h = convert2relative(image, bbox)
              label = class_names.index(label)
              f.write(&quot;{} {:.4f} {:.4f} {:.4f} {:.4f} {:.4f}\n&quot;.format(label, x, y, w, h, float(confidence)))
  
  
  def batch_detection_example():
      args = parser()
      check_arguments_errors(args)
      batch_size = 3
      random.seed(3)  # deterministic bbox colors
      network, class_names, class_colors = darknet.load_network(
          args.config_file,
          args.data_file,
          args.weights,
          batch_size=batch_size
      )
      image_names = ['data/horses.jpg', 'data/horses.jpg', 'data/eagle.jpg']
      images = [cv2.imread(image) for image in image_names]
      images, detections,  = batch_detection(network, images, class_names,
                                             class_colors, batch_size=batch_size)
      for name, image in zip(image_names, images):
          cv2.imwrite(name.replace(&quot;data/&quot;, &quot;&quot;), image)
      print(detections)
  
  
  def main():
      args = parser()
      check_arguments_errors(args)
  
      random.seed(3)  # deterministic bbox colors
      network, class_names, class_colors = darknet.load_network(
          args.config_file,
          args.data_file,
          args.weights,
          batch_size=args.batch_size
      )
  
      images = load_images(args.input)
  
      index = 0
      while True:
          # loop asking for new image paths if no list is given
          if args.input:
              if index &gt;= len(images):
                  break
              image_name = images[index]
          else:
              image_name = input(&quot;Enter Image Path: &quot;)
          prev_time = time.time()
          image, detections = image_detection(
              image_name, network, class_names, class_colors, args.thresh
          )
          if args.save_labels:
              save_annotations(image_name, image, detections, class_names)
          darknet.print_detections(detections, args.ext_output)
          fps = int(1/(time.time() - prev_time))
          print(&quot;FPS: {}&quot;.format(fps))
          if not args.dont_show:
              cv2.imshow('Inference', image)
              if cv2.waitKey() &amp; 0xFF == ord('q'):
                  break
          index += 1
  
  
  if __name__ == &quot;__main__&quot;:
      # unconmment next line for an example of batch processing
      # batch_detection_example()
      main()
  </code></pre>