详解:用Python OpenCV库来处理图像并测量物体的长度

ops/2025/2/26 9:28:52/
1. 项目背景

智能卷尺测量系统通过传感器和算法实现自动测量,具备高精度、便携性和数据存储功能,适用于建筑、制造等领域。该系统的核心算法涉及到图像处理、计算机视觉和机器学习等技术。本文主要介绍Python OpenCV库的处理逻辑。

1. 安装所需的库

pip install opencv-python opencv-python-headless numpy

2. 代码实现

python">import cv2
import numpy as np# 加载预训练的深度学习模型(例如:YOLO或SSD)
# 这里我们使用OpenCV自带的MobileNet SSD模型
net = cv2.dnn.readNetFromCaffe("deploy.prototxt",  # 模型配置文件"mobilenet_iter_73000.caffemodel"  # 预训练模型权重
)# 加载类别标签
CLASSES = ["background", "aeroplane", "bicycle", "bird", "boat","bottle", "bus", "car", "cat", "chair", "cow", "diningtable","dog", "horse", "motorbike", "person", "pottedplant","sheep", "sofa", "train", "tvmonitor"]# 初始化摄像头
cap = cv2.VideoCapture(0)while True:# 读取摄像头帧ret, frame = cap.read()if not ret:break# 获取帧的尺寸(h, w) = frame.shape[:2]# 预处理图像:缩放、归一化、交换通道blob = cv2.dnn.blobFromImage(frame, 0.007843, (300, 300), 127.5)net.setInput(blob)detections = net.forward()# 遍历检测结果for i in np.arange(0, detections.shape[2]):confidence = detections[0, 0, i, 2]# 过滤掉低置信度的检测结果if confidence > 0.2:idx = int(detections[0, 0, i, 1])box = detections[0, 0, i, 3:7] * np.array([w, h, w, h])(startX, startY, endX, endY) = box.astype("int")# 绘制边界框和标签label = "{}: {:.2f}%".format(CLASSES[idx], confidence * 100)cv2.rectangle(frame, (startX, startY), (endX, endY), (0, 255, 0), 2)y = startY - 15 if startY - 15 > 15 else startY + 15cv2.putText(frame, label, (startX, y), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)# 计算物体的宽度和高度(以像素为单位)object_width = endX - startXobject_height = endY - startY# 假设我们知道物体的实际尺寸,可以将其转换为实际长度# 例如,假设物体的实际宽度为10cmactual_width_cm = 10.0pixels_per_cm = object_width / actual_width_cm# 计算物体的实际高度actual_height_cm = object_height / pixels_per_cm# 显示测量结果measurement_label = "Width: {:.2f}cm, Height: {:.2f}cm".format(actual_width_cm, actual_height_cm)cv2.putText(frame, measurement_label, (startX, y + 20), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)# 显示结果帧cv2.imshow("Smart Tape Measure", frame)# 按下 'q' 键退出if cv2.waitKey(1) & 0xFF == ord('q'):break# 释放摄像头并关闭所有窗口
cap.release()
cv2.destroyAllWindows()

3. 代码说明

  • 模型加载:我们使用了OpenCV自带的MobileNet SSD模型来检测物体。你需要下载deploy.prototxtmobilenet_iter_73000.caffemodel文件。

  • 图像处理:我们使用cv2.dnn.blobFromImage对图像进行预处理,然后将其输入到神经网络中进行推理。

  • 物体检测:我们遍历检测结果,并过滤掉低置信度的检测结果。然后,我们绘制边界框和标签。

  • 测量:假设我们知道物体的实际尺寸(例如宽度为10cm),我们可以根据像素与实际尺寸的比例来计算物体的实际高度。

  • 显示结果:最后,我们在图像上显示测量结果。

4. 注意事项

  • 模型文件:你需要下载 MobileNet SSD 模型的配置文件和预训练权重文件deploy.prototxtmobilenet_iter_73000.caffemodel文件,并将它们放在与脚本相同的目录中。

  • deploy.prototxt: 下载链接

  • mobilenet_iter_73000.caffemodel: 下载链接

  • 实际尺寸:在实际应用中,你需要知道物体的实际尺寸才能进行准确的测量。你可以通过校准过程来确定像素与实际尺寸的比例。

  • 性能优化:在实际应用中,你可能需要对代码进行优化,以提高检测和测量的准确性。

5、创建图形化界面:

