Skip navigation

HCM optimalizálással (Python)

Feladat

Az előző programhoz hasonló feladatot old meg a 08_Kontur\Python\ mappában található ocv_scipy_powell_test.py példaprogram. X- és Y- irányú eltolásokat képes kezelni. Egy betöltött, kontúrt tartalmazó bináris képen detektálja a nem 0 értékű pontokat, mint a kontúr pontjait. Alkalmaz egy rögzített X- és Y-irányú eltolást a koordinátákra, és előállítja az új kontúr képet. Majd Powell optimalizálással megkeresi a legjobb illesztő paramétereket. Az egyes iterációs lépésekben meg is jeleníti az egymásra vetített kontúrokat.

A példában megismerhetjük a Scipy optimalizáló csomagjának használati módját.

Példaprogram

Szükséges importálások.

import cv2
import numpy as np
from scipy import optimize

Fix eltolási értékek (az eredeti kontúrra alkalmazva).

TRANS_X = -22
TRANS_Y = 3

Eredeti kontúr kép betöltése és kontúrpontok kinyerése.

im1 = cv2.imread('04_ol.png', cv2.IMREAD_GRAYSCALE)
# Extract contour points from im1
cnts1_y, cnts1_x = np.nonzero(im1)

im2 kontúrkép előállítása.

# Generating im2 by applying a known displacement to im1 contours
im2 = np.zeros((im1.shape[0], im1.shape[1]), np.uint8)
im2[cnts1_y + TRANS_Y, cnts1_x + TRANS_X] = 255

Egymásra vetített kontúr képek előállítása és megjelenítése.

# Blending contours
h, w = im1.shape[:2]
image_orig_blend = cv2.merge((np.zeros((h, w), np.uint8), im1, im2))
cv2.imshow('Originals (blended)', image_orig_blend)

Kontúrok kinyerése az illesztendő képből.

# Extract contour points of im2
cnts2_y, cnts2_x = np.nonzero(im2)

Távolságtérkép számítása.

# Distance map from the inverse of im1 and write result to image
# im1_dist = cv2.distanceTransform(255 - im1, cv2.DIST_L2, cv2.DIST_MASK_PRECISE)
im1_dist = cv2.distanceTransform(~im1, 2, 5)

Az optimalizálandó függvény. A params tömböt az optimalizáló módszer adja át. Ennek értelmezése a függvény feladata. A függvénynek vissza kell adnia, a paramétrek szerinti transzformáció után milyen távolságra kerülnek a kontúrok?

# Function to optimize (contour distance based on global displacement parameters)
def func(params):
    global im1_dist, cnts2_x, cnts2_y

    # Get parameters from optimizer
    dy = int(round(params[0]))
    dx = int(round(params[1]))

    # Compute distance
    distance_sum = 0
    for idx in range(0, len(cnts2_x)):
        distance_sum = distance_sum + im1_dist[cnts2_y[idx] + dy, cnts2_x[idx] + dx]

    print('params:', params, 'distance:', distance_sum)
    display_result(dx, dy)
    cv2.waitKey(100)

    return distance_sum

Kontúrok egymásra vetített megjelenítését végző függvény. 

def display_result(dx, dy):
    im2[:, :] = 0
    im2[cnts2_y + dy, cnts2_x + dx] = 255
    image_reg_blend = cv2.merge((np.zeros((h, w), np.uint8), im1, im2))
    cv2.imshow('Registered (blended)', image_reg_blend)

Optimalizáló paraméterezése és indítása. 

# Initial parameters (identical transformation)
x0 = np.array([0, 0])

# Start Powell optimization (from SciPy)
result = optimize.fmin_powell(func, x0)

Eredmények megjelenítése.

# Print and display result
print(result)
dist_y = int(round(result[0]))
dist_x = int(round(result[1]))
print('Result:', dist_x, dist_y)
display_result(dist_x, dist_y)

Program befejezése.

cv2.waitKey(0)
cv2.destroyAllWindows()

Feladatok

  • Az eredmény képet fájlba is írjuk ki!
  • Az im2 képet fájlból töltsük be, ne generáljuk!
  • Töltsünk be az eredetitől eltérő kontúrokat is illesztendőként!
  • Forgatásokat is vegyen figyelembe az optimalizáló!
  • Kezeljük a képtartományon kívül eső pontokat is! Jelen verzióban ez futási hibához vezet.