Измерение расстояния на фотографии с помощью Python и OpenCV

В этой статье мы расскажем, как создать инструмент для измерения расстояний на фотографии, используя язык программирования Python и библиотеку OpenCV. Для измерения расстояний на фотографии мы используем известное расстояние между зрачками человека — 6 см.

Зрачки автоматически обнаруживаются с помощью алгоритма Хаара, встроенного в OpenCV. После определения расстояния между зрачками в пикселях можно вычислить коэффициент преобразования пикселей в сантиметры и применять его для измерения других расстояний на изображении.

Что потребуется: перед началом убедитесь, что на вашем компьютере установлены следующие инструменты и библиотеки: Python 3.x и OpenCV — библиотека для работы с изображениями.

Вот полный код программы. Он автоматически обнаруживает зрачки, дает пользователю возможность выбрать две точки на изображении, рисует стрелку между ними и отображает расстояние в сантиметрах.

import cv2
import numpy as np

# Константа - расстояние между зрачками в реальной жизни (в сантиметрах)
INTERPUPILLARY_DISTANCE_CM = 6.0

# Глобальные переменные для координат точек
points = []

def click_event(event, x, y, flags, param):
    global points
    image = param["original_image"].copy()
    interpupillary_distance_px = param["interpupillary_distance_px"]

    if event == cv2.EVENT_LBUTTONDOWN:
        points.append((x, y))
        cv2.circle(image, (x, y), 5, (0, 255, 0), -1)
        cv2.imshow("Image", image)
        
        # Если выбраны две точки
        if len(points) == 2:
            # Вычисляем расстояние в пикселях
            distance_px = np.sqrt((points[1][0] - points[0][0])**2 + (points[1][1] - points[0][1])**2)
            cm_per_px = INTERPUPILLARY_DISTANCE_CM / interpupillary_distance_px
            distance_cm = distance_px * cm_per_px

            # Отобразить стрелку и текст на изображении
            midpoint = ((points[0][0] + points[1][0]) // 2, (points[0][1] + points[1][1]) // 2)
            cv2.arrowedLine(image, points[0], points[1], (255, 0, 0), 2, tipLength=0.05)
            cv2.putText(image, f"{distance_cm:.2f} cm", midpoint, cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
            
            # Показать обновленное изображение
            cv2.imshow("Image", image)
            print(f"Расстояние между точками: {distance_cm:.2f} см")
            
            # Сбросить точки для нового измерения
            points.clear()

def detect_eyes(image):
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    eye_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + "haarcascade_eye.xml")
    eyes = eye_cascade.detectMultiScale(gray, 1.3, 5)

    if len(eyes) >= 2:
        # Берем два самых крупных глаза
        eyes = sorted(eyes, key=lambda x: x[2] * x[3], reverse=True)[:2]
        eye_centers = [(x + w // 2, y + h // 2) for x, y, w, h in eyes]
        return eye_centers
    else:
        print("Не удалось определить два глаза.")
        return None

# Загрузка изображения
image_path = "path_to_your_image.jpg"  # Замените на путь к вашему изображению
image = cv2.imread(image_path)

if image is None:
    print("Ошибка: изображение не найдено!")
    exit()

# Определение зрачков
eye_centers = detect_eyes(image)
if eye_centers:
    for center in eye_centers:
        cv2.circle(image, center, 10, (255, 0, 0), -1)

    # Расчет расстояния между зрачками в пикселях
    interpupillary_distance_px = np.sqrt((eye_centers[1][0] - eye_centers[0][0])**2 +
                                         (eye_centers[1][1] - eye_centers[0][1])**2)

    print(f"Расстояние между зрачками (пиксели): {interpupillary_distance_px:.2f}")
    print("Теперь укажите две точки на изображении для измерения расстояния.")

    # Установка обратного вызова мыши
    param = {
        "original_image": image.copy(),
        "interpupillary_distance_px": interpupillary_distance_px
    }
    cv2.imshow("Image", image)
    cv2.setMouseCallback("Image", click_event, param=param)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
else:
    print("Программа завершена.")
Как это работает
  1. Определение зрачков
    Используется предварительно обученный каскад Хаара для поиска глаз на изображении. Центры двух самых крупных областей считаются центрами зрачков.
  2. Вычисление масштаба
    Расстояние между зрачками в пикселях измеряется, после чего рассчитывается масштаб, преобразующий пиксели в сантиметры.
  3. Измерение расстояний
    Пользователь выбирает две точки на изображении. Программа рассчитывает расстояние между ними в пикселях, преобразует его в сантиметры и отображает результат на изображении.
  4. Отображение результата
    На изображении рисуется стрелка между выбранными точками, а также подписывается измеренное расстояние.
Пример использования

Укажите путь к изображению в переменной image_path.

image_path = "person_photo.jpg"

Запустите программу. На изображении автоматически будут выделены зрачки.

Нажмите на изображении, чтобы указать две точки. Программа нарисует стрелку между ними и отобразит расстояние в сантиметрах.

Применение

Этот инструмент может быть полезен в медицине, инженерии, архитектуре и других областях, где требуется измерение объектов на изображениях с известным масштабом.

Попробуйте внедрить его в ваши проекты или доработать под ваши задачи!