智能卷尺系统通常在移动终端(如手机或平板)上使用,我们使用适合移动开发的框架Kivy:一个开源的 Python 库,支持跨平台开发(包括 Android 和 iOS)。代码如下:

1. 安装 Kivy

首先,确保你已经安装了 Kivy。可以通过以下命令安装:

pip install kivy
2. 使用 Kivy 开发移动端智能卷尺系统

以下是一个完整的 Kivy 示例代码,集成了摄像头捕获和物体测量功能。

代码:smart_tape_measure.py

python">from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.image import Image
from kivy.clock import Clock
from kivy.graphics.texture import Texture
from kivy.uix.camera import Camera
import cv2
import numpy as np# 加载预训练的深度学习模型
net = cv2.dnn.readNetFromCaffe("deploy.prototxt", "mobilenet_iter_73000.caffemodel")# 加载类别标签
CLASSES = ["background", "aeroplane", "bicycle", "bird", "boat","bottle", "bus", "car", "cat", "chair", "cow", "diningtable","dog", "horse", "motorbike", "person", "pottedplant","sheep", "sofa", "train", "tvmonitor"]# 初始化全局变量
object_width_cm = 10.0  # 假设物体的实际宽度为10cm
pixels_per_cm = Noneclass SmartTapeMeasureApp(App):def build(self):# 主布局self.layout = BoxLayout(orientation='vertical')# 摄像头图像显示self.image_widget = Image()self.layout.add_widget(self.image_widget)# 测量结果标签self.result_label = Label(text="测量结果将显示在这里", size_hint=(1, 0.1))self.layout.add_widget(self.result_label)# 开始按钮self.start_button = Button(text="开始测量", size_hint=(1, 0.1))self.start_button.bind(on_press=self.start_measurement)self.layout.add_widget(self.start_button)# 初始化摄像头self.capture = cv2.VideoCapture(0)Clock.schedule_interval(self.update, 1.0 / 30.0)  # 每秒更新30帧return self.layoutdef start_measurement(self, instance):# 重置测量结果self.result_label.text = "测量中..."def update(self, dt):# 读取摄像头帧ret, frame = self.capture.read()if ret:# 处理图像processed_frame = self.process_image(frame)# 显示处理后的图像self.display_image(processed_frame)def process_image(self, frame):global pixels_per_cm(h, w) = frame.shape[:2]# 预处理图像blob = cv2.dnn.blobFromImage(frame, 0.007843, (300, 300), 127.5)net.setInput(blob)detections = net.forward()# 遍历检测结果for i in np.arange(0, detections.shape[2]):confidence = detections[0, 0, i, 2]# 过滤掉低置信度的检测结果if confidence > 0.2:idx = int(detections[0, 0, i, 1])box = detections[0, 0, i, 3:7] * np.array([w, h, w, h])(startX, startY, endX, endY) = box.astype("int")# 绘制边界框和标签label = "{}: {:.2f}%".format(CLASSES[idx], confidence * 100)cv2.rectangle(frame, (startX, startY), (endX, endY), (0, 255, 0), 2)y = startY - 15 if startY - 15 > 15 else startY + 15cv2.putText(frame, label, (startX, y), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)# 计算物体的宽度和高度(以像素为单位)object_width = endX - startXobject_height = endY - startY# 计算像素与实际尺寸的比例if pixels_per_cm is None:pixels_per_cm = object_width / object_width_cm# 计算物体的实际高度actual_height_cm = object_height / pixels_per_cm# 更新测量结果measurement_label = "Width: {:.2f}cm, Height: {:.2f}cm".format(object_width_cm, actual_height_cm)self.result_label.text = measurement_labelreturn framedef display_image(self, frame):# 将 OpenCV 图像转换为 Kivy 纹理frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)buf = frame.tostring()texture = Texture.create(size=(frame.shape[1], frame.shape[0]), colorfmt='rgb')texture.blit_buffer(buf, colorfmt='rgb', bufferfmt='ubyte')self.image_widget.texture = texturedef on_stop(self):# 释放摄像头self.capture.release()if __name__ == '__main__':SmartTapeMeasureApp().run()
3. 代码说明
  1. Kivy 界面

    • 使用 BoxLayout 构建了一个简单的界面,包含一个图像显示区域、一个测量结果标签和一个开始按钮。

    • 点击“开始测量”按钮后,系统会开始处理摄像头帧并显示测量结果。

  2. 摄像头捕获

    • 使用 OpenCV 捕获摄像头帧,并通过 Kivy 的 Texture 将帧显示在界面上。

  3. 物体检测与测量

    • 使用 MobileNet SSD 模型检测物体,并计算物体的实际尺寸。

    • 假设物体的实际宽度为 10cm,根据像素与实际尺寸的比例计算物体的实际高度。

  4. 实时更新

    • 使用 Kivy 的 Clock 定时器每秒更新 30 帧,实现实时测量。


