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.
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.
# 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
# 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: