def sift_train(self, images, n_clusters=120, n_jobs=-1): """ 利用SIFT,训练特征提取器(训练KMeans) 只利用SIFT得到描述子是不够的,因为每幅图片的描述子维度太高而且数量不一 致,所以利用词袋模型将这些描述子聚类得到直方图。该方法就是训练聚类器, 以便能从描述子得到最终的直方图。 Parameters ---------- images : 列表 要用来训练的图片的集合。列表中的每个图片都是二维的numpy数组(灰度 图)。 c_clusters : int 描述子聚类的类数,即特征向量的维度。 n_jobs : int 训练时用到的CPU核心数,如果是-1则使用全部核心。 """ sift = SIFT_create() descs = np.array([sift.detectAndCompute(img, None)[1] for img in images]) # Sometimes descriptor is None, turn it into np.ndarray type. descs = [d if isinstance(d, np.ndarray) else np.array([]).reshape(0, 128).astype('float32') for d in descs] # 训练好的聚类器放入self.red self.red = KMeans(n_clusters=n_clusters, n_jobs=n_jobs, random_state=42).fit(np.vstack(descs))
def sift_train(self, images, n_clusters=120, n_jobs=-1): """ 利用SIFT,训练特征提取器(训练KMeans) 只利用SIFT得到描述子是不够的,因为每幅图片的描述子维度太高而且数量不一 致,所以利用词袋模型将这些描述子聚类得到直方图。该方法就是训练聚类器, 以便能从描述子得到最终的直方图。 Parameters ---------- images : 列表 要用来训练的图片的集合。列表中的每个图片都是二维的numpy数组(灰度 图)。 c_clusters : int 描述子聚类的类数,即特征向量的维度。 n_jobs : int 训练时用到的CPU核心数,如果是-1则使用全部核心。 """ sift = SIFT_create() descs = np.array( [sift.detectAndCompute(img, None)[1] for img in images]) # Sometimes descriptor is None, turn it into np.ndarray type. descs = [ d if isinstance(d, np.ndarray) else np.array([]).reshape( 0, 128).astype('float32') for d in descs ] # 训练好的聚类器放入self.red self.red = KMeans(n_clusters=n_clusters, n_jobs=n_jobs, random_state=42).fit(np.vstack(descs))
def image2descriptors(imlist, descriptor='ORB'): """ For each image in the imlist list extract the given descriptor (ORB and SIFT supported) Return the lists : [keypoint], [descriptor] """ from cv2 import imread desc = [] key = [] if(descriptor=='ORB'): from cv2 import ORB_create for imname in imlist: im = imread(imname) k, d = ORB_create().detectAndCompute(im, None) desc.append(d) key.append(k) if(descriptor=='BRISK'): from cv2 import BRISK_create for imname in imlist: im = imread(imname) k, d = BRISK_create().detectAndCompute(im, None) desc.append(d) key.append(k) elif(descriptor=="SIFT"): from cv2.xfeatures2d import SIFT_create for imname in imlist: im = imread(imname) k, d = SIFT_create().detectAndCompute(im, None) desc.append(d) key.append(k) else: print 'Desc is not equal to ORB or to SIFT' print 'bordel' return key, desc
def __init__(self, action_space, feature_type=None, filter_features=None, max_time_steps=100, distance_threshold=4.0, **kwargs): """ filter_features indicates whether to filter out key points that are not on the object in the current image. Key points in the target image are always filtered out. """ SimpleQuadPanda3dEnv.__init__(self, action_space, **kwargs) ServoingEnv.__init__(self, env=self, max_time_steps=max_time_steps, distance_threshold=distance_threshold) lens = self.camera_node.node().getLens() self._observation_space.spaces['points'] = BoxSpace( np.array([-np.inf, lens.getNear(), -np.inf]), np.array([np.inf, lens.getFar(), np.inf])) film_size = tuple(int(s) for s in lens.getFilmSize()) self.mask_camera_sensor = Panda3dMaskCameraSensor( self.app, (self.skybox_node, self.city_node), size=film_size, near_far=(lens.getNear(), lens.getFar()), hfov=lens.getFov()) for cam in self.mask_camera_sensor.cam: cam.reparentTo(self.camera_sensor.cam) self.filter_features = True if filter_features is None else False self._feature_type = feature_type or 'sift' if cv2.__version__.split('.')[0] == '3': from cv2.xfeatures2d import SIFT_create, SURF_create from cv2 import ORB_create if self.feature_type == 'orb': # https://github.com/opencv/opencv/issues/6081 cv2.ocl.setUseOpenCL(False) else: SIFT_create = cv2.SIFT SURF_create = cv2.SURF ORB_create = cv2.ORB if self.feature_type == 'sift': self._feature_extractor = SIFT_create() elif self.feature_type == 'surf': self._feature_extractor = SURF_create() elif self.feature_type == 'orb': self._feature_extractor = ORB_create() else: raise ValueError("Unknown feature extractor %s" % self.feature_type) if self.feature_type == 'orb': self._matcher = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True) else: self._matcher = cv2.BFMatcher(cv2.NORM_L2, crossCheck=True) self._target_key_points = None self._target_descriptors = None
def main(): # Parse command line and configure logging level opts = docopt.docopt(__doc__) logging.basicConfig(level=logging.WARN if opts['--quiet'] else logging.INFO) feat_detector = SIFT_create() # Determine which save function to use. save_fn, out_format = save_npz, 'npz' if opts['--lowe']: save_fn, out_format = save_lowe, 'key' im_glob = os.path.join(opts['<imgdir>'], opts['--imglob']) for im_pn in glob.glob(im_glob): logging.info('Processing %s...', im_pn) # Construct the mask and features path im_bn, im_ext = os.path.splitext(os.path.basename(im_pn)) mask_pn = os.path.join(opts['<maskdir>'], opts['--maskformat'].format( basename=im_bn, ext=im_ext )) out_pn = os.path.join(opts['<outdir>'], opts['--outformat'].format( basename=im_bn, ext=im_ext, format=out_format )) # Compute hashes of image and mask im_hash = sha256_file(im_pn) mask_hash = sha256_file(mask_pn) # Load the image and mask from disk im = np.asarray(Image.open(im_pn).convert('L')) mask = np.asarray(Image.open(mask_pn).convert('L')) # Detect keypoints and features kps, descs = feat_detector.detectAndCompute(im, mask) metadata = { 'image_path': os.path.abspath(im_pn), 'mask_path': os.path.abspath(mask_pn), 'image_sha256': im_hash, 'mask_sha256': mask_hash, } # Save output save_fn(out_pn, kps, descs, metadata)
def find_features_in_array_SIFT(self, sub_image, main_image, debug=False): # Initiate SIFT detector sift = SIFT_create() # find the keypoints and descriptors with SIFT kp1, des1 = sift.detectAndCompute(sub_image, None) kp2, des2 = sift.detectAndCompute(main_image, None) # BFMatcher with default params bf = cv2.BFMatcher() matches = bf.knnMatch(des1, des2, k=2) logging.debug("Found {} possible matches".format(len(matches))) ret_list = [] good = [] for m, n in matches: if m.distance < 0.75 * n.distance: good.append([m]) good.sort(key=lambda x: x[0].distance) if debug: # cv2.drawMatchesKnn expects list of lists as matches. img3 = cv2.drawMatchesKnn(sub_image, kp1, main_image, kp2, good, flags=2, outImg=None, matchColor=(255, 255, 0)) plt.imshow(img3), plt.show() ret_list = [] for match in good: index = match[0].trainIdx point = kp2[index].pt ret_list.append((int(point[0]), int(point[1]))) logging.debug("After filtering {}".format(len(good))) return ret_list
class SIFTDetector(Detector): def __init__(self): Detector.__init__(self) self.SIFT = SIFT_create() def __repr__(self): return "SIFTDetector(SIFT={SIFT}".format(SIFT=self.SIFT) def detect(self, image): keypoints, descriptors = self.SIFT.detectAndCompute(image.cv_image, None) return keypoints, descriptors
def sift_extract(self, image): """ 利用SIFT,对给定的图片提取特征向量。使用前必须先初始化特征提取器。 Parameters ---- image : 二维numpy数组 灰度图。 Returns ------- 一维numpy数组 图片的特征向量。 """ assert self.red, "self.red should be initial!" n_clusters = self.red.n_clusters # 聚类的数量 features = np.zeros(n_clusters) # 提取到的特征 sift = SIFT_create() descriptors = sift.detectAndCompute(image, None)[1] if descriptors is None: # 如果没有找到一个描述子,就返回全是0的数组 return features y = self.red.predict(descriptors) # 对描述子聚类 features[list(set(y))] = 1 # 得到最终的特征 return features
def getKpAndDescriptors(self, img, detector="sift"): if detector.lower() == "harris": thr = 0.01 size = 2 dst = cv2.cornerHarris(cv2.cvtColor(img, cv2.COLOR_BGR2GRAY), 2, 3, 0.04) dst = cv2.dilate(dst, None) kp = np.argwhere(dst > thr * dst.max()) key_points = [cv2.KeyPoint(k[0], k[1], 2) for k in kp] sift_creator = SIFT_create() __, descriptors = sift_creator.compute(cv2.cvtColor(img, cv2.COLOR_BGR2GRAY), key_points) return descriptors[:100] elif detector.lower() == "sift": sift_creator = SIFT_create() kp, descriptors = sift_creator.detectAndCompute(cv2.cvtColor(img, cv2.COLOR_BGR2GRAY), None) return descriptors[:100]
sift_2 = get_sift_descriptor(rotate_image_2, rotate_interest_points_2) # Get the matched pairs of points matched_pairs = create_matched_pairs(sift_1, sift_2, 0.5) # Plot the matched pairs of feature points large_image = match_image_points(rotate_image_1, rotate_image_2, rotate_interest_points_1, rotate_interest_points_2, matched_pairs) plot_image(large_image, 'Matched Interest Points') # Read left and right image for panoramic stitching im_left = imread('.\sample image\DT_left.jpg') im_right = imread('.\sample image\DT_right.jpg') # Create the SIFT feature point detector object sift = SIFT_create() # Identify the keypoints and SIFT descriptors skp_left = sift.detect(im_left) skp_right = sift.detect(im_right) skp_left, sd_left = sift.compute(im_left, skp_left) skp_right, sd_right = sift.compute(im_right, skp_right) # Plot the keypoints on the image keypoints_left = draw_keypoints(im_left, skp_left) plot_image(keypoints_left, 'Keypoints on Left Image') keypoints_right = draw_keypoints(im_right, skp_right) plot_image(keypoints_right, 'Keypoints on Right Image') # Adjust the descriptors to be of equal sizes if sd_left.size < sd_right.size:
def __init__(self): Detector.__init__(self) self.SIFT = SIFT_create()
def spoj(leva, desna, sleva=False, nove=None, orig=None): # Ukoliko nisu prosledjene tacke, moraju se naci if nove is None or orig is None \ or not nove or not orig \ or len(nove) != len(orig) \ or len(nove) < 4: # Log poruka o akciji if LOGUJ: print() print('Traže se korespondencije.') # Upotreba SIFT (scale-invariant feature transform) # algoritma za pronalazak zanimljivih tacaka na slikama sift = SIFT_create() kpl, desl = sift.detectAndCompute(leva, None) kpd, desd = sift.detectAndCompute(desna, None) # Uparivanje dobijenih deskriptora # brute-force metodom najblizih suseda parovi = BFMatcher().knnMatch(desd, desl, k=2) # Filtriranje parova izuzimanjem onih previse # dalekih; ovo nije neophodno, ali olaksava # posao RANSAC-u i znatno ga ubrzava bliski = [m for m, n in parovi if m.distance < 0.5 * n.distance] # Neophodna su barem cetiri para za # potrebe odredjivanja projekcije if len(bliski) < 4: raise ValueError # Izdvajanje originala (sa desne slike) # i slika (sa leve slike) za projekciju orig = np.float32([kpd[m.queryIdx].pt for m in bliski]).reshape(-1, 2) nove = np.float32([kpl[m.trainIdx].pt for m in bliski]).reshape(-1, 2) # Log poruka o akciji if LOGUJ: print('Uspešno odabrane korespondencije.') elif LOGUJ: print() # Log poruka o akciji if LOGUJ: print('Određuje se transformacija.') # Izracunavanje matrice projekcije M = RANSAC(nove, orig) if sleva: M = LA.inv(M) # Log poruka o akciji if LOGUJ: print('Uspešno određena transformacija.') # Dimenzije ulaznih slika dim1 = leva.shape[1], leva.shape[0] dim2 = desna.shape[1], desna.shape[0] if sleva: dim1, dim2 = dim2, dim1 # Pronalazak tacaka van slike cosk = np.array([[0, 0, 1], [dim2[0] - 1, 0, 1], [0, dim2[1] - 1, 1], [dim2[0] - 1, dim2[1] - 1, 1]]) cosk = np.array([*map(lambda x: M @ x, cosk)]) cosk = np.array([*map(lambda x: [x[0] / x[2], x[1] / x[2], 1], cosk)]) mini = cosk[:, 0].min(), cosk[:, 1].min() mini = [*map(lambda x: abs(ceil(min(x, 0))), mini)] # Nova matrica, sa dodatkom translacije koja # dosad nevidljive elemente smesta na sliku M = np.array([[1, 0, mini[0]], [0, 1, mini[1]], [0, 0, 1]]) @ M # Dimenzije slike koja nije fiksirana cosk = np.array( [*map(lambda x: [x[0] + mini[0], x[1] + mini[1], 1], cosk)]) dim = (ceil(max(cosk[:, 0].max() + 1, dim1[0] + mini[0])), ceil(max(cosk[:, 1].max() + 1, dim1[1] + mini[1]))) # Obuhvatajuci pravougaonik (bounding box) # slike koja nije fiksna zarad ustede vremena; # ukoliko su dimenzije nove slike dosta vece # od polazne, nema potrebe gledati crne piksele minx = int(ceil(cosk[:, 0].min())) maxx = int(ceil(cosk[:, 0].max())) + 1 miny = int(ceil(cosk[:, 1].min())) maxy = int(ceil(cosk[:, 1].max())) + 1 gran = (miny, minx), (maxy, maxx) # Cuvanje fiksirane i slike koju treba # transformisati pod informativnijim imenima fiksna = leva transf = desna if sleva: fiksna, transf = transf, fiksna # Log poruka o akciji if LOGUJ: print(f'Transformiše se {"leva" if sleva else "desna"} slika.') # Transformacija slike koja nije fiksirana transf = projektuj(transf, M, dim, gran) # Log poruka o akciji if LOGUJ: print('Uspešno izvršena transformacija.') # Log poruka o akciji if LOGUJ: print('Spajaju se slike.') # Uzduzne granice preklapanja if sleva: lgran = mini[0] dgran = maxx else: lgran = minx dgran = dim1[0] + mini[0] # Postavljanje fiksne slike na mesto; # prvo obrada delova pre i posle granice if sleva: transf[mini[1]:dim1[1]+mini[1], dgran :dim1[0]+mini[0]] = \ [[fiksna[i-mini[1],j-mini[0]] for j in range( dgran , dim1[0]+mini[0])] for i in range(mini[1], dim1[1]+mini[1])] else: transf[mini[1]:dim1[1]+mini[1], mini[0]: lgran ] = \ [[fiksna[i-mini[1],j-mini[0]] for j in range(mini[0], lgran )] for i in range(mini[1], dim1[1]+mini[1])] # Funkcija za filtriranje crnih piskela crn = lambda p: all(map(lambda x: x == 0, p)) # Funkcija za interpolaciju piksela duzina = dgran - lgran + 1 if sleva: pros = lambda y, x, j: (dgran - j) / duzina * x + (j - lgran + 1 ) / duzina * y else: pros = lambda x, y, j: (dgran - j) / duzina * x + (j - lgran + 1 ) / duzina * y # Tezinsko uprosecavanje (interpolacija) # necrnih piksela unutar granicnog pojasa transf[mini[1]:dim1[1] + mini[1], lgran:dgran] = [[ transf[i, j] if crn(fiksna[i - mini[1], j - mini[0]]) else fiksna[i - mini[1], j - mini[0]] if crn(transf[i, j]) else pros(fiksna[i - mini[1], j - mini[0]], transf[i, j], j) for j in range(lgran, dgran) ] for i in range(mini[1], dim1[1] + mini[1])] # Log poruka o akciji if LOGUJ: print('Uspešno spojene slike.') # Isecanje praznih ivica return iseci(transf)