Skip navigation

Mintakeresés jellemzőpontok által OpenCV-ben

Minta keresése és illesztése

Az alábbi példában megnézzük, hogy hogyan tudunk egy mintát megtalálni egy képen. Ehhez a következő lépéseket kell végrehajtanunk:

  1. Képek megnyitása.
  2. Képek szürkeárnyalatossá konvertálása
  3. Jellemzőpontok keresése és leírók készítése mindkét képen.
  4. Jellemzőpontok párosítása.
  5. A pontpárok közötti homográfia kiszámítása.
  6. A homográfia végrehajtása.

A feladat megoldásához az OpenCV függvénykönyvtárat fogjuk használni.

Az alábbi képeket fogjuk használni:

      

import cv2
import numpy as np

SOURCE_IMAGE1='../DIP_konyv.jpg'
SOURCE_IMAGE2='../konyvek09.jpg'

MATCHING_IMAGE='flann_matching_DIP_konyv.jpg'

## képek beolvasása
img1 = cv2.imread(SOURCE_IMAGE1);
img2 = cv2.imread(SOURCE_IMAGE2);
h1,w1 = img1.shape[:2]
h2,w2 = img2.shape[:2]


## a képet szürkeárnyalatossá konvertáljuk
gray_img1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
gray_img2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)

## jellemzőpontok detektálása
surf = cv2.xfeatures2d.SURF_create()
keypoints1 = surf.detect(gray_img1, None)
keypoints2 = surf.detect(gray_img2, None)

## kulcspont leírók számítása
keypoints1, descriptors1 = surf.compute(gray_img1, keypoints1)
keypoints2, descriptors2 = surf.compute(gray_img2, keypoints2)

## pontpárok keresése
# FLANN parameterek
FLANN_INDEX_KDTREE = 0
index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5)
search_params = dict(checks=50)   # or pass empty dictionary

flann = cv2.FlannBasedMatcher(index_params,search_params)

matches = flann.knnMatch(descriptors1,descriptors2,k=2) ## ez kNN-alapú,
                                                        ## minden pontnak két lehetséges párja lehet

# csak a jó párosításokat tároljuk el, amelyek átmentek a Lowe-teszten
good = []
for m,n in matches:
    if m.distance < 0.7*n.distance:
        good.append(m)

points1 = []
points2 = []

for m in good:
    points1.append(keypoints1[m.queryIdx].pt)
    points2.append(keypoints2[m.trainIdx].pt)
points1, points2 = np.float32((points1, points2))

H, mask = cv2.findHomography(points1, points2, cv2.RANSAC)
matchesMask = mask.ravel().tolist() # azok a pontok, amelyek szerepelnek a párosításban

## a minta keretét egy téglalapként reprezentáljuk és ezt transzformáljuk
bounding_points = np.float32([ [0,0],[0,h1-1],[w1-1,h1-1],[w1-1,0] ]).reshape(-1,1,2)
transformed_points = cv2.perspectiveTransform(bounding_points,H)
int_transformed_points = np.int32(transformed_points)
img2 = cv2.polylines(img2,[int_transformed_points],True,255,10, cv2.LINE_AA)

draw_params = dict(matchColor = (0,255,0), # zöld színnel rajzolunk
                   singlePointColor = None,
                   matchesMask = matchesMask, # csak amit lemaszkoltunk azt rajzoljuk
                   flags = 2)

found_template_img = cv2.drawMatches(img1,keypoints1,img2,keypoints2,good,None,**draw_params)
cv2.imwrite("template_found.png", found_template_img )