Distance Estimation with single-camera OpenCV python
So right then, how can we find the distance from the object camera in real-time with the webcam at decent accuracy, without requiring any extra hardware like a stereo camera or depth sensor at all?
This blog post will cover the implementation of a simple algorithm call triangle similarity, for object detection, we will keep that simple by just using face detection of OpenCV.
Codebase
The code will be available on my GitHub Repository, where I am going to explain important code snippets, In case you need help, just leave a comment, I will be happy to help you out 😎
Requirements
Requirements are pretty simple you need Python, OpenCV, and Haar-cascade files for face detection.
Having python installed on your machine, just open the terminal, and following in the terminal and you are done.
pip install opencv-python # on Linux turn pip to pip3
Capture the Reference Image
The reference image, allows us to map the real world(object plane) since we lose the depth of the object when we capture it in 2D space(image), otherwise, we need a special camera, that can capture the depth since we want to use our webcam, the reference image is required, you need to take care of few things, so accuracy won’t drop, you can use mine reference image it won’t affect much, but I will recommend to capture it yourself to get more accuracy.
Same Size
Recommend using the same camera for distance estimation and for capturing reference images.
keep the camera straight as possible while capturing the reference images.
here is a script for capturing a reference image
Measure distance from object camera, note it down, and capture the image,
Measure the width of the object, and note it down as well.
Important Variables
# distance from camera to object(face) measured
KNOWN_DISTANCE = 76.2 # centimeter
# width of face in the real world or Object Plane
KNOWN_WIDTH = 14.3 # centimeter
Object Detection (face)
I am using face detection here, it is implacable to every object detector, just follow the procedure.
face detection using Opencv python, here is the function which detects the face and returns face width, in pixels
# face detector function
def face_data(image):
'''
This function Detect the face
:param Takes image as argument.
:returns face_width in the pixels
'''
face_width = 0
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
faces = face_detector.detectMultiScale(gray_image, 1.3, 5)
for (x, y, h, w) in faces:
cv2.rectangle(image, (x, y), (x+w, y+h), WHITE, 1)
face_width = w
return face_width
Focal Length Finder
The Focal Length finder Function Tacks Three Arguments:
Measured_distance is the distance from the camera to the object while capturing the Reference image, Known_distance = 72.2 # centimetres
Real_width Its the measured width of an object in real-world, here I measure the width of the face which is around Known_width =14.3 # centimeters
Width_in_rf_image is the width of the object in the image/frame it will be in pixels
This function will return the focal length, which is used to find the distance.
# focal length finder function
def FocalLength(measured_distance, real_width, width_in_rf_image):
focal_length = (width_in_rf_image* measured_distance)/ real_width
return focal_length
Distance Finder
This Function Tasks Three Arguments,
Focal length in pixel, which is a return from the Focal length finder function
Real_width Its measures the width of an object in real-world, here I measure the width of the face which is around Known_width =14.3 # centimetre
Width_in_rf_image is the width of the object in the image/frame it will be in pixels
The distance finder function will return the distance in the centimetres
# distance estimation function
def Distance_finder(Focal_Length, real_face_width, face_width_in_frame):
distance = (real_face_width * Focal_Length)/face_width_in_frame
return distance
You can also create a face following a Robot using Distance Estimation