OpenCV构建交互式图像距离测量工具

在计算机视觉和图形学应用中,准确测量图像上的点之间距离是一项常见且重要的任务。本篇技术博客将详细介绍如何利用Python编程语言和OpenCV库构建一个交互式的图像距离测量工具。我们将通过编写一个名为ImageProcessor的类,让用户能够在图像上点击选取点,并实时显示两点间的实际距离(以毫米为单位)。下面让我们一起深入探讨代码实现及其核心功能。

一、代码结构概览

首先,我们来看看整个程序的主要组成部分:

python 复制代码
import cv2
import numpy as np


class ImageProcessor:
    def __init__(self, image_path, pixel_to_mm=0.3):
        self.image_path = image_path
        self.pixel_to_mm = pixel_to_mm
        self.image = None
        self.points = []
        self.distances = []
        self.load_image()

    def load_image(self):
        try:
            self.image = cv2.imread(self.image_path)
        except FileNotFoundError:
            print("Image file not found.")
            exit()

    def calculate_distance(self, point1, point2):
        pixel_distance = np.sqrt((point2[0] - point1[0]) ** 2 + (point2[1] - point1[1]) ** 2)
        actual_distance = pixel_distance * self.pixel_to_mm
        return pixel_distance, actual_distance

    def draw_on_image(self):
        img_copy = self.image.copy()
        for i in range(len(self.points)):
            cv2.circle(img_copy, self.points[i], 3, (0, 0, 255), -1)  # Display Point
            if i % 2 == 1:
                cv2.line(img_copy, self.points[i - 1], self.points[i], (255, 0, 0), 2)  # Draw line between points

                pixel_distance, actual_distance = self.calculate_distance(self.points[i - 1], self.points[i])
                self.distances.append(actual_distance)
                text = "AD: {:.2f} mm".format(actual_distance)
                cv2.putText(img_copy, text, (
                (self.points[i - 1][0] + self.points[i][0]) // 2, (self.points[i - 1][1] + self.points[i][1]) // 2),
                            cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 0), 2)

        return img_copy

    def mouse_event(self, event, x, y, flags, param):
        if event == cv2.EVENT_LBUTTONDOWN:
            self.points.append((x, y))

    def process(self):
        cv2.namedWindow('Image')
        cv2.setMouseCallback('Image', self.mouse_event)

        while True:
            img_copy = self.draw_on_image()

            cv2.imshow('Image', img_copy)
            key = cv2.waitKey(1) & 0xFF
            if key == 27:  # Press 'Esc' to exit
                break

        cv2.destroyAllWindows()


if __name__ == "__main__":
    processor = ImageProcessor('mask/img.png', pixel_to_mm=0.3)
    processor.process()

该程序主要由以下几部分组成:

  1. 标题引入必要的库:cv2(OpenCV库)用于图像处理和显示,numpy(NumPy库)用于数值计算。

  2. 定义ImageProcessor类:封装图像加载、点选、距离计算、结果显示等逻辑。

  3. 主程序入口:创建ImageProcessor实例,传入图像路径和像素与毫米的比例,默认为0.3,然后调用process方法启动交互过程。

    接下来,我们将逐一解析ImageProcessor类中的关键方法。

二、ImageProcessor类详解

  1. __init__方法
python 复制代码
def __init__(self, image_path, pixel_to_mm=0.3):
    self.image_path = image_path
    self.pixel_to_mm = pixel_to_mm
    self.image = None
    self.points = []
    self.distances = []
    self.load_image()

__init__方法是类的构造器,负责初始化对象属性。这里定义了以下几个属性:

image_path: 存储待处理图像的路径。

pixel_to_mm: 像素与毫米之间的比例,默认值为0.3,表示每个像素代表0.3毫米。

image: 用于存放加载的图像数据。

points: 存储用户点击的点坐标,按点击顺序排列。

distances: 存储已计算的实际距离值。

最后,load_image方法被调用,用于加载指定路径下的图像

  1. load_image方法
python 复制代码
def load_image(self):
   try:
       self.image = cv2.imread(self.image_path)
   except FileNotFoundError:
       print("Image file not found.")
       exit()

