Skip to main content

6-4 Circle and Face Detection Using OpenCV

This tutorial provides an overview and practical examples for implementing circle and face detection using OpenCV in both C++ and Python.


Circle Detection with HoughCircles

To detect circles in images, OpenCV offers the HoughCircles function. This method works by converting the image into a parameter space where circles are identified based on their center coordinates and radius.

cv::HoughCircles Syntax:

void cv::HoughCircles(
InputArray image,
OutputArray circles,
int method,
double dp, // Inverse ratio of accumulator resolution to image resolution
double minDist, // Minimum distance between circle centers
double param1 = 100, // Canny high threshold
double param2 = 100, // Accumulator threshold
int minRadius = 0,
int maxRadius = 0
);
tip

Tune minDist, param1, and param2 to improve detection accuracy. Use minRadius and maxRadius to filter specific circle sizes.

Example C++ Code: Detecting Circles from Camera

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main() {
VideoCapture cap(0);
if (!cap.isOpened()) {
cerr << "Error: Could not open camera." << endl;
return -1;
}

Mat frame, gray;
while (true) {
cap >> frame;
if (frame.empty()) break;

cvtColor(frame, gray, COLOR_BGR2GRAY);
GaussianBlur(gray, gray, Size(9, 9), 2, 2);

vector<Vec3f> circles;
HoughCircles(gray, circles, HOUGH_GRADIENT, 1, gray.rows / 16, 100, 30, 10, 100);

for (size_t i = 0; i < circles.size(); i++) {
Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
int radius = cvRound(circles[i][2]);
circle(frame, center, radius, Scalar(0, 255, 0), 2);
circle(frame, center, 2, Scalar(0, 0, 255), 3);
}

imshow("Circle Detection", frame);
if (waitKey(30) == 27) break;
}

cap.release();
return 0;
}

Build Instructions:

mkdir build
cd build
cmake ..
make

Suggested Development Flow

Due to the variability of camera input, start development using still images, then videos, and finally move to live camera feeds.

Stage 1: Image Input

Mat image = imread("image.jpg");
if (!image.data) {
cerr << "No image data\n";
return -1;
}
imshow("Display Image", image);
waitKey(0);

Stage 2: Video Input

VideoCapture cap("video.mp4");
if (!cap.isOpened()) {
cerr << "Error: Could not open video." << endl;
return -1;
}

Mat frame;
while (true) {
cap >> frame;
if (frame.empty()) break;
// Process frame...
if (waitKey(30) == 27) break;
}

Stage 3: Live Camera

VideoCapture cap(0);
if (!cap.isOpened()) {
cerr << "Error: Could not open camera." << endl;
return -1;
}

Mat frame;
while (true) {
cap >> frame;
if (frame.empty()) break;
// Process frame...
if (waitKey(30) == 27) break;
}

Face Detection with Haar Cascades

Face detection is implemented using Haar feature-based cascade classifiers trained with positive and negative images.

Python Example: Face Detection

import cv2

def detectFace(img):
filename = img.split(".")[0]
img = cv2.imread(img)
grayImg = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
color = (0, 255, 0)

face_classifier = cv2.CascadeClassifier(cv2.data.haarcascades + "haarcascade_frontalface_default.xml")
faces = face_classifier.detectMultiScale(grayImg, scaleFactor=1.2, minNeighbors=3, minSize=(32, 32))

for (x, y, w, h) in faces:
cv2.rectangle(img, (x, y), (x + w, y + h), color, 2)

cv2.imwrite(filename + "_face.jpg", img)

detectFace('human.jpg')

C++ Example: Face and Eye Detection

#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;

CascadeClassifier face_cascade, eyes_cascade;

void detectAndDisplay(Mat frame) {
Mat gray;
cvtColor(frame, gray, COLOR_BGR2GRAY);
equalizeHist(gray, gray);

vector<Rect> faces;
face_cascade.detectMultiScale(gray, faces);

for (size_t i = 0; i < faces.size(); i++) {
Point center(faces[i].x + faces[i].width/2, faces[i].y + faces[i].height/2);
ellipse(frame, center, Size(faces[i].width/2, faces[i].height/2), 0, 0, 360, Scalar(255, 0, 255), 4);

Mat faceROI = gray(faces[i]);
vector<Rect> eyes;
eyes_cascade.detectMultiScale(faceROI, eyes);

for (size_t j = 0; j < eyes.size(); j++) {
Point eye_center(faces[i].x + eyes[j].x + eyes[j].width/2,
faces[i].y + eyes[j].y + eyes[j].height/2);
int radius = cvRound((eyes[j].width + eyes[j].height) * 0.25);
circle(frame, eye_center, radius, Scalar(255, 0, 0), 4);
}
}

imshow("Capture - Face detection", frame);
}

Run Command:

./objectDetection --camera=0 \
--face_cascade=/usr/local/share/opencv4/haarcascades/haarcascade_frontalface_alt.xml \
--eyes_cascade=/usr/local/share/opencv4/haarcascades/haarcascade_eye_tree_eyeglasses.xml

Make sure the XML files are available in /usr/share/opencv4/haarcascades or /usr/local/share/opencv4/haarcascades.