Introduction
In this tutorial we will continue with the contour topics. Previously we saw how to draw bounding boxes around the objects using their contours. Now we will see how to draw convex hull around the contours.
The convex hull is quit a useful feature when used for object detection and manipulation. We will see some ready OpenCV function which will help us generate and draw the convex hulls objects.
Convex hull basics
The convex hull is the minimum closed set of points, which encloses all points of a given object. It has random shape, depending on the object shape. Usually the convex hull connects the most outer points of the object. It is wide used in the mathematics, statistics, economics, geometric modeling as well as in the image processing. More information about it you can find here.
Convex hull implementation
We will now see one example on how to generate and draw convex hulls around random objects. The code below shows how to do it.
// Add convex hull around the contours in an image void addConvexHull() { // Path to the input image std::string l_pathToInputImage{ "../Resources/shapes.jpg" }; // Create an object to hold the image data of the first image Mat l_image; // Read the image date from a file with no change to color scheme l_image = imread(l_pathToInputImage, IMREAD_UNCHANGED); // Check if we have read the first image data correctly if (!l_image.data) { std::cout << "No image data \n"; return; } // Convert the image to grayscale Mat l_imageGrayscale{}; cvtColor(l_image, l_imageGrayscale, COLOR_BGR2GRAY); blur(l_imageGrayscale, l_imageGrayscale, Size{ 3,3 }); // Apply the canny edge detection constexpr int c_kernelSize = 3; constexpr double c_lowerThreshold = 30.0; constexpr double c_upperThreshold = c_lowerThreshold * 3.0; Mat l_cannyImage{}; Canny(l_imageGrayscale, l_cannyImage, c_lowerThreshold, c_lowerThreshold, c_kernelSize); // Find the contours std::vector<std::vector<Point> > l_contours; std::vector<Vec4i> l_hierarchy; findContours(l_cannyImage, l_contours, l_hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE); // Get the convex hulls std::vector<std::vector<Point> > l_convexHull(l_contours.size()); for (size_t i = 0; i < l_contours.size(); i++) { convexHull(l_contours[i], l_convexHull[i]); } // Draw the contours and the convex hulls Mat l_result = Mat::zeros(l_cannyImage.size(), CV_8UC3); for (int i = 0; i < l_contours.size(); i++) { const Scalar c_lineColor{ 0, 255, 0 }; const Scalar c_convexHullLineColor{ 0, 0, 255 }; constexpr int c_lineThickness = 1; drawContours(l_result, l_contours, i, c_lineColor, c_lineThickness, LINE_8, l_hierarchy); drawContours(l_result, l_convexHull, i, c_convexHullLineColor, c_lineThickness, LINE_8, l_hierarchy); } // Display the input image namedWindow("Input", WINDOW_NORMAL); cv::imshow("Input", l_image); // Display the result image namedWindow("Result", WINDOW_NORMAL); cv::imshow("Result", l_result); }
We have the standard loading of an image, which we will process further. Then we find the contours in that image. We already saw how to do this in a previous tutorial.
On line #38 we start getting the convex hulls for each contour. For this purpose, we use the function convexHull(). It takes the contour points as a first argument. As a second argument we need to provide one vector, where OpenCV will store the convex hull’s points. The third and the fourth arguments are optional. The third one is a flag, stating whether the orientation of the convex hull will be clockwise or not. We leave these two arguments with their default values.
We are ready generating the convex hulls. The next step is to draw the results. We use the drawContours function to draw both the contours and the convex hulls for each object. You can see the results on my side:

Conclusion
In this tutorial we saw how to detect and draw convex hull around a given object by using its contour. It was a short tutorial but an important one. We will meet the convex hulls further down the road.
As usual the code example is available below as an archive and in GitHub.
Next, we will see yet another algorithm to detect features.

Passionate developer, loving husband and caring father. As an introvert programming is my life. I work as a senior software engineer in a big international company. My hobbies include playing computer games (mostly World of Warcraft), watching TV series and hiking.