Title: Histogram of Oriented Gradients and Object Detection - PyImageSearch

URL Source: https://pyimagesearch.com/2014/11/10/histogram-oriented-gradients-object-detection/

Published Time: 2014-11-10T15:00:00+00:00

Markdown Content:
[![Image 1: Detecting beer in images using Histogram of Oriented Gradients](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20600%20450'%3E%3C/svg%3E)](https://pyimagesearch.com/wp-content/uploads/2014/10/hog_object_detection_beer.jpg)

If you’ve been paying attention to my Twitter account lately, you’ve probably noticed [one](https://twitter.com/PyImageSearch/status/523197501181272064) or [two](https://twitter.com/PyImageSearch/status/523516653238484992) teasers of what I’ve been working on — a Python framework/package to rapidly construct object detectors using Histogram of Oriented Gradients and Linear Support Vector Machines.

Honestly, I really can’t stand using the Haar cascade classifiers provided by OpenCV (i.e. the Viola-Jones detectors) — and hence why I’m working on my own suite of classifiers. While cascade methods are extremely fast, they leave much to be desired. If you’ve ever used OpenCV to detect faces you’ll know exactly what I’m talking about.

[![Image 2: Figure 1: Example of falsely detecting a face in an image. This is a common problem when using cv2.detectMultiScale.](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20235%20300'%3E%3C/svg%3E)](https://pyimagesearch.com/wp-content/uploads/2014/10/hog_object_detection_false_positive.jpg)

**Figure 1:** Example of falsely detecting a face in an image. This is a common problem when using cv2.detectMultiScale.

In order to detect faces/humans/objects/whatever in OpenCV (and remove the false positives), you’ll spend a lot of time tuning the `cv2.detectMultiScale`  parameters. And again, there is no guarantee that the exact same parameters will work from image-to-image. This makes batch-processing large datasets for face detection a tedious task since you’ll be very concerned with either (1) falsely detecting faces or (2) missing faces entirely, simply due to poor parameter choices on a per image basis.

There is also the problem that the Viola-Jones detectors **_are nearing 15 years old._** If this detector were a nice bottle of Cabernet Sauvignon I might be pretty stoked right now. But the field has advanced substantially since then_._  Back in 2001 the Viola-Jones detectors were state-of-the-art and they were certainly a huge motivating force behind the incredible new advances we have in object detection today.

Now, the Viola-Jones detector isn’t our only choice for object detection. We have object detection using keypoints, local invariant descriptors, and bag-of-visual-words models. We have Histogram of Oriented Gradients. We have deformable parts models. Exemplar models. And we are now utilizing Deep Learning with pyramids to recognize objects at different scales!

All that said, even though the Histogram of Oriented Gradients descriptor for object recognition is nearly a decade old, it is still heavily used today — and with fantastic results. The Histogram of Oriented Gradients method suggested by Dalal and Triggs in their seminal 2005 paper, [_Histogram of Oriented Gradients for Human Detection_](http://lear.inrialpes.fr/people/triggs/pubs/Dalal-cvpr05.pdf) demonstrated that the Histogram of Oriented Gradients (HOG) image descriptor and a Linear Support Vector Machine (SVM) could be used to train highly accurate object classifiers — or in their particular study, human detectors.

I’m not going to review the entire detailed process of training an object detector using Histogram of Oriented Gradients (yet), simply because each step can be fairly detailed. But I wanted to take a minute and detail the general algorithm for training an object detector using Histogram of Oriented Gradients. It goes a little something like this:

### Step 1:

Sample _P_ positive samples from your training data of the object(s) you want to detect and extract HOG descriptors from these samples.

### Step 2:

Sample _N_ negative samples from a _negative training set_ that **_does not contain_** any of the objects you want to detect and extract HOG descriptors from these samples as well. In practice _N >> P._

### Step 3:

Train a Linear Support Vector Machine on your positive and negative samples.

### Step 4:

[![Image 3: Figure 2: Example of the sliding a window approach, where we slide a window from left-to-right and top-to-bottom.](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20256%20377'%3E%3C/svg%3E)](https://pyimagesearch.com/wp-content/uploads/2014/10/sliding_window_example.gif)

**Figure 2:** Example of the sliding a window approach, where we slide a window from left-to-right and top-to-bottom. _Note: Only a single scale is shown. In practice this window would be applied to multiple scales of the image._

**Apply hard-negative mining.** For each image and each possible scale of each image in your negative training set, apply the sliding window technique and slide your window across the image. At each window compute your HOG descriptors and apply your classifier. If your classifier (incorrectly) classifies a given window as an object (and it will, there will absolutely be false-positives), record the feature vector associated with the false-positive patch along with the probability of the classification. **This approach is called _hard-negative mining._**

### Step 5:

Take the false-positive samples found during the hard-negative mining stage, sort them by their confidence (i.e. probability) and re-train your classifier using these hard-negative samples. _(Note: You can iteratively apply steps 4-5, but in practice one stage of hard-negative mining usually \[not not always\] tends to be enough. The gains in accuracy on subsequent runs of hard-negative mining tend to be minimal.)_

### Step 6:

Your classifier is now trained and can be applied to your test dataset. Again, just like in Step 4, for each image in your test set, and for each scale of the image, apply the sliding window technique. At each window extract HOG descriptors and apply your classifier. If your classifier detects an object with sufficiently large probability, record the bounding box of the window. After you have finished scanning the image, apply non-maximum suppression to remove redundant and overlapping bounding boxes.

These are the bare minimum steps required, but by using this 6-step process you can train and build object detection classifiers of your own! Extensions to this approach include a [deformable parts model](http://cs.brown.edu/~pff/papers/lsvm-pami.pdf) and [Exemplar SVMs](http://www.cs.cmu.edu/~efros/exemplarsvm-iccv11.pdf), where you train a classifier for _each_ _positive instance_ rather than a _collection of them._

However, if you’ve ever worked with object detection in images you’ve likely ran into the problem of _detecting multiple_ _bounding boxes around the object you want to detect in the image._

Here’s an example of this overlapping bounding box problem:

[![Image 4: Figure 3: (Left) Detecting multiple overlapping bounding boxes around the face we want to detect. (Right) Applying non-maximum suppression to remove the redundant bounding boxes.](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20600%20425'%3E%3C/svg%3E)](https://pyimagesearch.com/wp-content/uploads/2014/10/hog_object_detection_nms.jpg)

**Figure 3:** _(Left)_ Detecting multiple overlapping bounding boxes around the face we want to detect. _(Right)_ Applying non-maximum suppression to remove the redundant bounding boxes.

Notice on the _left_ we have 6 overlapping bounding boxes that have correctly detected Audrey Hepburn’s face. However, these 6 bounding boxes all refer to the same face — we need a method to suppress the 5 smallest bounding boxes in the region, keeping only the largest one, as seen on the _right_.

This is a common problem, no matter if you are using the Viola-Jones based method or following the Dalal-Triggs paper.

There are multiple ways to remedy this problem. Triggs et al. suggests to use the [Mean-Shift algorithm](http://en.wikipedia.org/wiki/Mean-shift) to detect multiple modes in the bounding box space by utilizing the _(x, y)_ coordinates of the bounding box as well as the logarithm of the current scale of the image.

I’ve personally tried this method and wasn’t satisfied with the results. Instead, you’re much better off relying on a _strong classifier_ with _higher accuracy_ (meaning there are very few false positives) and then applying non-maximum suppression to the bounding boxes.

I spent some time looking for a good non-maximum suppression (sometimes called non-maxima suppression) implementation in Python. When I couldn’t find one, I chatted with my friend [Dr. Tomasz Malisiewicz](http://people.csail.mit.edu/tomasz/), who has spent his entire career working with object detector algorithms and the HOG descriptor. There is literally _no one_ that I know who has more experience in this area than Tomasz. And if you’ve ever read any of his papers, you’ll know why. His work is fantastic.

Anyway, after chatting with him, he pointed me to two MATLAB implementations. [The first](https://github.com/rbgirshick/voc-dpm/blob/master/test/nms.m) is based on the work by [Felzenszwalb et al](http://cs.brown.edu/~pff/). and their deformable parts model.

The [second method](http://quantombone.blogspot.com/2011/08/blazing-fast-nmsm-from-exemplar-svm.html) is implemented by Tomasz himself for his [Exemplar SVM](https://github.com/quantombone/exemplarsvm) project which he used for his dissertation and his ICCV 2011 paper, [_Ensemble of Exemplar-SVMs for Object Detection and Beyond_](http://www.cs.cmu.edu/~tmalisie/projects/iccv11/index.html). It’s important to note that Tomasz’s method _is over 100x faster_ than the Felzenszwalb et al. method. And when you’re executing your non-maximum suppression function millions of times, that 100x speedup really matters.

I’ve implemented both the Felzenszwalb et al. and Tomasz et al. methods, porting them from MATLAB to Python. Next week we’ll start with the Felzenszwalb method, then the following week I’ll cover Tomasz’s method. While Tomasz’s method is substantially faster, I think it’s important to see both implementations so we can understand exactly _why_ his method obtains such drastic speedups.

Be sure to stick around and check out these posts! These are absolutely critical steps to building object detectors of your own!

### What's next? We recommend [PyImageSearch University](https://pyimagesearch.com/pyimagesearch-university/?utm_source=blogPost&utm_medium=bottomBanner&utm_campaign=What%27s%20next%3F%20I%20recommend).

**Course information:**  
84 total classes • 114+ hours of on-demand code walkthrough videos • Last updated: February 2024  
★★★★★ 4.84 (128 Ratings) • 16,000+ Students Enrolled

**I strongly believe that if you had the right teacher you could _master_ computer vision and deep learning.**

Do 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?

That’s _not_ the case.

All you need to master computer vision and deep learning is for someone to explain things to you in _simple, intuitive_ terms. _And that’s exactly what I do_. My mission is to change education and how complex Artificial Intelligence topics are taught.

If 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 _successfully_ and _confidently_ apply computer vision to your work, research, and projects. Join me in computer vision mastery.

**Inside PyImageSearch University you'll find:**

*   ✓ **84 courses** on essential computer vision, deep learning, and OpenCV topics
*   ✓ **84 Certificates** of Completion
*   ✓ **114+ hours** of on-demand video
*   ✓ **Brand new courses released _regularly_**, ensuring you can keep up with state-of-the-art techniques
*   ✓ **Pre-configured Jupyter Notebooks in Google Colab**
*   ✓ Run all code examples in your web browser — works on Windows, macOS, and Linux (no dev environment configuration required!)
*   ✓ Access to **centralized code repos for _all_ 536+ tutorials** on PyImageSearch
*   ✓ **Easy one-click downloads** for code, datasets, pre-trained models, etc.
*   ✓ **Access** on mobile, laptop, desktop, etc.

[Click here to join PyImageSearch University](https://pyimagesearch.com/pyimagesearch-university/?utm_source=blogPost&utm_medium=bottomBanner&utm_campaign=What%27s%20next%3F%20I%20recommend)

Summary
-------

In this blog post we had a little bit of a history lesson regarding object detectors. We also had a sneak peek into a Python framework that I am working on for object detection in images.

From there we had a quick review of how the Histogram of Oriented Gradients method is used in conjunction with a Linear SVM to train a robust object detector.

However, no matter what method of object detection you use, you will likely end up with multiple bounding boxes surrounding the object you want to detect. In order to remove these redundant boxes you’ll need to apply Non-Maximum Suppression.

Over the next two weeks I’ll show you two implementations of Non-Maximum Suppression that you can use in your own object detection projects.

Be sure to enter your email address in the form below to receive an announcement when these posts go live! Non-Maximum Suppression is absolutely _critical_ to obtaining an accurate and robust object detection system using HOG, so you definitely don’t want to miss these posts!

![Image 5](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20410%20567'%3E%3C/svg%3E)

#### Join the PyImageSearch Newsletter and Grab My FREE 17-page Resource Guide PDF

Enter your email address below to **join the PyImageSearch Newsletter** and **download my FREE 17-page Resource Guide PDF** on Computer Vision, OpenCV, and Deep Learning.