def match_outlines(self, orig_image, skewed_image):
orig_image = np.array(orig_image)
skewed_image = np.array(skewed_image)
try:
surf = cv2.xfeatures2d.SURF_create(400)
except Exception:
surf = cv2.SIFT(400)
kp1, des1 = surf.detectAndCompute(orig_image, None)
kp2, des2 = surf.detectAndCompute(skewed_image, None)
FLANN_INDEX_KDTREE = 0
index_params = dict(algorithm=FLANN_INDEX_KDTREE, trees=5)
search_params = dict(checks=50)
flann = cv2.FlannBasedMatcher(index_params, search_params)
matches = flann.knnMatch(des1, des2, k=2)
# store all the good matches as per Lowe's ratio test.
good = []
for m, n in matches:
if m.distance < 0.7 * n.distance:
good.append(m)
MIN_MATCH_COUNT = 10
if len(good) > MIN_MATCH_COUNT:
src_pts = np.float32([kp1[m.queryIdx].pt for m in good
]).reshape(-1, 1, 2)
dst_pts = np.float32([kp2[m.trainIdx].pt for m in good
]).reshape(-1, 1, 2)
M, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 5.0)
# see https://ch.mathworks.com/help/images/examples/find-image-rotation-and-scale-using-automated-feature-matching.html for details
ss = M[0, 1]
sc = M[0, 0]
scaleRecovered = math.sqrt(ss * ss + sc * sc)
thetaRecovered = math.atan2(ss, sc) * 180 / math.pi
self.log.info("MAP: Calculated scale difference: %.2f, "
"Calculated rotation difference: %.2f" %
(scaleRecovered, thetaRecovered))
#deskew image
im_out = cv2.warpPerspective(skewed_image, np.linalg.inv(M),
(orig_image.shape[1], orig_image.shape[0]))
return im_out
else:
self.log.warn("MAP: Not enough matches are found - %d/%d"
% (len(good), MIN_MATCH_COUNT))
return skewed_image
python类FlannBasedMatcher()的实例源码
def match(query_feature, train_feature):
"""
calculate some match result between two images' feature data
parameter :
'query_feature' is one image's feature data
'train_feature' is another image's feature data
both like ( keypoints, descriptros, (height,width) )
keypoints is like [ pt1, pt2, pt3, ... ]
return value :
True of False
steps :
1. create a matcher
2. do match
"""
flann_params = dict(algorithm=1, trees=5)
matcher = cv2.FlannBasedMatcher(flann_params,{})
res=matchFeatures(query_feature, train_feature, matcher)
del flann_params
del matcher
return res
# function used to get current milli timestamp
def checkAvailability(sift, tkp, tdes, matchimg):
"""
:param sift:
:param tkp:
:param tdes:sift feature object, template keypoints, and template descriptor
:param matchimg:
:return:
"""
qimg = cv2.imread(matchimg)
qimggray = cv2.cvtColor(qimg,cv2.COLOR_BGR2GRAY)
# kernel = np.ones((5,5), np.uint8)
# qimggray = cv2.erode(qimggray, kernel, iterations=1)
# ret,threshimg = cv2.threshold(qimggray,100,255,cv2.THRESH_BINARY)
qkp,qdes = sift.detectAndCompute(qimggray, None)
# plt.imshow(threshimg, 'gray'), plt.show()
FLANN_INDEX_KDITREE=0
index_params=dict(algorithm=FLANN_INDEX_KDITREE,tree=5)
# FLANN_INDEX_LSH = 6
# index_params = dict(algorithm=FLANN_INDEX_LSH,
# table_number=12, # 12
# key_size=20, # 20
# multi_probe_level=2) # 2
search_params = dict(checks = 50)
flann=cv2.FlannBasedMatcher(index_params,search_params)
matches=flann.knnMatch(tdes,qdes,k=2)
goodMatch=[]
for m_n in matches:
if len(m_n) != 2:
continue
m, n = m_n
if(m.distance<0.75*n.distance):
goodMatch.append(m)
MIN_MATCH_COUNT = 30
if (len(goodMatch) >= MIN_MATCH_COUNT):
tp = []
qp = []
for m in goodMatch:
tp.append(tkp[m.queryIdx].pt)
qp.append(qkp[m.trainIdx].pt)
tp, qp = np.float32((tp, qp))
H, status = cv2.findHomography(tp, qp, cv2.RANSAC, 3.0)
h = timg.shape[0]
w = timg.shape[1]
trainBorder = np.float32([[[0, 0], [0, h - 1], [w - 1, h - 1], [w - 1, 0]]])
queryBorder = cv2.perspectiveTransform(trainBorder, H)
cv2.polylines(qimg, [np.int32(queryBorder)], True, (0, 255, 0), 5)
cv2.imshow('result', qimg)
plt.imshow(qimg, 'gray'), plt.show()
return True
else:
print "Not Enough match found- %d/%d" % (len(goodMatch), MIN_MATCH_COUNT)
return False
# cv2.imshow('result', qimg)
# if cv2.waitKey(10) == ord('q'):
# cv2.destroyAllWindows()
def __init__(self, img, min_match_count=10, flann_index=0, flann_trees=5,
flann_checks=50):
self.min_match_count = min_match_count
self.thing = img
self.rvr_comm,self.sdr_comm = multiprocessing.Pipe(duplex=False)
# Initiate SIFT detector
self.sift = cv2.xfeatures2d.SIFT_create()
# Find keypoints and descriptors of thing with SIFT
self.keypoints, self.descriptors = self.sift.detectAndCompute(img,
None)
print 'num keypoints =', len(self.keypoints)
# Initiate FLANN matcher
index_params = dict(algorithm = flann_index, trees = flann_trees)
search_params = dict(checks = flann_checks)
self.flann = cv2.FlannBasedMatcher(index_params, search_params)
def find_correspondence_points(img1, img2):
sift = cv2.xfeatures2d.SIFT_create()
# find the keypoints and descriptors with SIFT
kp1, des1 = sift.detectAndCompute(
cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY), None)
kp2, des2 = sift.detectAndCompute(
cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY), None)
# Find point matches
FLANN_INDEX_KDTREE = 0
index_params = dict(algorithm=FLANN_INDEX_KDTREE, trees=5)
search_params = dict(checks=50)
flann = cv2.FlannBasedMatcher(index_params, search_params)
matches = flann.knnMatch(des1, des2, k=2)
# Apply Lowe's SIFT matching ratio test
good = []
for m, n in matches:
if m.distance < 0.8 * n.distance:
good.append(m)
src_pts = np.asarray([kp1[m.queryIdx].pt for m in good])
dst_pts = np.asarray([kp2[m.trainIdx].pt for m in good])
# Constrain matches to fit homography
retval, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 100.0)
mask = mask.ravel()
# We select only inlier points
pts1 = src_pts[mask == 1]
pts2 = dst_pts[mask == 1]
return pts1.T, pts2.T
def __init__(self, image,
maxImageSize=1000,
minInlierRatio=0.15, minInliers=25,
fast=False):
'''
maxImageSize -> limit image size to speed up process, set to False to deactivate
minInlierRatio --> [e.g:0.2] -> min 20% inlier need to be matched, else: raise Error
'''
self.signal_ranges = []
self.maxImageSize = maxImageSize
self.minInlierRatio = minInlierRatio
self.minInliers = minInliers
self._fH = None # homography factor, if image was resized
self.base8bit = self._prepareImage(image)
# Parameters for nearest-neighbour matching
# flann_params = dict(algorithm=1, trees=2)
# self.matcher = cv2.FlannBasedMatcher(flann_params, {})
# PATTERN DETECTOR:
# self.detector = cv2.BRISK_create()
if fast:
self.detector = cv2.ORB_create()
else:
self.detector = cv2.ORB_create(
nfeatures=70000,
# scoreType=cv2.ORB_FAST_SCORE
)
# removed because of license issues:
# cv2.xfeatures2d.SIFT_create()
f, d = self.detector.detectAndCompute(self.base8bit, None)
self.base_features, self.base_descs = f, d # .astype(np.float32)
def __init__(self, templates, ratio=0.75):
self.templates = templates
self.ratio = ratio
flann_params = dict(algorithm=FLANN_INDEX_KDTREE, trees=5)
self.matcher = cv2.FlannBasedMatcher(flann_params, {})
self.pool = ThreadPool(processes=cv2.getNumberOfCPUs())
def __setstate__(self, state):
self.templates = state['templates']
self.ratio = state['ratio']
flann_params = dict(algorithm=FLANN_INDEX_KDTREE, trees=5)
self.matcher = cv2.FlannBasedMatcher(flann_params, {})
self.pool = ThreadPool(processes=1) # cv2.getNumberOfCPUs())
def homography(img1, img2, visualize=False):
"""
Finds Homography matrix from Image1 to Image2.
Two images should be a plane and can change in viewpoint
:param img1: Source image
:param img2: Target image
:param visualize: Flag to visualize the matched pixels and Homography warping
:return: Homography matrix. (or) Homography matrix, Visualization image - if visualize is True
"""
sift = cv.xfeatures2d.SIFT_create()
kp1, desc1 = sift.detectAndCompute(img1, None)
kp2, desc2 = sift.detectAndCompute(img2, None)
index_params = dict(algorithm=FLANN_INDEX_KDTREE, trees=INDEX_PARAM_TREES)
# number of times the trees in the index should be recursively traversed
# Higher values gives better precision, but also takes more time
sch_params = dict(checks=SCH_PARAM_CHECKS)
flann = cv.FlannBasedMatcher(index_params, sch_params)
matches = flann.knnMatch(desc1, desc2, k=2)
logging.debug('{} matches found'.format(len(matches)))
# select good matches
matches_arr = []
good_matches = []
for m, n in matches:
if m.distance < GOOD_MATCH_THRESHOLD * n.distance:
good_matches.append(m)
matches_arr.append(m)
if len(good_matches) < MIN_MATCH_COUNT:
raise (Exception('Not enough matches found'))
else:
logging.debug('{} of {} are good matches'.format(len(good_matches), len(matches)))
src_pts = [kp1[m.queryIdx].pt for m in good_matches]
src_pts = np.array(src_pts, dtype=np.float32).reshape((-1, 1, 2))
dst_pts = [kp2[m.trainIdx].pt for m in good_matches]
dst_pts = np.array(dst_pts, dtype=np.float32).reshape((-1, 1, 2))
homo, mask = cv.findHomography(src_pts, dst_pts, cv.RANSAC, 5)
if visualize:
res = visualize_homo(img1, img2, kp1, kp2, matches, homo, mask)
return homo, res
return homo
def getMatches(self, sceneImage):
"""
sceneImage: ?????array??
return dst: ????????
"""
# Initiate SIFT detector
sift = cv2.xfeatures2d.SIFT_create()
# find the keypoints and descriptors with SIFT
kp1, des1 = sift.detectAndCompute(self.MarkImage[:,:,0],None)
kp2, des2 = sift.detectAndCompute(sceneImage[:,:,0],None)
# create BFMatcher object
FLANN_INDEX_KDTREE = 0
index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5)
search_params = dict(checks = 50)
flann = cv2.FlannBasedMatcher(index_params, search_params)
# Match descriptors.
matches = flann.knnMatch(des1,des2,k=2)
# Sort them in the order of their distance.
good = []
for m,n in matches:
if m.distance < 0.7*n.distance:
good.append(m)
if len(good) < self.MIN_MATCH_COUNT:
return None
src_pts = np.float32([ kp1[m.queryIdx].pt for m in good ]).reshape(-1,1,2)
dst_pts = np.float32([ kp2[m.trainIdx].pt for m in good ]).reshape(-1,1,2)
M, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC,5.0)
matchesMask = mask.ravel().tolist()
h,w = self.MarkImage.shape[:2]
pts = np.float32([ [0,0],[0,h-1],[w-1,h-1],[w-1,0] ]).reshape(-1,1,2)
dst = cv2.perspectiveTransform(pts,M)
draw_params = dict(matchColor = (0,255,0), # draw matches in green color
singlePointColor = None,
matchesMask = matchesMask, # draw only inliers
flags = 2)
self.SceneImage = sceneImage
self.DrawParams = draw_params
self.KP1 = kp1
self.KP2 = kp2
self.GoodMatches = good
return dst
def getMatches(self, sceneImage):
"""
sceneImage: ?????array??
return dst: ????????
"""
# Initiate SIFT detector
sift = cv2.xfeatures2d.SIFT_create()
# find the keypoints and descriptors with SIFT
kp1, des1 = sift.detectAndCompute(self.MarkImage[:,:,0],None)
kp2, des2 = sift.detectAndCompute(sceneImage[:,:,0],None)
# create BFMatcher object
FLANN_INDEX_KDTREE = 0
index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5)
search_params = dict(checks = 50)
flann = cv2.FlannBasedMatcher(index_params, search_params)
# Match descriptors.
matches = flann.knnMatch(des1,des2,k=2)
# Sort them in the order of their distance.
good = []
for m,n in matches:
if m.distance < 0.7*n.distance:
good.append(m)
if len(good) < self.MIN_MATCH_COUNT:
return None
src_pts = np.float32([ kp1[m.queryIdx].pt for m in good ]).reshape(-1,1,2)
dst_pts = np.float32([ kp2[m.trainIdx].pt for m in good ]).reshape(-1,1,2)
M, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC,5.0)
matchesMask = mask.ravel().tolist()
h,w = self.MarkImage.shape[:2]
pts = np.float32([ [0,0],[0,h-1],[w-1,h-1],[w-1,0] ]).reshape(-1,1,2)
dst = cv2.perspectiveTransform(pts,M)
draw_params = dict(matchColor = (0,255,0), # draw matches in green color
singlePointColor = None,
matchesMask = matchesMask, # draw only inliers
flags = 2)
self.SceneImage = sceneImage
self.DrawParams = draw_params
self.KP1 = kp1
self.KP2 = kp2
self.GoodMatches = good
return dst
def find_image_position(origin='origin.png', query='query.png', outfile=None):
'''
find all image positions
@return None if not found else a tuple: (origin.shape, query.shape, postions)
might raise Exception
'''
img1 = cv2.imread(query, 0) # query image(small)
img2 = cv2.imread(origin, 0) # train image(big)
# Initiate SIFT detector
sift = cv2.SIFT()
# find the keypoints and descriptors with SIFT
kp1, des1 = sift.detectAndCompute(img1,None)
kp2, des2 = sift.detectAndCompute(img2,None)
print len(kp1), len(kp2)
FLANN_INDEX_KDTREE = 0
index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5)
search_params = dict(checks = 50)
# flann
flann = cv2.FlannBasedMatcher(index_params, search_params)
matches = flann.knnMatch(des1, des2, k=2)
# store all the good matches as per Lowe's ratio test.
good = []
for m,n in matches:
if m.distance < 0.7*n.distance:
good.append(m)
print len(kp1), len(kp2), 'good cnt:', len(good)
if len(good)*1.0/len(kp1) < 0.5:
#if len(good)<MIN_MATCH_COUNT:
print "Not enough matches are found - %d/%d" % (len(good),MIN_MATCH_COUNT)
return img2.shape, img1.shape, []
queryPts = []
trainPts = []
for dm in good:
queryPts.append(kp1[dm.queryIdx])
trainPts.append(kp2[dm.trainIdx])
img3 = cv2.drawKeypoints(img1, queryPts)
cv2.imwrite('image/query.png', img3)
img3 = cv2.drawKeypoints(img2, trainPts)
point = _middlePoint(trainPts)
print 'position in', point
if outfile:
edge = 10
top_left = (point[0]-edge, point[1]-edge)
bottom_right = (point[0]+edge, point[1]+edge)
cv2.rectangle(img3, top_left, bottom_right, 255, 2)
cv2.imwrite(outfile, img3)
return img2.shape, img1.shape, [point]
def find_image_position(origin='origin.png', query='query.png', outfile=None):
'''
find all image positions
@return None if not found else a tuple: (origin.shape, query.shape, postions)
might raise Exception
'''
img1 = cv2.imread(query, 0) # query image(small)
img2 = cv2.imread(origin, 0) # train image(big)
# Initiate SIFT detector
sift = cv2.SIFT()
# find the keypoints and descriptors with SIFT
kp1, des1 = sift.detectAndCompute(img1,None)
kp2, des2 = sift.detectAndCompute(img2,None)
print len(kp1), len(kp2)
FLANN_INDEX_KDTREE = 0
index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5)
search_params = dict(checks = 50)
# flann
flann = cv2.FlannBasedMatcher(index_params, search_params)
matches = flann.knnMatch(des1, des2, k=2)
# store all the good matches as per Lowe's ratio test.
good = []
for m,n in matches:
if m.distance < 0.7*n.distance:
good.append(m)
print len(kp1), len(kp2), 'good cnt:', len(good)
if len(good)*1.0/len(kp1) < 0.5:
#if len(good)<MIN_MATCH_COUNT:
print "Not enough matches are found - %d/%d" % (len(good),MIN_MATCH_COUNT)
return img2.shape, img1.shape, []
queryPts = []
trainPts = []
for dm in good:
queryPts.append(kp1[dm.queryIdx])
trainPts.append(kp2[dm.trainIdx])
img3 = cv2.drawKeypoints(img1, queryPts)
cv2.imwrite('image/query.png', img3)
img3 = cv2.drawKeypoints(img2, trainPts)
point = _middlePoint(trainPts)
print 'position in', point
if outfile:
edge = 10
top_left = (point[0]-edge, point[1]-edge)
bottom_right = (point[0]+edge, point[1]+edge)
cv2.rectangle(img3, top_left, bottom_right, 255, 2)
cv2.imwrite(outfile, img3)
return img2.shape, img1.shape, [point]
def match_outlines(self, orig_image, skewed_image):
orig_image = np.array(orig_image)
skewed_image = np.array(skewed_image)
try:
surf = cv2.xfeatures2d.SURF_create(400)
except Exception:
surf = cv2.SIFT(400)
kp1, des1 = surf.detectAndCompute(orig_image, None)
kp2, des2 = surf.detectAndCompute(skewed_image, None)
FLANN_INDEX_KDTREE = 0
index_params = dict(algorithm=FLANN_INDEX_KDTREE, trees=5)
search_params = dict(checks=50)
flann = cv2.FlannBasedMatcher(index_params, search_params)
matches = flann.knnMatch(des1, des2, k=2)
# store all the good matches as per Lowe's ratio test.
good = []
for m, n in matches:
if m.distance < 0.7 * n.distance:
good.append(m)
MIN_MATCH_COUNT = 10
if len(good) > MIN_MATCH_COUNT:
src_pts = np.float32([kp1[m.queryIdx].pt for m in good
]).reshape(-1, 1, 2)
dst_pts = np.float32([kp2[m.trainIdx].pt for m in good
]).reshape(-1, 1, 2)
M, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 5.0)
# see https://ch.mathworks.com/help/images/examples/find-image-rotation-and-scale-using-automated-feature-matching.html for details
ss = M[0, 1]
sc = M[0, 0]
scaleRecovered = math.sqrt(ss * ss + sc * sc)
thetaRecovered = math.atan2(ss, sc) * 180 / math.pi
self.log.info("MAP: Calculated scale difference: %.2f, "
"Calculated rotation difference: %.2f" %
(scaleRecovered, thetaRecovered))
#deskew image
im_out = cv2.warpPerspective(skewed_image, np.linalg.inv(M),
(orig_image.shape[1], orig_image.shape[0]))
return im_out
else:
self.log.warn("MAP: Not enough matches are found - %d/%d"
% (len(good), MIN_MATCH_COUNT))
return skewed_image