{
  "source_file": "0930",
  "source_platform": "技术平台",
  "author": "Adrian Rosebrock / PyImageSearch",
  "title_listed": "YOLO Object Detection with OpenCV",
  "keywords": "YOLO,目标检测,OpenCV",
  "domain": "图像处理",
  "content_type": "教程",
  "is_paid_flag": "否",
  "url": "https://pyimagesearch.com/2018/11/12/yolo-object-detection-with-opencv/",
  "publish_date": "2018-11",
  "corpus_stage": "预训练/SFT",
  "notes": "用OpenCV做YOLO目标检测",
  "id": "38db5bb25336",
  "collected_at": "2026-10-02T17:17:44",
  "title": "YOLO object detection with OpenCV - PyImageSearch",
  "body_markdown": "Click here to download the source code to this post\nIn this tutorial, you’ll learn how to use the YOLO object detector to detect objects in both images and video streams using Deep Learning, OpenCV, and Python.\nBy applying object detection, you’ll not only be able to determine\nwhat\nis in an image but also\nwhere\na given object resides!\nWe’ll start with a brief discussion of the YOLO object detector, including how the object detector works.\nFrom there we’ll use OpenCV, Python, and deep learning to:\nApply the YOLO object detector to images\nApply YOLO to video streams\nWe’ll wrap up the tutorial by discussing some of the limitations and drawbacks of the YOLO object detector, including some of my personal tips and suggestions.\nA dataset with annotated objects is critical for understanding and implementing YOLO object detection. It aids in building a model that can detect and classify various objects in images or videos.\nRoboflow\nhas free tools for each stage of the computer vision pipeline that will streamline your workflows and supercharge your productivity.\nSign up or Log in to your\nRoboflow account\nto access state of the art dataset libaries and revolutionize your computer vision pipeline.\nYou can start by choosing your own datasets or using our\nPyimageSearch’s assorted library of useful datasets\n.\nBring data in any of 40+ formats to\nRoboflow\n, train using any state-of-the-art model architectures, deploy across multiple platforms (API, NVIDIA, browser, iOS, etc), and connect to applications or 3rd party tools.\nTo learn how to use YOLO for object detection with OpenCV,\njust keep reading!\nUpdate July 2021:\nAdded section on YOLO v4 and YOLO v5, including how they can be incorporated into OpenCV and PyTorch projects.\nLooking for the source code to this post?\nJump Right To The Downloads Section\nYOLO Object detection with OpenCV\nIn the rest of this tutorial we’ll:\nDiscuss the YOLO object detector model and architecture\nUtilize YOLO to detect objects in images\nApply YOLO to detect objects in video streams\nDiscuss some of the limitations and drawbacks of the YOLO object detector\nLet’s dive in!\nNote: This post was last updated on February 5th, 2022 to update images, references, and formatting.  Enjoy!\nWhat is the YOLO object detector?\nFigure 1:\nA simplified illustration of the YOLO object detector pipeline (\nsource\n). We’ll use YOLO with OpenCV in this blog post.\nWhen it comes to deep learning-based object detection, there are three primary object detectors you’ll encounter:\nR-CNN and their variants, including the original R-CNN, Fast R- CNN, and Faster R-CNN\nSingle Shot Detector (SSDs)\nYOLO\nR-CNNs are one of the first deep learning-based object detectors and are an example of a\ntwo-stage detector.\nIn the first R-CNN publication,\nRich feature hierarchies for accurate object detection and semantic segmentation\n, (2013) Girshick et al. proposed an object detector that required an algorithm such as\nSelective Search\n(or equivalent) to propose candidate bounding boxes that could contain objects.\nThese regions were then passed into a CNN for classification, ultimately leading to one of the first deep learning-based object detectors.\nThe problem with the standard R-CNN method was that it was\npainfully slow\nand not a complete end-to-end object detector.\nGirshick et al. published a second paper in 2015, entitled\nFast R- CNN\n. The Fast R-CNN algorithm made considerable improvements to the original R-CNN, namely increasing accuracy and reducing the time it took to perform a forward pass; however, the model still relied on an external region proposal algorithm.\nIt wasn’t until Girshick et al.’s follow-up 2015 paper,\nFaster R-CNN: Towards Real-Time Object Detection with Region Proposal Networks\n, that R-CNNs became a true end-to-end deep learning object detector by removing the Selective Search requirement and instead relying on a Region Proposal Network (RPN) that is (1) fully convolutional and (2) can predict the object bounding boxes and “objectness” scores (i.e., a score quantifying how likely it is a region of an image may contain an image). The outputs of the RPNs are then passed into the R-CNN component for final classification and labeling.\nWhile R-CNNs tend to be very accurate, the biggest problem with the R-CNN family of networks is their speed — they were incredibly slow, obtaining only 5 FPS on a GPU.\nTo help increase the speed of deep learning-based object detectors, both Single Shot Detectors (SSDs) and YOLO use a\none-stage detector strategy\n.\nThese algorithms treat object detection as a regression problem, taking a given input image and simultaneously learning bounding box coordinates and corresponding class label probabilities.\nIn general, single-stage detectors tend to be less accurate than two-stage detectors\nbut are significantly faster.\nYOLO is a great example of a single stage detector.\nFirst introduced in 2015 by Redmon et al., their paper,\nYou Only Look Once: Unified, Real-Time Object Detection\n, details an object detector capable of super real-time object detection, obtaining\n45 FPS\non a GPU.\nNote:\nA smaller variant of their model called “Fast YOLO” claims to achieve 155 FPS on a GPU.\nYOLO has gone through a number of different iterations, including\nYOLO9000: Better, Faster, Stronger\n(i.e., YOLOv2), capable of detecting over 9,000 object detectors.\nRedmon and Farhadi are able to achieve such a large number of object detections by performing joint training for both object detection and classification. Using joint training the authors trained YOLO9000 simultaneously on both the ImageNet classification dataset and COCO detection dataset. The result is a YOLO model, called YOLO9000, that can predict detections for object classes that don’t have labeled detection data.\nWhile interesting and novel, YOLOv2’s performance was a bit underwhelming given the title and abstract of the paper.\nOn the 156 class version of COCO, YOLO9000 achieved 16% mean Average Precision (mAP), and yes, while YOLO can detect 9,000 separate classes, the accuracy is not quite what we would desire.\nRedmon and Farhadi recently published a new YOLO paper,\nYOLOv3: An Incremental Improvement\n(2018). YOLOv3 is significantly larger than previous models but is, in my opinion, the best one yet out of the YOLO family of object detectors.\nWe’ll be using YOLOv3 in this blog post, in particular, YOLO trained on the COCO dataset.\nThe COCO dataset consists of 80 labels, including, but not limited to:\nPeople\nBicycles\nCars and trucks\nAirplanes\nStop signs and fire hydrants\nAnimals, including cats, dogs, birds, horses, cows, and sheep, to name a few\nKitchen and dining objects, such as wine glasses, cups, forks, knives, spoons, etc.\n… and much more!\nYou can find a full list of what YOLO trained on the COCO dataset can detect\nusing this link\n.\nI’ll wrap up this section by saying that any academic needs to read Redmon’s YOLO papers and tech reports — not only are they novel and insightful, they are incredibly entertaining as well.\nBut seriously, if you do nothing else today\nread the YOLOv3 tech report\n.\nIt’s only 6 pages and one of those pages is just references/citations.\nFurthermore, the tech report is honest in a way that academic papers rarely, if ever, are.\nProject structure\nLet’s take a look at today’s project layout. You can use your OS’s GUI (Finder for OSX, Nautilus for Ubuntu), but you may find it easier and faster to use the\ntree\ncommand in your terminal:\n$ tree\n.\n├── images\n│   ├── baggage_claim.jpg\n│   ├── dining_table.jpg\n│   ├── living_room.jpg\n│   └── soccer.jpg\n├── output\n│   ├── airport_output.avi\n│   ├── car_chase_01_output.avi\n│   ├── car_chase_02_output.avi\n│   └── overpass_output.avi\n├── videos\n│   ├── airport.mp4\n│   ├── car_chase_01.mp4\n│   ├── car_chase_02.mp4\n│   └── overpass.mp4\n├── yolo-coco\n│   ├── coco.names\n│   ├── yolov3.cfg\n│   └── yolov3.weights\n├── yolo.py\n└── yolo_video.py\n\n4 directories, 19 files\nOur project today consists of 4 directories and two Python scripts.\nThe directories (in order of importance) are:\nyolo-coco/\n: The YOLOv3 object detector pre-trained (on the COCO dataset) model files. These were trained by the\nDarknet team\n.\nimages/\n: This folder contains four static images which we’ll perform object detection on for testing and evaluation purposes.\nvideos/\n: After performing object detection with YOLO on images, we’ll process videos in real time. This directory contains four sample videos for you to test with.\noutput/\n: Output videos that have been processed by YOLO and annotated with bounding boxes and class names can go in this folder.\nWe’re reviewing two Python scripts —\nyolo.py\nand\nyolo_video.py\n. The first script is for images and then we’ll take what we learn and apply it to video in the second script.\nAre you ready?\nYOLO object detection in images\nLet’s get started applying the YOLO object detector to images!\nOpen up the\nyolo.py\nfile in your project and insert the following code:\n# import the necessary packages\nimport numpy as np\nimport argparse\nimport time\nimport cv2\nimport os\n\n# construct the argument parse and parse the arguments\nap = argparse.ArgumentParser()\nap.add_argument(\"-i\", \"--image\", required=True,\n\thelp=\"path to input image\")\nap.add_argument(\"-y\", \"--yolo\", required=True,\n\thelp=\"base path to YOLO directory\")\nap.add_argument(\"-c\", \"--confidence\", type=float, default=0.5,\n\thelp=\"minimum probability to filter weak detections\")\nap.add_argument(\"-t\", \"--threshold\", type=float, default=0.3,\n\thelp=\"threshold when applying non-maxima suppression\")\nargs = vars(ap.parse_args())\nAll you need installed for this script is OpenCV 3.4.2+ with Python bindings. You can find my\nOpenCV installation tutorials here\n, just keep in mind that OpenCV 4 is in beta right now — you may run into issues installing or running certain scripts since it’s not an official release. For the time being I recommend going for OpenCV 3.4.2+. You can actually be up and running in less than 5 minutes\nwith pip\nas well.\nFirst, we import our required packages — as long as OpenCV and NumPy are installed, your interpreter will breeze past these lines.\nNow let’s parse four command line arguments. Command line arguments are processed at runtime and allow us to change the inputs to our script from the terminal. If you aren’t familiar with them, I encourage you to read more in my\nprevious tutorial\n. Our command line arguments include:\n--image\n: The path to the input image. We’ll detect objects in this image using YOLO.\n--yolo\n: The base path to the YOLO directory. Our script will then load the required YOLO files in order to perform object detection on the image.\n--confidence\n: Minimum probability to filter weak detections. I’ve given this a default value of 50% (\n0.5\n), but you should feel free to experiment with this value.\n--threshold\n: This is our non-maxima suppression threshold with a default value of\n0.3\n. You can read more about\nnon-maxima suppression here\n.\nAfter parsing, the\nargs\nvariable is now a dictionary containing the key-value pairs for the command line arguments. You’ll see\nargs\na number of times in the rest of this script.\nLet’s load our class labels and set random colors for each:\n# load the COCO class labels our YOLO model was trained on\nlabelsPath = os.path.sep.join([args[\"yolo\"], \"coco.names\"])\nLABELS = open(labelsPath).read().strip().split(\"\\n\")\n\n# initialize a list of colors to represent each possible class label\nnp.random.seed(42)\nCOLORS = np.random.randint(0, 255, size=(len(LABELS), 3),\n\tdtype=\"uint8\")\nHere we load all of our class\nLABELS\n(notice the first command line argument,\nargs[\"yolo\"]\nbeing used) on\nLines 21 and 22\n. Random\nCOLORS\nare then assigned to each label on\nLines 25-27\n.\nLet’s derive the paths to the YOLO weights and configuration files followed by loading YOLO from disk:\n# derive the paths to the YOLO weights and model configuration\nweightsPath = os.path.sep.join([args[\"yolo\"], \"yolov3.weights\"])\nconfigPath = os.path.sep.join([args[\"yolo\"], \"yolov3.cfg\"])\n\n# load our YOLO object detector trained on COCO dataset (80 classes)\nprint(\"[INFO] loading YOLO from disk...\")\nnet = cv2.dnn.readNetFromDarknet(configPath, weightsPath)\nTo load YOLO from disk on\nLine 35\n, we’ll take advantage of OpenCV’s DNN function called\ncv2.dnn.readNetFromDarknet\n. This function requires both a\nconfigPath\nand\nweightsPath\nwhich are established via command line arguments on\nLines 30 and 31\n.\nI cannot stress this enough: you’ll need at least OpenCV 3.4.2 to run this code as it has the updated\ndnn\nmodule required to load YOLO.\nLet’s load the image and send it through the network:\n# load our input image and grab its spatial dimensions\nimage = cv2.imread(args[\"image\"])\n(H, W) = image.shape[:2]\n\n# determine only the *output* layer names that we need from YOLO\nln = net.getLayerNames()\nln = [ln[i[0] - 1] for i in net.getUnconnectedOutLayers()]\n\n# construct a blob from the input image and then perform a forward\n# pass of the YOLO object detector, giving us our bounding boxes and\n# associated probabilities\nblob = cv2.dnn.blobFromImage(image, 1 / 255.0, (416, 416),\n\tswapRB=True, crop=False)\nnet.setInput(blob)\nstart = time.time()\nlayerOutputs = net.forward(ln)\nend = time.time()\n\n# show timing information on YOLO\nprint(\"[INFO] YOLO took {:.6f} seconds\".format(end - start))\nIn this block we:\nLoad the input\nimage\nand extract its dimensions (\nLines 38 and 39\n).\nDetermine the output layer names from the YOLO model (\nLines 42 and 43\n).\nConstruct a\nblob\nfrom the image (\nLines 48 and 49\n). Are you confused about what a blob is or what the\ncv2.dnn.blobFromImage\ndoes? Give\nthis blog post\na read.\nNow that our blob is prepared, we’ll\nPerform a forward pass through our YOLO network (\nLines 50 and 52\n)\nShow the inference time for YOLO (\nLine 56\n)\nWhat good is object detection unless we visualize our results? Let’s take steps now to filter and visualize our results.\nBut first, let’s initialize some lists we’ll need in the process of doing so:\n# initialize our lists of detected bounding boxes, confidences, and\n# class IDs, respectively\nboxes = []\nconfidences = []\nclassIDs = []\nThese lists include:\nboxes\n: Our bounding boxes around the object.\nconfidences\n: The confidence value that YOLO assigns to an object. Lower confidence values indicate that the object might not be what the network thinks it is. Remember from our command line arguments above that we’ll filter out objects that don’t meet the\n0.5\nthreshold.\nclassIDs\n: The detected object’s class label.\nLet’s begin populating these lists with data from our YOLO\nlayerOutputs\n:\n# loop over each of the layer outputs\nfor output in layerOutputs:\n\t# loop over each of the detections\n\tfor detection in output:\n\t\t# extract the class ID and confidence (i.e., probability) of\n\t\t# the current object detection\n\t\tscores = detection[5:]\n\t\tclassID = np.argmax(scores)\n\t\tconfidence = scores[classID]\n\n\t\t# filter out weak predictions by ensuring the detected\n\t\t# probability is greater than the minimum probability\n\t\tif confidence > args[\"confidence\"]:\n\t\t\t# scale the bounding box coordinates back relative to the\n\t\t\t# size of the image, keeping in mind that YOLO actually\n\t\t\t# returns the center (x, y)-coordinates of the bounding\n\t\t\t# box followed by the boxes' width and height\n\t\t\tbox = detection[0:4] * np.array([W, H, W, H])\n\t\t\t(centerX, centerY, width, height) = box.astype(\"int\")\n\n\t\t\t# use the center (x, y)-coordinates to derive the top and\n\t\t\t# and left corner of the bounding box\n\t\t\tx = int(centerX - (width / 2))\n\t\t\ty = int(centerY - (height / 2))\n\n\t\t\t# update our list of bounding box coordinates, confidences,\n\t\t\t# and class IDs\n\t\t\tboxes.append([x, y, int(width), int(height)])\n\t\t\tconfidences.append(float(confidence))\n\t\t\tclassIDs.append(classID)\nThere’s a lot here in this code block — let’s break it down.\nIn this block, we:\nLoop over each of the\nlayerOutputs\n(beginning on\nLine 65\n).\nLoop over each\ndetection\nin\noutput\n(a nested loop beginning on\nLine 67\n).\nExtract the\nclassID\nand\nconfidence\n(\nLines 70-72\n).\nUse the\nconfidence\nto filter out weak detections (\nLine 76\n).\nNow that we’ve filtered out unwanted detections, we’re going to:\nScale bounding box coordinates so we can display them properly on our original image (\nLine 81\n).\nExtract coordinates and dimensions of the bounding box (\nLine 82\n). YOLO returns bounding box coordinates in the form:\n(centerX, centerY, width, and height)\n.\nUse this information to derive the top-left\n(x, y)\n-coordinates of the bounding box (\nLines 86 and 87\n).\nUpdate the\nboxes\n,\nconfidences\n, and\nclassIDs\nlists (\nLines 91-93\n).\nWith this data, we’re now going to apply what is called “non-maxima suppression”:\n# apply non-maxima suppression to suppress weak, overlapping bounding\n# boxes\nidxs = cv2.dnn.NMSBoxes(boxes, confidences, args[\"confidence\"],\n\targs[\"threshold\"])\nYOLO does not apply\nnon-maxima suppression\nfor us, so we need to explicitly apply it.\nApplying non-maxima suppression suppresses significantly overlapping bounding boxes, keeping only the most confident ones.\nNMS also ensures that we do not have any redundant or extraneous bounding boxes.\nTaking advantage of OpenCV’s built-in DNN module implementation of NMS, we perform non-maxima suppression on\nLines 97 and 98\n. All that is required is that we submit our bounding\nboxes\n,\nconfidences\n, as well as both our confidence threshold and NMS threshold.\nIf you’ve been reading this blog, you might be wondering why we didn’t use my\nimutils implementation of NMS\n. The primary reason is that the\nNMSBoxes\nfunction is now working in OpenCV. Previously it failed for some inputs and resulted in an error message. Now that the\nNMSBoxes\nfunction is working, we can use it in our own scripts.\nLet’s draw the boxes and class text on the image!\n# ensure at least one detection exists\nif len(idxs) > 0:\n\t# loop over the indexes we are keeping\n\tfor i in idxs.flatten():\n\t\t# extract the bounding box coordinates\n\t\t(x, y) = (boxes[i][0], boxes[i][1])\n\t\t(w, h) = (boxes[i][2], boxes[i][3])\n\n\t\t# draw a bounding box rectangle and label on the image\n\t\tcolor = [int(c) for c in COLORS[classIDs[i]]]\n\t\tcv2.rectangle(image, (x, y), (x + w, y + h), color, 2)\n\t\ttext = \"{}: {:.4f}\".format(LABELS[classIDs[i]], confidences[i])\n\t\tcv2.putText(image, text, (x, y - 5), cv2.FONT_HERSHEY_SIMPLEX,\n\t\t\t0.5, color, 2)\n\n# show the output image\ncv2.imshow(\"Image\", image)\ncv2.waitKey(0)\nAssuming at least one detection exists (\nLine 101\n), we proceed to loop over\nidxs\ndetermined by non-maxima suppression.\nThen, we simply draw the bounding box and text on\nimage\nusing our random class colors (\nLines 105-113\n).\nFinally, we display our resulting image until the user presses any key on their keyboard (ensuring the window opened by OpenCV is selected and focused).\nTo follow along with this guide, make sure you use the\n“Downloads”\nsection of this tutorial to download the source code, YOLO model, and example images.\nFrom there, open up a terminal and execute the following command:\n$ python yolo.py --image images/baggage_claim.jpg --yolo yolo-coco\n[INFO] loading YOLO from disk...\n[INFO] YOLO took 0.347815 seconds\nFigure 2:\nYOLO with OpenCV is used to detect people and baggage in an airport.\nHere you can see that YOLO has not only detected each person in the input image, but also the suitcases as well!\nFurthermore, if you take a look at the right corner of the image you’ll see that YOLO has also detected the handbag on the lady’s shoulder.\nLet’s try another example:\n$ python yolo.py --image images/living_room.jpg --yolo yolo-coco\n[INFO] loading YOLO from disk...\n[INFO] YOLO took 0.340221 seconds\nFigure 3:\nYOLO object detection with OpenCV is used to detect a person, dog, TV, and chair. The remote is a false-positive detection but looking at the ROI you could imagine that the area does share resemblances to a remote.\nThe image above contains a person (myself) and a dog (Jemma, the family beagle).\nYOLO also detects the TV monitor and a chair as well. I’m particularly impressed that YOLO was able to detect the chair given that it’s handmade, old fashioned “baby high chair”.\nInterestingly, YOLO thinks there is a “remote” in my hand. It’s actually not a remote — it’s the reflection of glass on a VHS tape; however, if you stare at the region it actually does look like it could be a remote.\nThe following example image demonstrates a limitation and weakness of the YOLO object detector:\n$ python yolo.py --image images/dining_table.jpg --yolo yolo-coco\n[INFO] loading YOLO from disk...\n[INFO] YOLO took 0.362369 seconds\nFigure 4:\nYOLO and OpenCV are used for object detection of a dining room table.\nWhile both the wine bottle, dining table, and vase are correctly detected by YOLO, only one of the two wine glasses is properly detected.\nWe discuss why YOLO struggles with objects close together in the\n“Limitations and drawbacks of the YOLO object detector”\nsection below.\nLet’s try one final image:\n$ python yolo.py --image images/soccer.jpg --yolo yolo-coco\n[INFO] loading YOLO from disk...\n[INFO] YOLO took 0.345656 seconds\nFigure 5:\nSoccer players and a soccer ball are detected with OpenCV using the YOLO object detector.\nYOLO is able to correctly detect each of the players on the pitch, including the soccer ball itself. Notice the person in the background who is detected despite the area being highly blurred and partially obscured.\nYOLO object detection in video streams\nNow that we’ve learned how to apply the YOLO object detector to single images, let’s also utilize YOLO to perform object detection in input video files as well.\nOpen up the\nyolo_video.py\nfile and insert the following code:\n# import the necessary packages\nimport numpy as np\nimport argparse\nimport imutils\nimport time\nimport cv2\nimport os\n\n# construct the argument parse and parse the arguments\nap = argparse.ArgumentParser()\nap.add_argument(\"-i\", \"--input\", required=True,\n\thelp=\"path to input video\")\nap.add_argument(\"-o\", \"--output\", required=True,\n\thelp=\"path to output video\")\nap.add_argument(\"-y\", \"--yolo\", required=True,\n\thelp=\"base path to YOLO directory\")\nap.add_argument(\"-c\", \"--confidence\", type=float, default=0.5,\n\thelp=\"minimum probability to filter weak detections\")\nap.add_argument(\"-t\", \"--threshold\", type=float, default=0.3,\n\thelp=\"threshold when applying non-maxima suppression\")\nargs = vars(ap.parse_args())\nWe begin with our imports and command line arguments.\nNotice that this script doesn’t have the\n--image\nargument as before. To take its place, we now have two video-related arguments:\n--input\n: The path to the\ninput\nvideo file.\n--output\n: Our path to the\noutput\nvideo file.\nGiven these arguments, you can now use videos that you record of scenes with your smartphone or videos you find online. You can then process the video file producing an annotated output video. Of course if you want to use your webcam to process a live video stream, that is possible too. Just find examples on PyImageSearch where the\nVideoStream\nclass from\nimutils.video\nis utilized and make some minor changes.\nMoving on, the next block is\nidentical\nto the block from the YOLO image processing script:\n# load the COCO class labels our YOLO model was trained on\nlabelsPath = os.path.sep.join([args[\"yolo\"], \"coco.names\"])\nLABELS = open(labelsPath).read().strip().split(\"\\n\")\n\n# initialize a list of colors to represent each possible class label\nnp.random.seed(42)\nCOLORS = np.random.randint(0, 255, size=(len(LABELS), 3),\n\tdtype=\"uint8\")\n\n# derive the paths to the YOLO weights and model configuration\nweightsPath = os.path.sep.join([args[\"yolo\"], \"yolov3.weights\"])\nconfigPath = os.path.sep.join([args[\"yolo\"], \"yolov3.cfg\"])\n\n# load our YOLO object detector trained on COCO dataset (80 classes)\n# and determine only the *output* layer names that we need from YOLO\nprint(\"[INFO] loading YOLO from disk...\")\nnet = cv2.dnn.readNetFromDarknet(configPath, weightsPath)\nln = net.getLayerNames()\nln = [ln[i[0] - 1] for i in net.getUnconnectedOutLayers()]\nHere we load labels and generate colors followed by loading our YOLO model and determining output layer names.\nNext, we’ll take care of some video-specific tasks:\n# initialize the video stream, pointer to output video file, and\n# frame dimensions\nvs = cv2.VideoCapture(args[\"input\"])\nwriter = None\n(W, H) = (None, None)\n\n# try to determine the total number of frames in the video file\ntry:\n\tprop = cv2.cv.CV_CAP_PROP_FRAME_COUNT if imutils.is_cv2() \\\n\t\telse cv2.CAP_PROP_FRAME_COUNT\n\ttotal = int(vs.get(prop))\n\tprint(\"[INFO] {} total frames in video\".format(total))\n\n# an error occurred while trying to determine the total\n# number of frames in the video file\nexcept:\n\tprint(\"[INFO] could not determine # of frames in video\")\n\tprint(\"[INFO] no approx. completion time can be provided\")\n\ttotal = -1\nIn this block, we:\nOpen a file pointer to the video file for reading frames in the upcoming loop (\nLine 45\n).\nInitialize our video\nwriter\nand frame dimensions (\nLines 46 and 47\n).\nTry to determine the\ntotal\nnumber of frames in the video file so we can estimate how long processing the entire video will take (\nLines 50-61\n).\nNow we’re ready to start processing frames one by one:\n# loop over frames from the video file stream\nwhile True:\n\t# read the next frame from the file\n\t(grabbed, frame) = vs.read()\n\n\t# if the frame was not grabbed, then we have reached the end\n\t# of the stream\n\tif not grabbed:\n\t\tbreak\n\n\t# if the frame dimensions are empty, grab them\n\tif W is None or H is None:\n\t\t(H, W) = frame.shape[:2]\nWe define a\nwhile\nloop (\nLine 64\n) and then we grab our first frame (\nLine 66\n).\nWe make a check to see if it is the last frame of the video. If so we need to\nbreak\nfrom the\nwhile\nloop (\nLines 70 and 71\n).\nNext, we grab the frame dimensions if they haven’t been grabbed yet (\nLines 74 and 75\n).\nNext, let’s perform a forward pass of YOLO, using our current\nframe\nas the input:\n# construct a blob from the input frame and then perform a forward\n\t# pass of the YOLO object detector, giving us our bounding boxes\n\t# and associated probabilities\n\tblob = cv2.dnn.blobFromImage(frame, 1 / 255.0, (416, 416),\n\t\tswapRB=True, crop=False)\n\tnet.setInput(blob)\n\tstart = time.time()\n\tlayerOutputs = net.forward(ln)\n\tend = time.time()\n\n\t# initialize our lists of detected bounding boxes, confidences,\n\t# and class IDs, respectively\n\tboxes = []\n\tconfidences = []\n\tclassIDs = []\nHere we construct a\nblob\nand pass it through the network, obtaining predictions. I’ve surrounded the forward pass operation with time stamps so we can calculate the elapsed time to make predictions on one frame — this will help us estimate the time needed to process the entire video.\nWe’ll then go ahead and initialize the same three lists we used in our previous script:\nboxes\n,\nconfidences\n, and\nclassIDs\n.\nThis next block is, again,\nidentical\nto our previous script:\n# loop over each of the layer outputs\n\tfor output in layerOutputs:\n\t\t# loop over each of the detections\n\t\tfor detection in output:\n\t\t\t# extract the class ID and confidence (i.e., probability)\n\t\t\t# of the current object detection\n\t\t\tscores = detection[5:]\n\t\t\tclassID = np.argmax(scores)\n\t\t\tconfidence = scores[classID]\n\n\t\t\t# filter out weak predictions by ensuring the detected\n\t\t\t# probability is greater than the minimum probability\n\t\t\tif confidence > args[\"confidence\"]:\n\t\t\t\t# scale the bounding box coordinates back relative to\n\t\t\t\t# the size of the image, keeping in mind that YOLO\n\t\t\t\t# actually returns the center (x, y)-coordinates of\n\t\t\t\t# the bounding box followed by the boxes' width and\n\t\t\t\t# height\n\t\t\t\tbox = detection[0:4] * np.array([W, H, W, H])\n\t\t\t\t(centerX, centerY, width, height) = box.astype(\"int\")\n\n\t\t\t\t# use the center (x, y)-coordinates to derive the top\n\t\t\t\t# and and left corner of the bounding box\n\t\t\t\tx = int(centerX - (width / 2))\n\t\t\t\ty = int(centerY - (height / 2))\n\n\t\t\t\t# update our list of bounding box coordinates,\n\t\t\t\t# confidences, and class IDs\n\t\t\t\tboxes.append([x, y, int(width), int(height)])\n\t\t\t\tconfidences.append(float(confidence))\n\t\t\t\tclassIDs.append(classID)\nIn this code block, we:\nLoop over output layers and detections (\nLines 94-96\n).\nExtract the\nclassID\nand filter out weak predictions (\nLines 99-105\n).\nCompute bounding box coordinates (\nLines 111-117\n).\nUpdate our respective lists (\nLines 121-123\n).\nNext, we’ll apply non-maxima suppression and begin to proceed to annotate the frame:\n# apply non-maxima suppression to suppress weak, overlapping\n\t# bounding boxes\n\tidxs = cv2.dnn.NMSBoxes(boxes, confidences, args[\"confidence\"],\n\t\targs[\"threshold\"])\n\n\t# ensure at least one detection exists\n\tif len(idxs) > 0:\n\t\t# loop over the indexes we are keeping\n\t\tfor i in idxs.flatten():\n\t\t\t# extract the bounding box coordinates\n\t\t\t(x, y) = (boxes[i][0], boxes[i][1])\n\t\t\t(w, h) = (boxes[i][2], boxes[i][3])\n\n\t\t\t# draw a bounding box rectangle and label on the frame\n\t\t\tcolor = [int(c) for c in COLORS[classIDs[i]]]\n\t\t\tcv2.rectangle(frame, (x, y), (x + w, y + h), color, 2)\n\t\t\ttext = \"{}: {:.4f}\".format(LABELS[classIDs[i]],\n\t\t\t\tconfidences[i])\n\t\t\tcv2.putText(frame, text, (x, y - 5),\n\t\t\t\tcv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 2)\nYou should recognize these lines as well. Here we:\nApply NMS using the\ncv2.dnn.NMSBoxes\nfunction (\nLines 127 and 128\n) to suppress weak, overlapping bounding boxes. You can read more about\nnon-maxima suppression here\n.\nLoop over the\nidxs\ncalculated by NMS and draw the corresponding bounding boxes + labels (\nLines 131-144\n).\nLet’s finish out the script:\n# check if the video writer is None\n\tif writer is None:\n\t\t# initialize our video writer\n\t\tfourcc = cv2.VideoWriter_fourcc(*\"MJPG\")\n\t\twriter = cv2.VideoWriter(args[\"output\"], fourcc, 30,\n\t\t\t(frame.shape[1], frame.shape[0]), True)\n\n\t\t# some information on processing single frame\n\t\tif total > 0:\n\t\t\telap = (end - start)\n\t\t\tprint(\"[INFO] single frame took {:.4f} seconds\".format(elap))\n\t\t\tprint(\"[INFO] estimated total time to finish: {:.4f}\".format(\n\t\t\t\telap * total))\n\n\t# write the output frame to disk\n\twriter.write(frame)\n\n# release the file pointers\nprint(\"[INFO] cleaning up...\")\nwriter.release()\nvs.release()\nTo wrap up, we simply:\nInitialize our video\nwriter\nif necessary (\nLines 147-151\n). The\nwriter\nwill be initialized on the first iteration of the loop.\nPrint out our estimates of how long it will take to process the video (\nLines 154-158\n).\nWrite the\nframe\nto the output video file (\nLine 161\n).\nCleanup and release pointers (\nLines 165 and 166\n).\nTo apply YOLO object detection to video streams, make sure you use the\n“Downloads”\nsection of this blog post to download the source, YOLO object detector, and example videos.\nFrom there, open up a terminal and execute the following command:\n$ python yolo_video.py --input videos/car_chase_01.mp4 \\\n\t--output output/car_chase_01.avi --yolo yolo-coco\n[INFO] loading YOLO from disk...\n[INFO] 583 total frames in video\n[INFO] single frame took 0.3500 seconds\n[INFO] estimated total time to finish: 204.0238\n[INFO] cleaning up...\nWhen you execute the commands above you will see a GIF excerpt from\na car chase video I found on YouTube\n.  Why not share it with me on twitter @pyimagesearch?\nIn the video/GIF, you can see not only the vehicles being detected, but people, as well as the traffic lights, are detected too!\nThe YOLO object detector is performing quite well here. Let’s try a different video clip from the same car chase video:\n$ python yolo_video.py --input videos/car_chase_02.mp4 \\\n\t--output output/car_chase_02.avi --yolo yolo-coco\n[INFO] loading YOLO from disk...\n[INFO] 3132 total frames in video\n[INFO] single frame took 0.3455 seconds\n[INFO] estimated total time to finish: 1082.0806\n[INFO] cleaning up...\nWhen you run the commands above you will see a suspect on the run, we have used OpenCV and YOLO object detection to find the person!  Share your output with me again on Twitter @pyimagesearch.\nYOLO is once again able to detect people.\nAt one point the suspect is actually able to make it back to their car and continue the chase — let’s see how YOLO performs there as well:\n$ python yolo_video.py --input videos/car_chase_03.mp4 \\\n\t--output output/car_chase_03.avi --yolo yolo-coco\n[INFO] loading YOLO from disk...\n[INFO] 749 total frames in video\n[INFO] single frame took 0.3442 seconds\n[INFO] estimated total time to finish: 257.8418\n[INFO] cleaning up...\nAs a final example, run the code above and you’ll see you can use YOLO as a starting point to building a traffic counter. Can you think of a great application that uses traffic counting?\nI can\n—\nhow about peak traffic detectors to notify people when to start a commute using traffic counting. Another option is to use traffic counting in order to measure the number of inbound customers to a brick and mortar business.\nBingo! There’s a business waiting to be launched right there. Be sure to run the script below and see the output.\n$ python yolo_video.py --input videos/overpass.mp4 \\\n\t--output output/overpass.avi --yolo yolo-coco\n[INFO] loading YOLO from disk...\n[INFO] 812 total frames in video\n[INFO] single frame took 0.3534 seconds\n[INFO] estimated total time to finish: 286.9583\n[INFO] cleaning up...\nI’ve put together a full video of YOLO object detection examples below:\nCredits for video and audio:\nCar chase video posted on\nYouTube by Quaker Oats\n.\nOverpass video on\nYouTube by Vlad Kiraly\n.\n“White Crow” on the\nFreeMusicArchive by XTaKeRuX\n.\nLimitations and drawbacks of the YOLO object detector\nArguably the largest limitation and drawback of the YOLO object detector is that:\nIt does not always handle small objects well\nIt\nespecially\ndoes not handle objects grouped close together\nThe reason for this limitation is due to the YOLO algorithm itself:\nThe YOLO object detector divides an input image into an\nSxS\ngrid where each cell in the grid predicts only a single object.\nIf there exist multiple, small objects in a single cell then YOLO will be unable to detect them, ultimately leading to missed object detections.\nTherefore, if you know your dataset consists of many small objects grouped close together then you should not use the YOLO object detector.\nIn terms of small objects, Faster R-CNN tends to work the best; however, it’s also the slowest.\nSSDs can also be used here; however, SSDs can also struggle with smaller objects (but not as much as YOLO).\nSSDs often give a nice tradeoff in terms of speed and accuracy as well.\nIt’s also worth noting that YOLO ran slower than SSDs in this tutorial.\nIn my previous tutorial on\nOpenCV object detection\n, we utilized an SSD — a single forward pass of the SSD took ~0.03 seconds.\nHowever, from this tutorial, we know that a forward pass of the YOLO object detector took ≈0.3 seconds,\napproximately, an order of magnitude slower!\nIf you’re using the pre-trained deep learning object detectors OpenCV supplies you may want to consider using SSDs over YOLO.\nFrom my personal experience, I’ve rarely encountered situations where I needed to use YOLO over SSDs:\nI have found SSDs much easier to train and their performance in terms of accuracy almost always outperforms YOLO (at least for the datasets I’ve worked with).\nYOLO may have excellent results on the COCO dataset; however, I have not found that same level of accuracy for my own tasks.\nI, therefore, tend to use the following guidelines when picking an object detector for a given problem:\nIf I know I need to detect small objects and speed is not a concern, I tend to use Faster R-CNN.\nIf speed is absolutely paramount, I use YOLO.\nIf I need a middle ground, I tend to go with SSDs.\nIn most of my situations I end up using SSDs or RetinaNet — both are a great balance between the YOLO/Faster R-CNN.\nAlternative YOLO object detection models\nWe utilized YOLO v3 inside this tutorial to perform YOLO object detection with OpenCV.\nJoseph Redmon, the creator of the YOLO object detector,\nhas ceased working on YOLO due to privacy concerns and misuse in military applications\n; however, other researchers in the computer vision and deep learning community have continued his work.\nWhile these are not “official” YOLO models (in the sense that Joseph Redmon did not create them nor does he endorse them), you will find publications and references to both YOLO v4 and YOLO v5 online:\nYOLO v4: Optimal Speed and Accuracy of Object Detection\nYOLO v5: PyTorch compatible\nIf you use the PyTorch deep learning library, then definitely check out YOLO v5 — the library makes it super easy to train custom YOLO models; however, the output YOLO v5 models are\nnot\ndirectly compatible with OpenCV (i.e., you’ll need to write additional code to make predictions on images/frames if you’re using OpenCV and YOLO v5 together).\nYOLO v4, on the other hand,\nis\ncompatible with OpenCV using the same code provided in this tutorial. All you need to do is provide the YOLO v4 weights and configuration files.\nThis tutorial\nwill help you get started using YOLO v4 with OpenCV.\nWhat's next? We recommend\nPyImageSearch University\n.\nCourse information:\n120+ total classes • 115+ hours of on-demand code walkthrough videos • Last updated: October 2026\n★★★★★\n4.84 (128 Ratings) • 16,000+ Students Enrolled\nI strongly believe that if you had the right teacher you could\nmaster\ncomputer vision and deep learning.\nDo you think learning computer vision and deep learning has to be time-consuming, overwhelming, and complicated? Or has to involve complex mathematics and equations? Or requires a degree in computer science?\nThat’s\nnot\nthe case.\nAll you need to master computer vision and deep learning is for someone to explain things to you in\nsimple, intuitive\nterms.\nAnd that’s exactly what I do\n. My mission is to change education and how complex Artificial Intelligence topics are taught.\nIf you're serious about learning computer vision, your next stop should be PyImageSearch University, the most comprehensive computer vision, deep learning, and OpenCV course online today. Here you’ll learn how to\nsuccessfully\nand\nconfidently\napply computer vision to your work, research, and projects. Join me in computer vision mastery.\nInside PyImageSearch University you'll find:\n✓\n120+ courses\non essential computer vision, deep learning, and OpenCV topics\n✓\n94+ Certificates\nof Completion\n✓\n115+ hours\nof on-demand video\n✓\nBrand new courses released\nregularly\n, ensuring you can keep up with state-of-the-art techniques\n✓\nPre-configured Jupyter Notebooks in Google Colab\n✓ Run all code examples in your web browser — works on Windows, macOS, and Linux (no dev environment configuration required!)\n✓ Access to\ncentralized code repos for\nall\n540+ tutorials\non PyImageSearch\n✓\nEasy one-click downloads\nfor code, datasets, pre-trained models, etc.\n✓\nAccess\non mobile, laptop, desktop, etc.\nClick here to join PyImageSearch University\nSummary\nIn this tutorial we learned how to perform YOLO object detection using Deep Learning, OpenCV, and Python.\nWe then briefly discussed the YOLO architecture followed by implementing Python code to:\nApply YOLO object detection to single images\nApply the YOLO object detector to video streams\nOn my machine with a 3GHz Intel Xeon W processor, a single forward pass of YOLO took ≈0.3 seconds; however,\nusing a Single Shot Detector (SSD) from a previous tutorial\n, resulted in only 0.03 second detection,\nan order of magnitude faster!\nFor real-time deep learning-based object detection on your CPU with OpenCV and Python, you may want to consider using the SSD.\nIf you are interested in training your own deep learning object detectors on your own custom datasets, be sure to refer to my book,\nDeep Learning for Computer Vision with Python\n, where I provide detailed guides on how to successfully train your own detectors.\nI hope you enjoyed today’s YOLO object detection tutorial!\nTo download the source code to today’s post, and be notified when future PyImageSearch blog posts are published,\njust enter your email address in the form below\n.\nDownload the Source Code and FREE 17-page Resource Guide\nEnter your email address below to get a .zip of the code and a\nFREE 17-page Resource Guide on Computer Vision, OpenCV, and Deep Learning.\nInside you'll find my hand-picked tutorials, books, courses, and libraries to help you master CV and DL!\nDownload the code!\nWebsite",
  "metadata": {
    "title": "YOLO object detection with OpenCV - PyImageSearch",
    "description": "In this guide you will learn how to use the YOLO object detector to detect objects in images and video using OpenCV, Python, and Deep Learning.",
    "keywords": null,
    "author": "Adrian Rosebrock",
    "og:locale": "en_US",
    "og:type": "article",
    "og:title": "YOLO object detection with OpenCV - PyImageSearch",
    "og:description": "In this guide you will learn how to use the YOLO object detector to detect objects in images and video using OpenCV, Python, and Deep Learning.",
    "og:url": "https://pyimagesearch.com/2018/11/12/yolo-object-detection-with-opencv/",
    "og:site_name": "PyImageSearch",
    "og:image": "https://pyimagesearch.com/wp-content/uploads/2018/11/yolo_living_room_output.jpg",
    "og:image:width": "600",
    "og:image:height": "600",
    "og:image:type": "image/jpeg",
    "twitter:label1": "Written by",
    "twitter:data1": "Adrian Rosebrock",
    "twitter:label2": "Est. reading time",
    "twitter:data2": "28 minutes",
    "article:published_time": "2018-11-12T15:00:55+00:00",
    "article:modified_time": "2024-12-23T08:42:16+00:00"
  },
  "paywall": {
    "listed_paid": false,
    "detected": false,
    "marker": "",
    "public_only": false,
    "policy": "付费/会员内容只保留页面公开可见部分，不绕过付费墙"
  },
  "crawl": {
    "success": true,
    "status_code": 200,
    "error": ""
  },
  "code_blocks": [
    {
      "file": "attachments/38db5bb25336/code/body-000.txt",
      "chars": 476,
      "language": "text"
    },
    {
      "file": "attachments/38db5bb25336/code/body-001.txt",
      "chars": 613,
      "language": "text"
    },
    {
      "file": "attachments/38db5bb25336/code/body-002.txt",
      "chars": 335,
      "language": "text"
    },
    {
      "file": "attachments/38db5bb25336/code/body-003.txt",
      "chars": 358,
      "language": "text"
    },
    {
      "file": "attachments/38db5bb25336/code/body-004.txt",
      "chars": 697,
      "language": "text"
    },
    {
      "file": "attachments/38db5bb25336/code/body-005.txt",
      "chars": 136,
      "language": "text"
    },
    {
      "file": "attachments/38db5bb25336/code/body-006.txt",
      "chars": 1169,
      "language": "text"
    },
    {
      "file": "attachments/38db5bb25336/code/body-007.txt",
      "chars": 162,
      "language": "text"
    },
    {
      "file": "attachments/38db5bb25336/code/body-008.txt",
      "chars": 619,
      "language": "text"
    },
    {
      "file": "attachments/38db5bb25336/code/body-009.txt",
      "chars": 134,
      "language": "text"
    },
    {
      "file": "attachments/38db5bb25336/code/body-010.txt",
      "chars": 132,
      "language": "text"
    },
    {
      "file": "attachments/38db5bb25336/code/body-011.txt",
      "chars": 133,
      "language": "text"
    },
    {
      "file": "attachments/38db5bb25336/code/body-012.txt",
      "chars": 127,
      "language": "text"
    },
    {
      "file": "attachments/38db5bb25336/code/body-013.txt",
      "chars": 707,
      "language": "text"
    },
    {
      "file": "attachments/38db5bb25336/code/body-014.txt",
      "chars": 847,
      "language": "text"
    },
    {
      "file": "attachments/38db5bb25336/code/body-015.txt",
      "chars": 635,
      "language": "text"
    },
    {
      "file": "attachments/38db5bb25336/code/body-016.txt",
      "chars": 334,
      "language": "text"
    },
    {
      "file": "attachments/38db5bb25336/code/body-017.txt",
      "chars": 487,
      "language": "text"
    },
    {
      "file": "attachments/38db5bb25336/code/body-018.txt",
      "chars": 1202,
      "language": "text"
    },
    {
      "file": "attachments/38db5bb25336/code/body-019.txt",
      "chars": 736,
      "language": "text"
    },
    {
      "file": "attachments/38db5bb25336/code/body-020.txt",
      "chars": 614,
      "language": "text"
    },
    {
      "file": "attachments/38db5bb25336/code/body-021.txt",
      "chars": 284,
      "language": "text"
    },
    {
      "file": "attachments/38db5bb25336/code/body-022.txt",
      "chars": 286,
      "language": "text"
    },
    {
      "file": "attachments/38db5bb25336/code/body-023.txt",
      "chars": 284,
      "language": "text"
    },
    {
      "file": "attachments/38db5bb25336/code/body-024.txt",
      "chars": 276,
      "language": "text"
    }
  ],
  "images": [
    {
      "status": "ok",
      "url": "https://b2633864.assetcdn.net/2633864/wp-content/uploads/2018/11/yolo_living_room_output.jpg?lossy=2&strip=1&webp=1",
      "bytes": 48432,
      "reused": true,
      "local_path": "attachments/38db5bb25336/images/005.jpg",
      "src": "https://b2633864.assetcdn.net/2633864/wp-content/uploads/2018/11/yolo_living_room_output.jpg?lossy=2&strip=1&webp=1",
      "alt": "",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://b2633864.assetcdn.net/2633864/wp-content/uploads/2020/01/source-code-icon.png?lossy=2&strip=1&webp=1",
      "bytes": 884,
      "reused": false,
      "local_path": "attachments/38db5bb25336/images/body-0f8ec41d2103feb4399d.png",
      "src": "https://b2633864.assetcdn.net/2633864/wp-content/uploads/2020/01/source-code-icon.png?lossy=2&strip=1&webp=1",
      "alt": "",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://b2633864.assetcdn.net/2633864/wp-content/uploads/2018/11/yolo_design.jpg?lossy=2&strip=1&webp=1",
      "bytes": 34235,
      "reused": false,
      "local_path": "attachments/38db5bb25336/images/body-7ec532cc8e78ecd3d77f.jpg",
      "src": "https://b2633864.assetcdn.net/2633864/wp-content/uploads/2018/11/yolo_design.jpg?lossy=2&strip=1&webp=1",
      "alt": "",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://b2633864.assetcdn.net/2633864/wp-content/uploads/2018/11/yolo_baggage_claim_output.jpg?lossy=2&strip=1&webp=1",
      "bytes": 46216,
      "reused": false,
      "local_path": "attachments/38db5bb25336/images/body-610f270e8f6412845540.jpg",
      "src": "https://b2633864.assetcdn.net/2633864/wp-content/uploads/2018/11/yolo_baggage_claim_output.jpg?lossy=2&strip=1&webp=1",
      "alt": "",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://b2633864.assetcdn.net/2633864/wp-content/uploads/2018/11/yolo_dining_table_output.jpg?lossy=2&strip=1&webp=1",
      "bytes": 53646,
      "reused": false,
      "local_path": "attachments/38db5bb25336/images/body-61acd4b957cbbfc66de6.jpg",
      "src": "https://b2633864.assetcdn.net/2633864/wp-content/uploads/2018/11/yolo_dining_table_output.jpg?lossy=2&strip=1&webp=1",
      "alt": "",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://b2633864.assetcdn.net/2633864/wp-content/uploads/2018/11/yolo_soccer_output.jpg?lossy=2&strip=1&webp=1",
      "bytes": 47698,
      "reused": false,
      "local_path": "attachments/38db5bb25336/images/body-c0b113e546e2e0451ad1.jpg",
      "src": "https://b2633864.assetcdn.net/2633864/wp-content/uploads/2018/11/yolo_soccer_output.jpg?lossy=2&strip=1&webp=1",
      "alt": "",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://fast.wistia.com/embed/medias/kno0cmko2z/swatch",
      "bytes": 3143,
      "reused": false,
      "local_path": "attachments/38db5bb25336/images/body-8ec9834d54100244f57f.img",
      "src": "https://fast.wistia.com/embed/medias/kno0cmko2z/swatch",
      "alt": "",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://b2633864.assetcdn.net/2633864/wp-content/uploads/2020/01/cta-source-guide-1.png?lossy=2&strip=1&webp=1",
      "bytes": 28126,
      "reused": false,
      "local_path": "attachments/38db5bb25336/images/body-8cd5816cf73385d96fcd.png",
      "src": "https://b2633864.assetcdn.net/2633864/wp-content/uploads/2020/01/cta-source-guide-1.png?lossy=2&strip=1&webp=1",
      "alt": "",
      "downloaded": true
    }
  ],
  "audio": [],
  "videos": [
    {
      "url": "https://www.youtube.com/watch?v=eeIEH2wjvhg",
      "src": "https://www.youtube.com/embed/eeIEH2wjvhg",
      "status": "ok",
      "kind": "single_video",
      "local_path": "attachments/38db5bb25336/videos/repair-eeIEH2wjvhg.mp4",
      "bytes": 38688263,
      "valid": true,
      "height": 720,
      "width": 1280,
      "duration": "160.781000",
      "reused": false
    },
    {
      "url": "https://www.youtube.com/watch?v=7K3dZmrcriU",
      "src": "https://www.youtube.com/watch?v=7K3dZmrcriU",
      "status": "ok",
      "kind": "single_video",
      "local_path": "attachments/38db5bb25336/videos/repair-7K3dZmrcriU.mp4",
      "bytes": 148712788,
      "valid": true,
      "height": 720,
      "width": 1280,
      "duration": "791.561000",
      "reused": false
    },
    {
      "url": "https://www.youtube.com/watch?v=nt3D26lrkho",
      "src": "https://www.youtube.com/watch?v=nt3D26lrkho",
      "status": "ok",
      "kind": "single_video",
      "local_path": "attachments/38db5bb25336/videos/repair-nt3D26lrkho.mp4",
      "bytes": 231737198,
      "valid": true,
      "height": 720,
      "width": 1280,
      "duration": "840.561000",
      "reused": false
    }
  ],
  "links": [
    {
      "href": "https://pyimagesearch.com/wp-content/uploads/2018/11/yolo_living_room_output.jpg",
      "label": "",
      "type": "a"
    },
    {
      "href": "https://roboflow.com/?ref=pyimagesearch",
      "label": "Roboflow",
      "type": "a"
    },
    {
      "href": "https://universe.roboflow.com/pyimagesearch?ref=pyimagesearch",
      "label": "PyimageSearch’s assorted library of useful datasets",
      "type": "a"
    },
    {
      "href": "https://www.youtube.com/embed/eeIEH2wjvhg",
      "label": "",
      "type": "iframe"
    },
    {
      "href": "https://pyimagesearch.com/wp-content/uploads/2018/11/yolo_design.jpg",
      "label": "",
      "type": "a"
    },
    {
      "href": "https://arxiv.org/abs/1506.02640",
      "label": "source",
      "type": "a"
    },
    {
      "href": "https://arxiv.org/abs/1311.2524",
      "label": "Rich feature hierarchies for accurate object detection and semantic segmentation",
      "type": "a"
    },
    {
      "href": "http://www.huppelen.nl/publications/selectiveSearchDraft.pdf",
      "label": "Selective Search",
      "type": "a"
    },
    {
      "href": "https://arxiv.org/abs/1504.08083",
      "label": "Fast R- CNN",
      "type": "a"
    },
    {
      "href": "https://arxiv.org/abs/1506.01497",
      "label": "Faster R-CNN: Towards Real-Time Object Detection with Region Proposal Networks",
      "type": "a"
    },
    {
      "href": "https://arxiv.org/abs/1612.08242",
      "label": "YOLO9000: Better, Faster, Stronger",
      "type": "a"
    },
    {
      "href": "https://arxiv.org/abs/1804.02767",
      "label": "YOLOv3: An Incremental Improvement",
      "type": "a"
    },
    {
      "href": "https://github.com/pjreddie/darknet/blob/master/data/coco.names",
      "label": "using this link",
      "type": "a"
    },
    {
      "href": "https://arxiv.org/pdf/1804.02767.pdf",
      "label": "read the YOLOv3 tech report",
      "type": "a"
    },
    {
      "href": "https://pjreddie.com/darknet/yolo/",
      "label": "Darknet team",
      "type": "a"
    },
    {
      "href": "https://pyimagesearch.com/opencv-tutorials-resources-guides/",
      "label": "OpenCV installation tutorials here",
      "type": "a"
    },
    {
      "href": "https://pyimagesearch.com/2018/09/19/pip-install-opencv/",
      "label": "with pip",
      "type": "a"
    },
    {
      "href": "https://pyimagesearch.com/2018/03/12/python-argparse-command-line-arguments/",
      "label": "previous tutorial",
      "type": "a"
    },
    {
      "href": "https://pyimagesearch.com/2014/11/17/non-maximum-suppression-object-detection-python/",
      "label": "non-maxima suppression here",
      "type": "a"
    },
    {
      "href": "https://pyimagesearch.com/2017/11/06/deep-learning-opencvs-blobfromimage-works/",
      "label": "this blog post",
      "type": "a"
    },
    {
      "href": "https://github.com/jrosebr1/imutils/blob/master/imutils/object_detection.py",
      "label": "imutils implementation of NMS",
      "type": "a"
    },
    {
      "href": "https://pyimagesearch.com/wp-content/uploads/2018/11/yolo_baggage_claim_output.jpg",
      "label": "",
      "type": "a"
    },
    {
      "href": "https://pyimagesearch.com/wp-content/uploads/2018/11/yolo_dining_table_output.jpg",
      "label": "",
      "type": "a"
    },
    {
      "href": "https://pyimagesearch.com/wp-content/uploads/2018/11/yolo_soccer_output.jpg",
      "label": "",
      "type": "a"
    },
    {
      "href": "https://www.youtube.com/watch?v=7K3dZmrcriU",
      "label": "a car chase video I found on YouTube",
      "type": "a"
    },
    {
      "href": "https://www.youtube.com/watch?v=nt3D26lrkho",
      "label": "YouTube by Vlad Kiraly",
      "type": "a"
    },
    {
      "href": "https://freemusicarchive.org/music/XTaKeRuX/Empty_Grave/White_Crow",
      "label": "FreeMusicArchive by XTaKeRuX",
      "type": "a"
    },
    {
      "href": "https://pyimagesearch.com/2017/09/11/object-detection-with-deep-learning-and-opencv/",
      "label": "OpenCV object detection",
      "type": "a"
    },
    {
      "href": "https://twitter.com/pjreddie/status/1230524770350817280",
      "label": "has ceased working on YOLO due to privacy concerns and misuse in military applications",
      "type": "a"
    },
    {
      "href": "https://arxiv.org/abs/2004.10934",
      "label": "YOLO v4: Optimal Speed and Accuracy of Object Detection",
      "type": "a"
    },
    {
      "href": "https://github.com/ultralytics/yolov5",
      "label": "YOLO v5: PyTorch compatible",
      "type": "a"
    },
    {
      "href": "https://dsbyprateekg.blogspot.com/2020/08/how-to-use-opencv-python-with-darknets.html",
      "label": "This tutorial",
      "type": "a"
    },
    {
      "href": "https://pyimagesearch.com/pyimagesearch-university/?utm_source=blogPost&utm_medium=bottomBanner&utm_campaign=What%27s%20next%3F%20I%20recommend",
      "label": "PyImageSearch University",
      "type": "a"
    },
    {
      "href": "https://pyimagesearch.com/deep-learning-computer-vision-python-book/",
      "label": "Deep Learning for Computer Vision with Python",
      "type": "a"
    }
  ],
  "repair_version": 2,
  "repaired_at": "2026-10-14T10:54:06Z",
  "source_url": "https://pyimagesearch.com/2018/11/12/yolo-object-detection-with-opencv/",
  "papers": [
    {
      "status": "ok",
      "url": "https://arxiv.org/pdf/1506.02640",
      "bytes": 5296750,
      "reused": true,
      "local_path": "papers/repair/27e378fce20ee7c0b279.pdf"
    },
    {
      "status": "ok",
      "url": "https://arxiv.org/pdf/1311.2524",
      "bytes": 6537772,
      "reused": true,
      "local_path": "papers/repair/5a971c9318fd8ef99b6d.pdf"
    },
    {
      "status": "ok",
      "url": "http://www.huppelen.nl/publications/selectiveSearchDraft.pdf",
      "bytes": 5937890,
      "reused": false,
      "local_path": "papers/repair/8f6fecd93959d250da16.pdf"
    },
    {
      "status": "ok",
      "url": "https://arxiv.org/pdf/1504.08083",
      "bytes": 731121,
      "reused": true,
      "local_path": "papers/repair/6389d2bce9bb81657bc7.pdf"
    },
    {
      "status": "ok",
      "url": "https://arxiv.org/pdf/1506.01497",
      "bytes": 6913803,
      "reused": true,
      "local_path": "papers/repair/713fc776568d336b3d68.pdf"
    },
    {
      "status": "ok",
      "url": "https://arxiv.org/pdf/1612.08242",
      "bytes": 5256083,
      "reused": false,
      "local_path": "papers/repair/1288fc7e9385e0345e39.pdf"
    },
    {
      "status": "ok",
      "url": "https://arxiv.org/pdf/1804.02767",
      "bytes": 2456177,
      "reused": false,
      "local_path": "papers/repair/7105c64d574bae97d89a.pdf"
    },
    {
      "status": "ok",
      "url": "https://arxiv.org/pdf/1804.02767.pdf",
      "bytes": 2456177,
      "reused": false,
      "local_path": "papers/repair/bbeea93939ac39318f94.pdf"
    },
    {
      "status": "ok",
      "url": "https://arxiv.org/pdf/2004.10934",
      "bytes": 3939513,
      "reused": false,
      "local_path": "papers/repair/a97d2df9a64bc0b94fb6.pdf"
    }
  ],
  "actual_video_files": [
    {
      "local_path": "attachments/38db5bb25336/videos/kno0cmko2z.mp4",
      "bytes": 154424456,
      "valid": true,
      "height": 1080,
      "width": 1920,
      "duration": "231.500000",
      "status": "ok"
    }
  ],
  "body_chars": 40105,
  "expected_body_images": 8,
  "discovery_status": "ok",
  "delivery_status": "ok",
  "missing_reason": "",
  "raw_html": "attachments/38db5bb25336/pages/source.html",
  "local_html": "attachments/38db5bb25336/pages/article.html",
  "body_base_path": "attachments/38db5bb25336/pages/",
  "body_markdown_path": "attachments/38db5bb25336/pages/article.md"
}