load_image方法负责从指定路径加载图像。它使用cv2.imread函数尝试读取图像,如果文件不存在,则捕获FileNotFoundError异常,打印错误消息并退出程序,确保程序在遇到无效文件时能优雅终止。

  1. calculate_distance方法
python 复制代码
def calculate_distance(self, point1, point2):
    pixel_distance = np.sqrt((point2[0] - point1[0]) ** 2 + (point2[1] - point1[1]) ** 2)
    actual_distance = pixel_distance * self.pixel_to_mm
    return pixel_distance, actual_distance

calculate_distance方法接收两个点坐标作为参数,计算它们之间的像素距离(欧氏距离)并转换为实际距离(毫米)。结果以元组形式返回,包含像素距离和实际距离。

  1. draw_on_image方法
python 复制代码
def draw_on_image(self):
    img_copy = self.image.copy()
    for i in range(len(self.points)):
        cv2.circle(img_copy, self.points[i], 3, (0, 0, 255), -1)  # Display Point
        if i % 2 == 1:
            cv2.line(img_copy, self.points[i - 1], self.points[i], (255, 0, 0), 2)  # Draw line between points

            pixel_distance, actual_distance = self.calculate_distance(self.points[i - 1], self.points[i])
            self.distances.append(actual_distance)
            text = "AD: {:.2f} mm".format(actual_distance)
            cv2.putText(img_copy, text, (
            (self.points[i - 1][0] + self.points[i][0]) // 2, (self.points[i - 1][1] + self.points[i][1]) // 2),
                        cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 0), 2)

    return img_copy

draw_on_image方法负责在图像副本上绘制用户选择的点、连线及距离文字。具体步骤如下:

  • 创建图像副本,防止直接修改原始图像。
  • 遍历points列表,绘制每个点为红色圆圈。
  • 当索引i为奇数时,表示当前点与前一个点构成一对,于是:
    绘制连接这两个点的线。
    调用calculate_distance计算它们之间的实际距离,并将结果添加到distances列表。
    在两点之间合适的位置绘制包含实际距离的文字。
    最后返回处理过的图像副本。
  1. mouse_event
python 复制代码
def mouse_event(self, event, x, y, flags, param):
    if event == cv2.EVENT_LBUTTONDOWN:
        self.points.append((x, y))

mouse_event方法作为鼠标回调函数,响应用户的鼠标操作。当用户按下左键(cv2.EVENT_LBUTTONDOWN)时,将当前鼠标位置((x, y))添加到points列表中。

相关推荐
桃花键神28 分钟前
AI可信论坛亮点:合合信息分享视觉内容安全技术前沿
人工智能
野蛮的大西瓜1 小时前
开源呼叫中心中,如何将ASR与IVR菜单结合,实现动态的IVR交互
人工智能·机器人·自动化·音视频·信息与通信
CountingStars6191 小时前
目标检测常用评估指标(metrics)
人工智能·目标检测·目标跟踪
tangjunjun-owen1 小时前
第四节:GLM-4v-9b模型的tokenizer源码解读
人工智能·glm-4v-9b·多模态大模型教程
冰蓝蓝1 小时前
深度学习中的注意力机制:解锁智能模型的新视角
人工智能·深度学习
橙子小哥的代码世界2 小时前
【计算机视觉基础CV-图像分类】01- 从历史源头到深度时代:一文读懂计算机视觉的进化脉络、核心任务与产业蓝图
人工智能·计算机视觉
黄公子学安全2 小时前
Java的基础概念(一)
java·开发语言·python
新加坡内哥谈技术2 小时前
苏黎世联邦理工学院与加州大学伯克利分校推出MaxInfoRL:平衡内在与外在探索的全新强化学习框架
大数据·人工智能·语言模型
程序员一诺2 小时前
【Python使用】嘿马python高级进阶全体系教程第10篇:静态Web服务器-返回固定页面数据,1. 开发自己的静态Web服务器【附代码文档】
后端·python
小木_.3 小时前
【Python 图片下载器】一款专门为爬虫制作的图片下载器,多线程下载,速度快,支持续传/图片缩放/图片压缩/图片转换
爬虫·python·学习·分享·批量下载·图片下载器