4. 运行步骤
  1. 确保已安装 Kivy 和 OpenCV。

  2. 将 deploy.prototxt 和 mobilenet_iter_73000.caffemodel 文件放在与脚本相同的目录中。

  3. 运行脚本:

    python smart_tape_measure.py
  4. 点击“开始测量”按钮,系统会实时显示摄像头画面和测量结果。

6. 打包为移动应用

要将 Kivy 应用打包为 Android 或 iOS 应用,可以使用 Buildozer 或 Kivy-iOS。

以下使用 Buildozer 打包为 Android APK

  1. 安装 Buildozer:

    pip install buildozer
  2. 在项目目录中初始化 Buildozer:

  3. buildozer init
  4. 修改 buildozer.spec 文件,确保包含 OpenCV 和其他依赖项。

  5. 打包 APK:

    buildozer -v android debug
  6. 生成的 APK 文件位于 bin 目录中,可以安装到 Android 设备上运行。


http://www.ppmy.cn/ops/161378.html

相关文章

akka现有的分布式定时任务框架总结

根据你的需求,以下是一些基于 Akka 实现的分布式定时任务框架,以及相关的 GitHub 项目推荐: 1. Openjob Openjob 是一个基于 Akka 架构的新一代分布式任务调度框架,支持多种定时任务、延时任务、工作流设计,采用无中…

【工欲善其事】2025 年实现听书自由——基于 Kokoro-82M 的开源 TTS 工具 audiblez 本地部署实战

文章目录 2025 年实现听书自由——基于 Kokoro-82M 的开源 TTS 工具 audiblez 本地部署实战1 前言2 本地部署准备工作3 具体安装步骤4 命令行启动测试5 GUI 界面启动测试6 相关资源一站式下载 2025 年实现听书自由——基于 Kokoro-82M 的开源 TTS 工具 audiblez 本地部署实战 …

Docker基础-常见命令

docker images -查看所有的本地镜像。 docker pull -把远端镜像拉取到本地。 docker rmi -删除镜像。 docker push -推到镜像仓库。 docker run -创建并运行容器(自动化,如果发现镜像不存在会先去拉取, 拉取完了以后再去自动创建容器&am…

从工程师到系统架构设计师

在技术领域,从一名初出茅庐的工程师成长为独当一面的系统架构设计师,是一条需要长期积累、持续突破的路径。这一过程不仅需要扎实的技术功底,更需要思维的升级和视野的拓展。以下将结合不同阶段的特征,为你梳理一条清晰的成长路线…

java面试项目介绍,详细说明

金三银四少走弯路,Java岗面试冲刺,你与大厂只差这篇文章包括面试准备,帮助大家少走弯路,成功入职大厂,并快速成长落地。 祝大家拿到满意的offer!(把许愿的offer发在评论区,一定会实现的) 主要从四大方面:掌握的主要知识、算法、项目、简历 掌握的主要知识 下面是我看过的资料和…

在 compare-form.vue 中添加 compareDate 隐藏字段,并在提交时自动填入当前时间

在 compare-form.vue 中添加 compareDate 隐藏字段,并在提交时自动填入当前时间。 提交表单时存入的对象是FakeRegistration,这个对象里面有compareDate字段,刚好表格查询的对象也是FakeRegistration,所以表格展示的时间就是刚才…

【AAAI2025】风车卷积替代标准卷积,增强了底层特征提取能力

Pinwheel-shaped Convolution and Scale-based Dynamic Loss for Infrared Small Target Detection 基于风车形卷积和尺度动态损失的红外小目标检测 风车形卷积(PConv)模块: 作者提出了一种新颖的风车形卷积(PConv)…

【C++ 真题】P2814 家谱

P2814 家谱 题目背景 现代的人对于本家族血统越来越感兴趣。 题目描述 给出充足的父子关系,请你编写程序找到某个人的最早的祖先。 输入格式 输入由多行组成,首先是一系列有关父子关系的描述,其中每一组父子关系中父亲只有一行&#xf…