单目测距系统 —— 基于已知物体大小的距离估算
项目描述
本项目是一个单目测距系统,旨在通过已知物体的实际大小来计算该物体与相机之间的距离。系统包括一个用户界面(UI),允许用户轻松配置和操作。此外,系统支持自定义模型权重,使得用户可以根据自己的需求更换模型以优化测距效果。此项目适用于需要精确距离估算的应用场景,如自动驾驶、机器人导航、安防监控等。
关键功能
-
焦距计算:
- 程序能够根据已知物体的实际大小及其在图像中的尺寸来计算相机的焦距。
-
距离估算:
- 通过物体在图像中的大小和先前计算的焦距,程序能够估算出物体与相机之间的距离。
-
用户界面:
- 提供了一个图形用户界面(GUI),使得用户能够直观地输入物体的实际大小,并查看测距结果。
-
模型灵活性:
- 允许用户更换模型权重,以适应不同的应用场景或提高特定物体的检测精度。
-
实时测距:
- 支持从摄像头实时捕获图像并进行距离估算。
-
离线测距:
- 用户可以从本地文件系统中上传单张或多张图片进行批量测距。
技术栈
- Python:项目的主要编程语言。
- OpenCV:用于图像处理和摄像头流的捕获。
- PyQt5 或 Pyside6:用于构建图形用户界面。
- 深度学习框架:如TensorFlow或PyTorch,用于模型训练和推理。
关键代码示例
以下是一个简化的代码示例,展示如何使用已知物体大小来计算焦距,并基于焦距和物体在图像中的大小来估算距离。
1. 焦距计算与距离估算
首先,定义一个函数来计算焦距,并基于焦距进行距离估算。
1import cv2
2import numpy as np
3
4def calculate_focal_length(known_width, known_distance):
5 """
6 Calculate the focal length of the camera using a known width at a known distance.
7
8 Args:
9 known_width (float): The known width of an object in meters.
10 known_distance (float): The known distance of the object from the camera in meters.
11
12 Returns:
13 float: The calculated focal length in pixels.
14 """
15 # 假设在距离known_distance处,已知宽度为known_width的对象在图像中的宽度为100像素
16 return known_distance * 100 / known_width
17
18def estimate_distance(known_width, object_width_in_pixels, focal_length):
19 """
20 Estimate the distance to an object using its known width and measured width in pixels.
21
22 Args:
23 known_width (float): The known width of the object in meters.
24 object_width_in_pixels (float): The measured width of the object in the image in pixels.
25 focal_length (float): The focal length of the camera in pixels.
26
27 Returns:
28 float: The estimated distance to the object in meters.
29 """
30 return (known_width * focal_length) / object_width_in_pixels
2. 用户界面
接下来,构建一个用户界面(使用PyQt5为例),允许用户输入已知物体的宽度,并显示测距结果。
1import sys
2from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton, QVBoxLayout, QWidget, QLineEdit, QLabel, QFileDialog, QTextEdit
3from PyQt5.QtGui import QImage, QPixmap
4from PyQt5.QtCore import QTimer
5
6class MonocularDistanceEstimationApp(QMainWindow):
7 def __init__(self):
8 super().__init__()
9 self.setWindowTitle('Monocular Distance Estimation')
10 self.setGeometry(100, 100, 800, 600)
11
12 self.central_widget = QWidget()
13 self.setCentralWidget(self.central_widget)
14
15 self.layout = QVBoxLayout()
16 self.central_widget.setLayout(self.layout)
17
18 self.image_label = QLabel()
19 self.layout.addWidget(self.image_label)
20
21 self.input_layout = QVBoxLayout()
22
23 self.known_width_input = QLineEdit()
24 self.known_width_input.setPlaceholderText('Enter known width in meters')
25 self.input_layout.addWidget(self.known_width_input)
26
27 self.distance_label = QLabel('Distance:')
28 self.input_layout.addWidget(self.distance_label)
29
30 self.distance_output = QTextEdit()
31 self.distance_output.setReadOnly(True)
32 self.input_layout.addWidget(self.distance_output)
33
34 self.layout.addLayout(self.input_layout)
35
36 self.camera_button = QPushButton('Use Camera')
37 self.camera_button.clicked.connect(self.use_camera)
38 self.layout.addWidget(self.camera_button)
39
40 self.file_button = QPushButton('Upload File')
41 self.file_button.clicked.connect(self.upload_file)
42 self.layout.addWidget(self.file_button)
43
44 self.cap = None
45 self.timer = QTimer()
46 self.timer.timeout.connect(self.update_frame)
47
48 def use_camera(self):
49 self.cap = cv2.VideoCapture(0) # 使用默认摄像头
50 self.timer.start(30) # 每30毫秒更新一次图像
51
52 def upload_file(self):
53 file_name, _ = QFileDialog.getOpenFileName(self, 'Open Image File', '', 'Image Files (*.jpg *.jpeg *.png)')
54 if file_name:
55 img = cv2.imread(file_name)
56 self.calculate_distance(img)
57
58 def calculate_distance(self, image):
59 known_width = float(self.known_width_input.text())
60 if known_width <= 0:
61 self.distance_output.setText('Please enter a valid positive width.')
62 return
63
64 # 这里简化处理,假设已知物体在图像中的宽度为100像素
65 object_width_in_pixels = 100
66
67 # 假设已知物体与相机的距离为100米
68 known_distance = 100
69
70 # 计算焦距
71 focal_length = calculate_focal_length(known_width, known_distance)
72
73 # 估算距离
74 distance = estimate_distance(known_width, object_width_in_pixels, focal_length)
75
76 self.distance_output.setText(f'Distance: {distance:.2f} meters')
77
78 # 将OpenCV图像转换为QPixmap以便在QLabel中显示
79 height, width, channel = image.shape
80 bytes_per_line = 3 * width
81 q_img = QImage(image.data, width, height, bytes_per_line, QImage.Format_RGB888).rgbSwapped()
82 pixmap = QPixmap.fromImage(q_img)
83 self.image_label.setPixmap(pixmap)
84
85 def update_frame(self):
86 ret, frame = self.cap.read()
87 if ret:
88 self.calculate_distance(frame)
89
90 def closeEvent(self, event):
91 if self.cap is not None:
92 self.cap.release()
93 self.timer.stop()
94 event.accept()
95
96if __name__ == '__main__':
97 app = QApplication(sys.argv)
98 window = MonocularDistanceEstimationApp()
99 window.show()
100 sys.exit(app.exec_())
说明
- 焦距计算:通过已知物体的实际宽度和其在图像中的宽度来计算相机的焦距。
- 距离估算:基于焦距和物体在图像中的宽度来估算物体与相机之间的距离。
- 用户界面:构建了一个简单的用户界面,允许用户选择使用摄像头或上传图片进行测距,并显示测距结果。
- 视频处理:当用户选择使用摄像头后,程序会读取视频流,并通过已知物体大小和焦距来估算距离。测距结果会在界面上展示。
总结
此单目测距系统通过结合焦距计算和已知物体大小的距离估算算法,实现了对物体距离的精确测量。系统提供了用户友好的界面,使得用户可以方便地选择使用摄像头或上传图片进行测距,并查看测距结果。该系统适用于多种应用场景,如自动驾驶、机器人导航、安防监控等。通过更换模型权重,用户可以根据自己的需求进一步优化测距性能。