当前位置: 首页 > article >正文

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

1. 项目背景

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

1. 安装所需的库

pip install opencv-python opencv-python-headless numpy

2. 代码实现

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 + 15
            cv2.putText(frame, label, (startX, y), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)

            # 计算物体的宽度和高度(以像素为单位)
            object_width = endX - startX
            object_height = endY - startY

            # 假设我们知道物体的实际尺寸,可以将其转换为实际长度
            # 例如,假设物体的实际宽度为10cm
            actual_width_cm = 10.0
            pixels_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

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 = None

class 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.layout

    def 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 + 15
                cv2.putText(frame, label, (startX, y), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)

                # 计算物体的宽度和高度(以像素为单位)
                object_width = endX - startX
                object_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_label

        return frame

    def 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 = texture

    def 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.kler.cn/a/561411.html

相关文章:

  • 计算机考研之数据结构:斐波那契数列专题(1)
  • Linux设备驱动开发-SPI驱动开发详解(包含设备树处理详细过程)
  • 第4章 Unicode 文本和字节序列
  • 神经网络 - 神经元
  • 【压力测试】要不要做全链路压测?
  • Jasper AI技术浅析(四):自然语言处理(NLP)与生成技术
  • 4部署kibana:5601
  • 【Python】2.获取pypi的api token 并把自己写好的库上传到pypi(保姆级图文)
  • 在 Windows 下的 Docker 中安装 R语言
  • Linux下安装Nginx服务及systemctl方式管理nginx详情
  • 编写一个程序,输入一个字符串并输出其长度(Java版)
  • Redis|持久化
  • 栅格地图路径规划:基于雪橇犬优化算法(Sled Dog Optimizer,SDO)的移动机器人路径规划(提供MATLAB代码)
  • day02
  • 推荐几款开源免费的 .NET MAUI 组件库
  • DeepSeek技术提升,Linux本地部署全攻略
  • 什么是可重入可重入锁?
  • AI算力加持,AORO M6 Pro智能对讲机构筑安全通信“数字化长城”
  • 2024最新版鸿蒙纯血原生应用开发教程文档丨学习ArkTS语言-基本语法
  • Java中将异步调用转为同步的五种方法