Open In App

Realtime Distance Estimation Using OpenCV – Python

Prerequisite: Introduction to OpenCV

In this article, we are going to see how to calculate the distance with a webcam using OpenCV in Python. By using it, one can process images and videos to identify objects, faces, or even the handwriting of a human. This article focuses on detecting objects.



We will do object detection in this article using something known as haar cascades.

Haar Cascades

Haar Cascade classifiers are an effective way for object detection. Haar Cascade is a machine learning-based approach where a lot of positive and negative images are used to train the classifier. 



The file can be downloaded from here:  Forrontalface.

Steps for Distance Estimation:

Face Detection:

This function will detect the face and return the face width in the pixels values. This face data function simply takes one argument, which image, returns the face width in the pixels, which is a requirement for the focal length finder and distance finder function. 




def face_data(image):
  
    face_width = 0  # making face width to zero
  
    # converting color image to gray scale image
    gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
  
    # detecting face in the image
    faces = face_detector.detectMultiScale(gray_image, 1.3, 5)
  
    # looping through the faces detect in the 
    # image getting coordinates x, y ,
    # width and height
    for (x, y, h, w) in faces:
  
        # draw the rectangle on the face
        cv2.rectangle(image, (x, y), (x+w, y+h), GREEN, 2)
  
        # getting face width in the pixels
        face_width = w
  
    # return the face width in pixel
    return face_width

Focal Length Finder:

The Focal Length finder Function Tacks Three Arguments: 

  1. Measured_distance: It is the distance from the camera to object while capturing the Reference image, Known_distance = 72.2 #centimeter
  2. Real_width: Its measure the width of an object in real-world, here we measure the width of the face which is around Known_width =14.3 #centimeter
  3. Width_in_rf_image: It 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 has three arguments.

  1. Focal length in pixel, which is a return from the Focal length finder function
  2. Real_width measures the width of an object in real-world, here we measure the width of the face  which is around Known_width =14.3 #centimeter
  3. 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 centimeters




# 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

Below is the full implementation:




# install opencv "pip install opencv-python"
import cv2
  
# distance from camera to object(face) measured
# centimeter
Known_distance = 76.2
  
# width of face in the real world or Object Plane
# centimeter
Known_width = 14.3
  
# Colors
GREEN = (0, 255, 0)
RED = (0, 0, 255)
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
  
# defining the fonts
fonts = cv2.FONT_HERSHEY_COMPLEX
  
# face detector object
face_detector = cv2.CascadeClassifier("haarcascade_frontalface_default.xml")
  
# focal length finder function
def Focal_Length_Finder(measured_distance, real_width, width_in_rf_image):
  
    # finding the focal length
    focal_length = (width_in_rf_image * measured_distance) / real_width
    return focal_length
  
# 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 the distance
    return distance
  
  
def face_data(image):
  
    face_width = 0  # making face width to zero
  
    # converting color image to gray scale image
    gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
  
    # detecting face in the image
    faces = face_detector.detectMultiScale(gray_image, 1.3, 5)
  
    # looping through the faces detect in the image
    # getting coordinates x, y , width and height
    for (x, y, h, w) in faces:
  
        # draw the rectangle on the face
        cv2.rectangle(image, (x, y), (x+w, y+h), GREEN, 2)
  
        # getting face width in the pixels
        face_width = w
  
    # return the face width in pixel
    return face_width
  
  
# reading reference_image from directory
ref_image = cv2.imread("Ref_image.png")
  
# find the face width(pixels) in the reference_image
ref_image_face_width = face_data(ref_image)
  
# get the focal by calling "Focal_Length_Finder"
# face width in reference(pixels),
# Known_distance(centimeters),
# known_width(centimeters)
Focal_length_found = Focal_Length_Finder(
    Known_distance, Known_width, ref_image_face_width)
  
print(Focal_length_found)
  
# show the reference image
cv2.imshow("ref_image", ref_image)
  
# initialize the camera object so that we
# can get frame from it
cap = cv2.VideoCapture(0)
  
# looping through frame, incoming from 
# camera/video
while True:
  
    # reading the frame from camera
    _, frame = cap.read()
  
    # calling face_data function to find
    # the width of face(pixels) in the frame
    face_width_in_frame = face_data(frame)
  
    # check if the face is zero then not 
    # find the distance
    if face_width_in_frame != 0:
        
        # finding the distance by calling function 
        # Distance finder function need 
        # these arguments the Focal_Length,
        # Known_width(centimeters),
        # and Known_distance(centimeters)
        Distance = Distance_finder(
            Focal_length_found, Known_width, face_width_in_frame)
  
        # draw line as background of text
        cv2.line(frame, (30, 30), (230, 30), RED, 32)
        cv2.line(frame, (30, 30), (230, 30), BLACK, 28)
  
        # Drawing Text on the screen
        cv2.putText(
            frame, f"Distance: {round(Distance,2)} CM", (30, 35), 
          fonts, 0.6, GREEN, 2)
  
    # show the frame on the screen
    cv2.imshow("frame", frame)
  
    # quit the program if you press 'q' on keyboard
    if cv2.waitKey(1) == ord("q"):
        break
  
# closing the camera
cap.release()
  
# closing the windows that are opened
cv2.destroyAllWindows()

Output:


Article Tags :