diff --git a/imutils/__init__.py b/imutils/__init__.py old mode 100644 new mode 100755 index 1cc0f8b..ef35c9b --- a/imutils/__init__.py +++ b/imutils/__init__.py @@ -2,7 +2,7 @@ # website: http://www.pyimagesearch.com # set the version number -__version__ = "0.4.3" +__version__ = "0.4.4" # import the necessary packages from .convenience import translate diff --git a/imutils/feature/__init__.py b/imutils/feature/__init__.py old mode 100644 new mode 100755 index d1856b1..b1d015b --- a/imutils/feature/__init__.py +++ b/imutils/feature/__init__.py @@ -1,4 +1,8 @@ from .helpers import corners_to_keypoints from .factories import FeatureDetector_create from .factories import DescriptorExtractor_create -from .gftt import GFTT \ No newline at end of file +from .factories import DescriptorMatcher_create +from .dense import DENSE +from .gftt import GFTT +from .harris import HARRIS +from .rootsift import RootSIFT diff --git a/imutils/feature/dense.py b/imutils/feature/dense.py new file mode 100755 index 0000000..1fbcf15 --- /dev/null +++ b/imutils/feature/dense.py @@ -0,0 +1,24 @@ +import cv2 + +class DENSE: + def __init__(self, step=6, radius=.5): + self.step = step + self.radius = radius + + def detect(self, img): + # initialize our list of keypoints + kps = [] + + # loop over the height and with of the image, taking a `step` + # in each direction + for x in range(0, img.shape[1], self.step): + for y in range(0, img.shape[0], self.step): + # create a keypoint and add it to the keypoints list + kps.append(cv2.KeyPoint(x, y, self.radius)) + + # return the dense keypoints + return kps + + def setInt(self, var, val): + if var == "initXyStep": + self.step = val diff --git a/imutils/feature/factories.py b/imutils/feature/factories.py old mode 100644 new mode 100755 index 63cf266..4b16d20 --- a/imutils/feature/factories.py +++ b/imutils/feature/factories.py @@ -1,29 +1,46 @@ #from .descriptors.rootsift import RootSIFT from ..convenience import is_cv2 import cv2 +from .dense import DENSE +from .gftt import GFTT +from .harris import HARRIS +from .rootsift import RootSIFT if is_cv2(): FeatureDetector_create = cv2.FeatureDetector_create DescriptorExtractor_create = cv2.DescriptorExtractor_create + DescriptorMatcher_create = cv2.DescriptorMatcher_create + else: try: - _DETECTOR_FACTORY = {"SIFT": cv2.xfeatures2d.SIFT_create, - "SURF": cv2.xfeatures2d.SURF_create, - "STAR": cv2.xfeatures2d.StarDetector_create, - "MSER": cv2.MSER_create, + _DETECTOR_FACTORY = {"BRISK": cv2.BRISK_create, + "DENSE": DENSE, "FAST": cv2.FastFeatureDetector_create, - "BRISK": cv2.BRISK_create, - "ORB": cv2.ORB_create + "GFTT": GFTT, + "HARRIS": HARRIS, + "MSER": cv2.MSER_create, + "ORB": cv2.ORB_create, + "SIFT": cv2.xfeatures2d.SIFT_create, + "SURF": cv2.xfeatures2d.SURF_create, + "STAR": cv2.xfeatures2d.StarDetector_create } _EXTRACTOR_FACTORY = {"SIFT": cv2.xfeatures2d.SIFT_create, - #"ROOTSIFT": RootSIFT, + "ROOTSIFT": RootSIFT, "SURF": cv2.xfeatures2d.SURF_create, "BRIEF": cv2.xfeatures2d.BriefDescriptorExtractor_create, "ORB": cv2.ORB_create, "BRISK": cv2.BRISK_create, "FREAK": cv2.xfeatures2d.FREAK_create } + + _MATCHER_FACTORY = {"BruteForce": cv2.DESCRIPTOR_MATCHER_BRUTEFORCE, + "BruteForce-SL2": cv2.DESCRIPTOR_MATCHER_BRUTEFORCE_SL2, + "BruteForce-L1": cv2.DESCRIPTOR_MATCHER_BRUTEFORCE_L1, + "BruteForce-Hamming": cv2.DESCRIPTOR_MATCHER_BRUTEFORCE_HAMMING, + "FlannBased": cv2.DESCRIPTOR_MATCHER_FLANNBASED + } + except AttributeError: _DETECTOR_FACTORY = {"MSER": cv2.MSER_create, "FAST": cv2.FastFeatureDetector_create, @@ -74,3 +91,16 @@ def DescriptorExtractor_create(extractor, *args, **kw_args): raise AttributeError("{} not a supported extractor".format(extractor)) return extr(*args, **kw_args) + + def DescriptorMatcher_create(matcher): + """ + + :param matcher: string of the type of descriptor matcher to return + :return: the matcher int + """ + try: + extr = _MATCHER_FACTORY[matcher] + except KeyError: + raise AttributeError("{} not a supported matcher".format(matcher)) + + return cv2.DescriptorMatcher_create(extr) diff --git a/imutils/feature/gftt.py b/imutils/feature/gftt.py old mode 100644 new mode 100755 diff --git a/imutils/feature/harris.py b/imutils/feature/harris.py new file mode 100755 index 0000000..66ee55b --- /dev/null +++ b/imutils/feature/harris.py @@ -0,0 +1,26 @@ +import cv2 +import numpy as np +from .helpers import corners_to_keypoints + + +class HARRIS: + def __init__(self, blockSize=2, apertureSize=3, k=0.1, T=0.02): + self.blockSize = blockSize + self.apertureSize = apertureSize + self.k = k + self.T = T + + def detect(self, img): + # convert our input image to a floating point data type and then + # compute the Harris corner matrix + gray = np.float32(img) + H = cv2.cornerHarris(gray, self.blockSize, self.apertureSize, self.k) + + # for every (x, y)-coordinate where the Harris value is above the + # threshold, create a keypoint (the Harris detector returns + # keypoint size a 3-pixel radius) + kps = np.argwhere(H > self.T * H.max()) + kps = [cv2.KeyPoint(pt[1], pt[0], 3) for pt in kps] + + # return the Harris keypoints + return kps diff --git a/imutils/feature/helpers.py b/imutils/feature/helpers.py old mode 100644 new mode 100755 diff --git a/imutils/feature/rootsift.py b/imutils/feature/rootsift.py new file mode 100644 index 0000000..4bb3742 --- /dev/null +++ b/imutils/feature/rootsift.py @@ -0,0 +1,31 @@ +# import the necessary packages +import numpy as np +import cv2 +from ..convenience import is_cv2 +from . import factories + +class RootSIFT: + def __init__(self): + # initialize the SIFT feature extractor + self.extractor = factories.DescriptorExtractor_create("SIFT") + + def compute(self, image, kps, eps=1e-7): + # compute SIFT descriptors for OpenCV 2.4 + if is_cv2: + (kps, descs) = self.extractor.compute(image, kps) + + # otherwise, computer SIFT descriptors for OpenCV 3+ + else: + (kps, descs) = self.extractor.detectAndCompute(image, None) + + # if there are no keypoints or descriptors, return an empty tuple + if len(kps) == 0: + return ([], None) + + # apply the Hellinger kernel by first L1-normalizing and taking the + # square-root + descs /= (descs.sum(axis=1, keepdims=True) + eps) + descs = np.sqrt(descs) + + # return a tuple of the keypoints and descriptors + return (kps, descs) \ No newline at end of file