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:
- Capture Reference Image: Measure the distance from the object(face) to the camera, capture a Reference image and note down the measured distance
- Measure the object (face) width, make sure that measurement units are kept for reference image and object(face) width. Mine Reference Image
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.
Python3
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:
- Measured_distance: It is the distance from the camera to object while capturing the Reference image, Known_distance = 72.2 #centimeter
- 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
- 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.
Python3
# 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.
- Focal length in pixel, which is a return from the Focal length finder function
- 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
- 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
Python3
# 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:
Python3
# 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: