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

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

一、代码结构概览

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

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__方法
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方法
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方法
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方法
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
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列表中。

相关推荐

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

    2024-04-04 08:34:01       40 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-04-04 08:34:01       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-04-04 08:34:01       106 阅读
  3. 在Django里面运行非项目文件

    2024-04-04 08:34:01       87 阅读
  4. Python语言-面向对象

    2024-04-04 08:34:01       96 阅读

热门阅读

  1. python vtk获取模型角度

    2024-04-04 08:34:01       32 阅读
  2. [动态规划]代码随想录总结(自用)

    2024-04-04 08:34:01       33 阅读
  3. 限制promise并行执行个数

    2024-04-04 08:34:01       39 阅读
  4. Making Anti-Palindromes

    2024-04-04 08:34:01       40 阅读
  5. ‘iostream‘ file not foundclang(pp_file_not_found)

    2024-04-04 08:34:01       38 阅读
  6. Datacom HCIP笔记-BGP协议 之二

    2024-04-04 08:34:01       38 阅读
  7. html根据屏幕分辨率大小字体自动变大缩小

    2024-04-04 08:34:01       35 阅读