import
numpy as np
import
cv2 as cv
import
imutils
class
Stitcher:
def
__init__(
self
):
self
.isv3
=
imutils.is_cv3()
def
stitch(
self
,imgs, ratio
=
0.75
, reprojThresh
=
4.0
, showMatches
=
False
):
print
(
'A'
)
(img2, img1)
=
imgs
(kp1, des1)
=
self
.detectAndDescribe(img1)
(kp2, des2)
=
self
.detectAndDescribe(img2)
print
(
len
(kp1),
len
(des1))
print
(
len
(kp2),
len
(des2))
R
=
self
.matchKeyPoints(kp1, kp2, des1, des2, ratio, reprojThresh)
if
R
is
None
:
return
None
(good, M, mask)
=
R
print
(M)
result
=
cv.warpPerspective(img1, M, (img1.shape[
1
]
+
img2.shape[
1
], img1.shape[
0
]))
result[
0
:img2.shape[
0
],
0
:img2.shape[
1
]]
=
img2
if
showMatches:
vis
=
self
.drawMatches1(img1, img2, kp1, kp2, good, mask)
return
(result, vis)
return
result
def
detectAndDescribe(
self
,img):
print
(
'B'
)
gray
=
cv.cvtColor(img, cv.COLOR_BGR2GRAY)
if
self
.isv3:
sift
=
cv.xfeatures2d.SIFT_create()
(kps, des)
=
sift.detectAndCompute(img,
None
)
else
:
sift
=
cv.FastFeatureDetector_create(
'SIFT'
)
kps
=
sift.detect(gray)
des
=
sift.compute(gray, kps)
kps
=
np.float32([kp.pt
for
kp
in
kps])
return
(kps, des)
def
matchKeyPoints(
self
,kp1, kp2, des1, des2, ratio, reprojThresh):
print
(
'C'
)
matcher
=
cv.DescriptorMatcher_create(
'BruteForce'
)
matches
=
matcher.knnMatch(des1, des2,
2
)
good
=
[]
for
m
in
matches:
if
len
(m)
=
=
2
and
m[
0
].distance < ratio
*
m[
1
].distance:
good.append((m[
0
].trainIdx, m[
0
].queryIdx))
print
(
len
(good))
if
len
(good) >
4
:
src_pts
=
np.float32([kp1[i]
for
(_, i)
in
good])
dst_pts
=
np.float32([kp2[i]
for
(i, _)
in
good])
(M, mask)
=
cv.findHomography(src_pts, dst_pts, cv.RANSAC, reprojThresh)
return
(good, M, mask)
return
None
def
drawMatches(img1, img2, kp1, kp2, matches, mask, M):
h, w
=
img1.shape[:
2
]
pts
=
np.float32([[
0
,
0
], [
0
, h
-
1
], [w
-
1
, h
-
1
], [w
-
1
,
0
]]).reshape(
-
1
,
1
,
2
)
dst
=
cv.perspectiveTransform(pts, M)
matchesMask
=
mask.ravel().tolist()
draw_params
=
dict
(matchColor
=
(
0
,
255
,
0
),
singlePointColor
=
None
,
matchesMask
=
matchesMask,
flags
=
2
)
img
=
cv.drawMatches(img1, kp1, img2, kp2, matches,
None
,
*
*
draw_params)
return
img
def
drawMatches1(
self
,img1, img2, kp1, kp2, metches,mask):
print
(
'D'
)
(hA,wA)
=
img1.shape[:
2
]
(hB,wB)
=
img2.shape[:
2
]
vis
=
np.zeros((
max
(hA,hB), wA
+
wB,
3
), dtype
=
'uint8'
)
vis[
0
:hA,
0
:wA]
=
img1
vis[
0
:hB, wA:]
=
img2
for
((trainIdx, queryIdx),s)
in
zip
(metches, mask):
if
s
=
=
1
:
ptA
=
(
int
(kp1[queryIdx][
0
]),
int
(kp1[queryIdx][
1
]))
ptB
=
(
int
(kp2[trainIdx][
0
])
+
wA,
int
(kp2[trainIdx][
1
]))
cv.line(vis, ptA, ptB, (
0
,
255
,
0
),
1
)
return
vis