📜  使用 OpenCV 进行实时距离估计 – Python

📅  最后修改于: 2022-05-13 01:54:57.873000             🧑  作者: Mango

使用 OpenCV 进行实时距离估计 – Python

先决条件: OpenCV简介

在本文中,我们将了解如何使用Python的OpenCV 计算网络摄像头的距离。通过使用它,人们可以处理图像和视频以识别物体、面孔,甚至是人类的笔迹。本文重点介绍检测对象。

我们将在本文中使用称为 haar 级联的东西进行对象检测。

哈尔瀑布

Haar Cascade 分类器是一种有效的目标检测方法。 Haar Cascade 是一种基于机器学习的方法,其中使用大量正负图像来训练分类器。

该文件可以从这里下载:Forrontalface。



距离估计步骤:

  • 捕捉参考图像:测量物体(人脸)到相机的距离,捕捉参考图像并记下测量的距离
  • 测量对象(人脸)宽度,确保保留参考图像和对象(人脸)宽度的测量单位。我的参考图片

人脸检测:

此函数将检测人脸并以像素值返回人脸宽度。这个人脸数据函数只接受一个参数,即哪个图像,返回以像素为单位的人脸宽度,这是焦距查找器和距离查找器函数。

Python3
def face_data(image):
 
    face_width = 0  # making face width to zero
 
    # converting color image ot 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


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


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


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 ot 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 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 the windows that are opened
cv2.destroyAllWindows()


焦距查找器:

焦距查找器函数三个参数:

  1. Measured_distance:拍摄参考图像时相机到物体的距离, Known_distance = 72.2 #centimeter
  2. Real_width:它测量的是现实世界中物体的宽度,这里我们测量的是人脸的宽度,大约为Known_width =14.3 #centimeter
  3. Width_in_rf_image:它是图像/帧中对象的宽度,以像素为单位

此函数将返回焦距,用于查找距离。

蟒蛇3

# 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

测距仪:

这个函数有三个参数。

  1. 以像素为单位的焦距,这是焦距查找器函数的返回值
  2. Real_width 测量现实世界中物体的宽度,这里我们测量的是人脸的宽度,大约为known_width =14.3 #centimete r
  3. Width_in_rf_image 是图像/帧中对象的宽度,以像素为单位

测距仪函数将返回以厘米为单位的距离



蟒蛇3

# 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

下面是完整的实现:

蟒蛇3

# 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 ot 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 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 the windows that are opened
cv2.destroyAllWindows()

输出: