Perspektiva - měření výšky v obraze

Cvičení je zaměřené na vyzkoušení si měření výšky objektů v obraze pomocí úběžníků a úběžnic (viz přednáška Perspektiva a geometrie obrazu).

Z pohledu zpracování obrazu se jedná o hranovou detekci pomocí Cannyho detektoru následovanou Houghovou transformací, která nalezené hrany aproximuje přímkami. K zisku úběžníků a úběžnic z nalezených přímek je využit algoritmus RANSAC převzatý z githubu. Ten vyhledá nejvhodnější přímky jdoucí stejným směrem postupně do všech tří úběžníků.

Následně je využit vlastní algoritmus pro odhad výšky objektů HeightEstimator na základě měření známých rozměrů v obraze. Měřit je nutné vždy od spojnice roviny horizontální s rovinou vertikální ve směru osy z.

Na obrázku příkladu je znázorněno měření dvou referenčních vzdáleností. Dále je na něm znázorněna reálná výška dvou objektů - osob. Měření se zadává vždy v pořadí: bod Tx (top point) a následně bod Bx (bottom point).

Import knihoven a konfigurace

import os
import io

import cv2
import numpy as np
import matplotlib.pyplot as plt
import warnings

from improutils import *
from skimage import feature, color, transform

warnings.filterwarnings('ignore')
%matplotlib inline
np.set_printoptions(formatter={'float': lambda x: "{0:0.3f}".format(x)})

%run height-estimator.ipynb

Pomocné funkce

Seznam funkcí pro přehlednost:


Úkol

Vytvořte umělou scénu sestávající se ze dvou šachovnic na sebe kolmých. Do scény umístěte objekt, jehož výšku chcete změřit pomocí kamery.

Kamerou získejte obrázek a uložte ho. Následně změřte ručně v obraze dvě a více vzdáleností ve směru osy z (čím více vzdáleností, tím přesnější výsledek). Můžete využít znalosti toho, že jedno pole mřížky má stranu dlouhou 3 cm. Stejné vzdálenosti změřte i v reálné scéně.

Pomocí algoritmu získejte úběžnice a úběžníky. Pomocí nich spočtěte reálnou výšku objektu v obraze.

1) Vytvořte umělou scénu a změřte reálné rozměry v ose z

Umělá scéna by měla vypadat nějak podobně jako na obrázku.

No description has been provided for this image

2) Získejte obrázek umělé scény kamerou Basler a zobrazte

Využijte jakýkoli nástroj, se kterým se již pracovalo (Pylon, Práce s Basler kamerami notebook). Dejte pozor na ideální světelné podmínky, zaostření, clonu, expoziční čas, atd!

V případě, že záběr obrázku je větší než samotná scéna, ořízněte si obrázek tak, aby na něm okolí nebylo.

img_bgr = load_image("data/bat.jpg") ###
img_bgr = crop(img_bgr, 400, 0, 1700, 1100)
plot_images(img_bgr)
No description has been provided for this image

3) Transformujte obrázek z BGR do RGB a získejte souřadnice úběžníků

# Funkce compute_vanishing_points vykresluje obrázky pomocí knihovny matplotlib,
# která očekává kanály v pořadí RGB a ne BGR jako OpenCV
img_rgb = img_bgr[:, :, ::-1] ###
vps = compute_vanishing_points(img_rgb)
vp1 = [-430.1802602709107, 44.11434930044662, 0.08169323944527151]
No description has been provided for this image
vp2 = [-810.1351170684693, -66.29642195794906, -0.5799483264940831]
No description has been provided for this image
vp3 = [-19.409363985040574, -232.63073378047363, -0.00965892917013543]
No description has been provided for this image

POZOR: Vypočítané úběžníky nemusí nutně být ve správném pořadí! Zkontrolujte, zda vp1 a vp2 jsou horizontální úběžníky a vpz je úběžník v ose z. V případě, že tomu tak není, zaměňte indexy u vps tak, aby tomu tak bylo.

# POZOR! Úběžníky nemusí být ve správném pořadí!
vp1 = vps[0]
vp2 = vps[1]
vpz = vps[2]

4) Zjistěte souřadnice dvojic bodů pro referenční měrení

Vždy se ze dvojice nejdříve volí Tx a následně až Bx. Zvolte celkem 3 dvojice referenčních bodů (ty, pro které máte změřené reálné vzdálenosti) a najděte jejich souřadnice. Referenční body se volí vždy v rovině vertikální (viz úvod). Následně zvolte 1 dvojici bodů měřených.

show_images(img_bgr)
x = 939, y = 742
x = 927, y = 539
x = 716, y = 734
x = 705, y = 542
x = 324, y = 727
x = 300, y = 547
show_images(img_bgr)
x = 494, y = 933
x = 451, y = 449
x = 1116, y = 910
x = 1108, y = 466

5) Souřadnice doplňte na správná místa skriptu

REFERENCE_MEASUREMENTS jsou referenční dvojice bodů a jejich reálná vzdálenost. Tx a Bx je dvojice bodů měřených.

# Struktura: Tx x,y; Bx x,y; reálná vzdálenost
# např. ((10, 10), (20, 20), 100)
REFERENCE_MEASUREMENTS = [
    ((927, 539), (939, 742), 30), ###
    ((705, 542), (716, 734), 30), ###
    ((300, 547), (324, 727), 30)  ###
]

# Dvojice měřených bodů objektů z obrazu
Bx = (494, 933) ###
Tx = (451, 449) ###

6) Využijte algoritmus pro výpočet odhadu výšky měřeného objektu

# Horizont
vl = np.cross(vp1, vp2)

# Vytvoření objektu pro výpočet odhadu výšky objektu a zavolání funkce
height_estimator = HeightEstimator(REFERENCE_MEASUREMENTS, vl, vpz)
height = abs(height_estimator.calc_height(Tx, Bx))

# Výstup
print('Objekt {:.2f} mm'.format(height))
Objekt 55.65 mm

7*) Dobrovolná úloha za 1 bod aktivity

Upravte výše uvedené tak, abyste vypočítali výšku lidí z obrazu test.jpg. Pro kontrolu je reálná výška zobrazena na obrázku výše.

img_bgr = load_image('data/test.jpg') ###
# img_bgr = crop(img, 0, 347, 1516, 1182)
plot_images(img_bgr)
No description has been provided for this image
img_rgb = img_bgr[:, :, ::-1] ###
vps = compute_vanishing_points(img_rgb)
vp1 = [-445.1158247149197, 62.8823766458496, 0.13270698757944915]
No description has been provided for this image
vp2 = [24.34713061596313, 1361.8430688987967, 0.017541160386140585]
No description has been provided for this image
vp3 = [672.5564470778017, 287.5506635440653, 0.4956305143328221]
No description has been provided for this image
# POZOR! Úběžníky nemusí být ve správném pořadí!
vp1 = vps[0]
vp2 = vps[2]
vpz = vps[1]
show_images(img_bgr)
# Struktura: Tx x,y; Bx x,y; reálná vzdálenost
# např. ((10, 10), (20, 20), 100)
REFERENCE_MEASUREMENTS = [
    ((886, 611),(881, 801), 139), ###
    ((906, 799),(909, 595),  149), ###
]

# Dvojice měřených bodů objektů z obrazu
Bx0 = (1027, 965) ###
Tx0 = (1016, 510) ###
Bx1 = (1337, 912) ###
Tx1 = (1342, 495) ###
# Horizont
vl = np.cross(vp1, vp2)

# Vytvoření objektu pro výpočet odhadu výšky objektu a zavolání funkce
height_estimator = HeightEstimator(REFERENCE_MEASUREMENTS, vl, vpz)
height = abs(height_estimator.calc_height(Tx0, Bx0))

# Výstup
print('Objekt {:.2f} cm'.format(height))
Objekt 170.71 cm
# Horizont
vl = np.cross(vp1, vp2)

# Vytvoření objektu pro výpočet odhadu výšky objektu a zavolání funkce
height_estimator = HeightEstimator(REFERENCE_MEASUREMENTS, vl, vpz)
height = abs(height_estimator.calc_height(Tx1, Bx1))

# Výstup
print('Objekt {:.2f} cm'.format(height))
Objekt 187.34 cm