<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      sift算法使用

      實(shí)際項(xiàng)目中一般都直接使用封裝好的sift算法。以前為了用sift,都是用的舊版本:opencv-contib-python=3.4.2.17,現(xiàn)在sift專利過期了,新版的opencv直接可以使用sift算法,opencv-python==4.5.1版本測(cè)試可以使用。

      sift算法理論部分參考前面文章:sift算法理解

      關(guān)于sift,opencv中主要有這個(gè)幾個(gè)函數(shù):

      1.1 sift特征點(diǎn)檢測(cè)

      cv2.SIFT_create()

      創(chuàng)建sift對(duì)象,官方文檔:https://docs.opencv.org/4.5.3/d7/d60/classcv_1_1SIFT.html

      sift = cv2.SIFT_create(nfeatures=0, nOctaveLayers=3, contrastThreshold=0.04, edgeThreshold=10, sigma=1.6)
      
      參數(shù):
      	nfeatures: 需要保留的特征點(diǎn)的個(gè)數(shù),特征按分?jǐn)?shù)排序(分?jǐn)?shù)取決于局部對(duì)比度)
      	nOctaveLayers:每一組高斯差分金字塔的層數(shù),sift論文中用的3。高斯金字塔的組數(shù)通過圖片分辨率計(jì)算得到
      	contrastThreshold: 對(duì)比度閾值,用于過濾低對(duì)比度區(qū)域中的特征點(diǎn)。閾值越大,檢測(cè)器產(chǎn)生的特征越少。 (sift論文用的0.03,nOctaveLayers若為3, 設(shè)置參數(shù)為0.09,實(shí)際值為:contrastThreshold/nOctaveLayers)
      	edgeThreshold:用于過濾掉類似圖片邊界處特征的閾值(邊緣效應(yīng)產(chǎn)生的特征),注意其含義與contrastThreshold不同,即edgeThreshold越大,檢測(cè)器產(chǎn)生的特征越多(過濾掉的特征越少);sift論文中用的10;
      	sigma:第一組高斯金字塔高斯核的sigma值,sift論文中用的1.6。 (圖片較模糊,或者光線較暗的圖片,降低這個(gè)參數(shù))
      	descriptorType:特征描述符的數(shù)據(jù)類型,支持CV_32F和CV_8U
      
      返回值:sift對(duì)象(cv2.Feature2D對(duì)象)
      

      cv2.Feature2D.detect()

      檢測(cè)特征關(guān)鍵點(diǎn),官方文檔:https://docs.opencv.org/4.5.3/d0/d13/classcv_1_1Feature2D.html#a8be0d1c20b08eb867184b8d74c15a677

      keypoints = cv2.Feature2D.detect(image, mask)
      參數(shù):
      	image:需要檢測(cè)關(guān)鍵點(diǎn)的圖片
      	mask:掩膜,為0的區(qū)域表示不需要檢測(cè)關(guān)鍵點(diǎn),大于0的區(qū)域檢測(cè)
      返回值:
      	keypoints:檢測(cè)到的關(guān)鍵點(diǎn)
      

      cv2.Feature2D.compute()

      生成特征關(guān)鍵點(diǎn)的描述符,官方文檔:https://docs.opencv.org/4.5.3/d0/d13/classcv_1_1Feature2D.html#a8be0d1c20b08eb867184b8d74c15a677

      keypoints, descriptors = cv.Feature2D.compute(image, keypoints)
      參數(shù):
      	image:需要生成描述子的圖片
      	keypoints: 需要生成描述子的關(guān)鍵點(diǎn)
      返回值:
      	keypoints:關(guān)鍵點(diǎn)(原始關(guān)鍵點(diǎn)中,不能生成描述子的關(guān)鍵點(diǎn)會(huì)被移除;)
      	descriptors:關(guān)鍵點(diǎn)對(duì)應(yīng)的描述子
      	
      

      cv2.Feature2D.detectAndCompute()

      檢測(cè)關(guān)鍵點(diǎn),并生成描述符,是上面detect()和compute()的綜合

      keypoints, descriptors = cv.Feature2D.detectAndCompute(image, mask)
      

      cv2.drawKetpoints()

      繪制檢測(cè)到的關(guān)鍵點(diǎn),官方文檔:https://docs.opencv.org/4.5.3/d4/d5d/group__features2d__draw.html#ga5d2bafe8c1c45289bc3403a40fb88920

      outImage = cv2.drawKeypoints(image, keypoints, outImage, color, flags)
      參數(shù):
      	image:檢測(cè)關(guān)鍵點(diǎn)的原始圖像
      	keypoints:檢測(cè)到的關(guān)鍵點(diǎn)
      	outImage:繪制關(guān)鍵點(diǎn)后的圖像,其內(nèi)容取決于falgs的設(shè)置
      	color:繪制關(guān)鍵點(diǎn)采用的顏色
      	flags:
      		cv2.DRAW_MATCHES_FLAGS_DEFAULT:默認(rèn)值,匹配了的關(guān)鍵點(diǎn)和單獨(dú)的關(guān)鍵點(diǎn)都會(huì)被繪制
      		cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS: 繪制關(guān)鍵點(diǎn),且每個(gè)關(guān)鍵點(diǎn)都繪制圓圈和方向
      		cv2.DRAW_MATCHES_FLAGS_DRAW_OVER_OUTIMG:
      		cv2.DRAW_MATCHES_FLAGS_NOT_DRAW_SINGLE_POINTS:只繪制匹配的關(guān)鍵點(diǎn),單獨(dú)的關(guān)鍵點(diǎn)不繪制
      

      flags的原始含義如下:

      keypoint

      https://docs.opencv.org/4.5.3/d2/d29/classcv_1_1KeyPoint.html#aea339bc868102430087b659cd0709c11

      上述檢測(cè)到的keypoint,在opencv中是一個(gè)類對(duì)象,其具有如下幾個(gè)屬性:

      angle: 特征點(diǎn)的方向,值在0-360
      class_id: 用于聚類id,沒有進(jìn)行聚類時(shí)為-1
      octave: 特征點(diǎn)所在的高斯金差分字塔組
      pt: 特征點(diǎn)坐標(biāo)
      response: 特征點(diǎn)響應(yīng)強(qiáng)度,代表了該點(diǎn)時(shí)特征點(diǎn)的程度(特征點(diǎn)分?jǐn)?shù)排序時(shí),會(huì)根據(jù)特征點(diǎn)強(qiáng)度)
      size:特征點(diǎn)領(lǐng)域直徑
      

      descriptor

      檢測(cè)點(diǎn)對(duì)應(yīng)的descriptor,是一個(gè)128維的向量。

      sift簡單使用

      opencv中sift特征點(diǎn)檢測(cè)和繪制,使用代碼和結(jié)果如下:(opencv版本:opencv-python==4.5.1.48)

      import cv2
      
      img = cv2.imread(r"./lenna.png")
      img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
      
      sift = cv2.SIFT_create(nfeatures=0, nOctaveLayers=3, contrastThreshold=0.04, edgeThreshold=10, sigma=1.6)
      keypoints, descriptors = sift.detectAndCompute(img_gray, None)
      
      for keypoint,descriptor in zip(keypoints, descriptors):
          print("keypoint:", keypoint.angle, keypoint.class_id, keypoint.octave, keypoint.pt, keypoint.response, keypoint.size)
          print("descriptor: ", descriptor.shape)
      
      img = cv2.drawKeypoints(image=img_gray, outImage=img, keypoints=keypoints,
                              flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS,
                              color=(51, 163, 236))
      
      cv2.imshow("img_gray", img_gray)
      cv2.imshow("new_img", img)
      cv2.waitKey(0)
      cv2.destroyAllWindows()
      

      1.2 sift特征點(diǎn)匹配

      通過sift得到圖片特征點(diǎn)后,一般會(huì)進(jìn)行圖片之間的特征點(diǎn)匹配。

      1. 匹配方法

      opencv中的特征點(diǎn)匹配主要有兩種方法:BFMatcher,F(xiàn)lannBasedMatcher:

      BFMatcher

      官方文檔:https://docs.opencv.org/4.5.3/d3/da1/classcv_1_1BFMatcher.html

      Brute Froce Matcher: 簡稱暴力匹配,意思就是嘗試所有可能匹配,實(shí)現(xiàn)最佳匹配。其繼承于類cv2.DescriptorMatcher,

      matcher = cv2.BFMatcher(normType=cv2.NORM_L2, crossCheck=False)   # 創(chuàng)建BFMatcher對(duì)象
      

      FlannBasedMatcher

      官方文檔:https://docs.opencv.org/4.5.3/dc/de2/classcv_1_1FlannBasedMatcher.html

      Flann-based descriptor matcher: 最近鄰近似匹配。 是一種近似匹配方法,并不追求完美,因此速度更快。 可以調(diào)整FlannBasedMatcher參數(shù)改變匹配精度或算法速度。其繼承于類cv2.DescriptorMatcher。

      FLANN_INDEX_KDTREE = 0  # 建立FLANN匹配器的參數(shù)
      indexParams = dict(algorithm=FLANN_INDEX_KDTREE, trees=5)  # 配置索引,密度樹的數(shù)量為5
      searchParams = dict(checks=50)  # 指定遞歸次數(shù)
      matcher = cv2.FlannBasedMatcher(indexParams, searchParams)  # 建立FlannBasedMatcher對(duì)象
      

      indexParams:

      algorithm:
          FLANN_INDEX_LINEAR:	線性暴力(brute-force)搜索
          FLANN_INDEX_KDTREE:	隨機(jī)kd樹,平行搜索。默認(rèn)trees=4
          FLANN_INDEX_KMEANS:	層次k均值樹。默認(rèn)branching=32,iterations=11,centers_init = CENTERS_RANDOM, cb_index =0.2
          FLANN_INDEX_COMPOSITE:	隨機(jī)kd樹和層次k均值樹來構(gòu)建索引。默認(rèn)trees =4,branching =32,iterations =11,centers_init=CENTERS_RANDOM,cb_index =0.2
      

      searchParams:

      SearchParams (checks=32, eps=0, sorted=true)
          checks:	默認(rèn)32
          eps:	默認(rèn)為0
          sorted:	默認(rèn)True
      

      2. 繪制匹配

      KMatch

      官方文檔:https://docs.opencv.org/4.5.3/d4/de0/classcv_1_1DMatch.html

      上述通過匹配方法得到的匹配,在opencv中都用KMatch類表示,其具有幾個(gè)屬性如下:

      queryIdx:查詢點(diǎn)的索引
      trainIdx:被查詢點(diǎn)的索引
      distance:查詢點(diǎn)和被查詢點(diǎn)之間的距離
      

      下面代碼中,每個(gè)點(diǎn)尋找兩個(gè)最近鄰匹配點(diǎn),即對(duì)于kp1中的每個(gè)關(guān)鍵點(diǎn),在kp2中尋找兩個(gè)和它距離最近的特征點(diǎn),所以每個(gè)關(guān)鍵點(diǎn)產(chǎn)生兩組匹配,即兩個(gè)KMatch類。kp1相當(dāng)于索引關(guān)鍵點(diǎn),對(duì)應(yīng)queryIdx; kp2相當(dāng)于查詢關(guān)鍵點(diǎn),對(duì)應(yīng)trainIdx。

      import cv2
      
      img1 = cv2.imread("iphone1.png")
      img2 = cv2.imread("iphone2.png")
      sift = cv2.SIFT_create()
      
      kp1, des1 = sift.detectAndCompute(img1, None)
      kp2, des2 = sift.detectAndCompute(img2, None)
      # 采用暴力匹配
      matcher = cv2.BFMatcher()
      matches = matcher.knnMatch(des1, des2, k=2)  # k=2,表示尋找兩個(gè)最近鄰
      
      # 上面每個(gè)點(diǎn)尋找兩個(gè)最近鄰匹配點(diǎn),即對(duì)于kp1中的每個(gè)關(guān)鍵點(diǎn),在kp2中尋找兩個(gè)和它距離最近的特征點(diǎn),所以每個(gè)關(guān)鍵點(diǎn)產(chǎn)生兩組匹配,即兩個(gè)KMatch類
      # kp1相當(dāng)于索引關(guān)鍵點(diǎn),對(duì)應(yīng)queryIdx; kp2相當(dāng)于查詢關(guān)鍵點(diǎn),對(duì)應(yīng)trainIdx
      for m in matches:  # 若尋找三個(gè)最近鄰點(diǎn),則m包括三個(gè)KMacth
          print(m[0].queryIdx, m[0].queryIdx, m[0].distance)  # m[0]表示距離最近的那個(gè)匹配
          print(m[1].queryIdx, m[1].queryIdx, m[1].distance)  # m[1]表示距離第二近的那個(gè)匹配
      

      參考:https://blog.csdn.net/wphkadn/article/details/85805105

      drawMatches()

      opencv中drawMatches()能繪制匹配特征點(diǎn)

      官方文檔:https://docs.opencv.org/4.5.3/d4/d5d/group__features2d__draw.html#ga5d2bafe8c1c45289bc3403a40fb88920

      outImg = cv2.drawMatches(img1, keypoints1, img2, keypoints2, matches1to2, outImg, matchColor, singlePointColor, matchesMask, flags)
      參數(shù):
      	img1:圖像1
      	keypoints1:圖像1的特征點(diǎn)
      	img2:圖像2
      	keypoints1:圖像2的特征點(diǎn)
      	matches1to2:圖像1特征點(diǎn)到圖像2特征點(diǎn)的匹配,keypoints1[i]和keypoints2[matches[i]]為匹配點(diǎn)
      	outImg: 繪制完的輸出圖像
      	matchColor:匹配特征點(diǎn)和其連線的顏色,-1時(shí)表示顏色隨機(jī)
      	singlePointColor:未匹配點(diǎn)的顏色,-1時(shí)表示顏色隨機(jī)
      	matchesMask: mask決定那些匹配點(diǎn)被畫出,若為空,則畫出所有匹配點(diǎn)
      	flags: 和上述cv2.drawKeypoints()中flags取值一樣
      

      下面代碼中對(duì)sift提取的特征點(diǎn)進(jìn)行匹配,采用暴力法匹配,并根據(jù)knn近鄰法中兩個(gè)鄰居的距離,篩選出了部分匹配點(diǎn),代碼和結(jié)果如下:

      import cv2
      import numpy as np
      
      #自己繪制匹配連線
      def drawMatchesKnn_cv2(img1, kp1, img2, kp2, goodMatch):
          h1, w1 = img1.shape[:2]
          h2, w2 = img2.shape[:2]
      
          vis = np.zeros((max(h1, h2), w1 + w2, 3), np.uint8)
          vis[:h1, :w1] = img1
          vis[:h2, w1:w1 + w2] = img2
      
          p1 = [kpp.queryIdx for kpp in goodMatch]
          p2 = [kpp.trainIdx for kpp in goodMatch]
          post1 = np.int32([kp1[pp].pt for pp in p1])
          post2 = np.int32([kp2[pp].pt for pp in p2]) + (w1, 0)
          for (x1, y1), (x2, y2) in zip(post1, post2):
              cv2.line(vis, (x1, y1), (x2, y2), (0, 0, 255))
          cv2.imshow("match", vis)
      
      
      img1 = cv2.imread("iphone1.png")
      img2 = cv2.imread("iphone2.png")
      sift = cv2.SIFT_create()
      
      kp1, des1 = sift.detectAndCompute(img1, None)
      kp2, des2 = sift.detectAndCompute(img2, None)
      
      # 采用暴力匹配
      matcher = cv2.BFMatcher()
      matches = matcher.knnMatch(des1, des2, k=2)  # k=2,表示尋找兩個(gè)最近鄰
      
      # 采用最近鄰近似匹配
      # FLANN_INDEX_KDTREE = 0  # 建立FLANN匹配器的參數(shù)
      # indexParams = dict(algorithm=FLANN_INDEX_KDTREE, trees=5)  # 配置索引,密度樹的數(shù)量為5
      # searchParams = dict(checks=50)  # 指定遞歸次數(shù)
      # matcher = cv2.FlannBasedMatcher(indexParams, searchParams)  # 建立FlannBasedMatcher對(duì)象
      # matches = matcher.knnMatch(des1, des2, k=2)  # k=2,表示尋找兩個(gè)最近鄰
      
      h1, w1 = img1.shape[:2]
      h2, w2 = img2.shape[:2]
      
      out_img1 = np.zeros((max(h1, h2), w1 + w2, 3), np.uint8)
      out_img1[:h1, :w1] = img1
      out_img1[:h2, w1:w1 + w2] = img2
      out_img1 = cv2.drawMatchesKnn(img1, kp1, img2, kp2, matches, out_img1)
      
      good_match = []
      for m, n in matches:
          if m.distance < 0.5*n.distance:    # 如果第一個(gè)鄰近距離比第二個(gè)鄰近距離的0.5倍小,則保留
              good_match.append(m)
      
      out_img2 = np.zeros((max(h1, h2), w1 + w2, 3), np.uint8)
      out_img2[:h1, :w1] = img1
      out_img2[:h2, w1:w1 + w2] = img2
      # p1 = [kp1[kpp.queryIdx] for kpp in good_match]  # kp1中挑選處的關(guān)鍵點(diǎn)
      # p2 = [kp2[kpp.trainIdx] for kpp in good_match]  # kp2中挑選處的關(guān)鍵點(diǎn)
      out_img2 = cv2.drawMatches(img1, kp1, img2, kp2, good_match, out_img2)
      # drawMatchesKnn_cv2(img1, kp1, img2, kp2, good_match)
      
      
      cv2.imshow("out_img1", out_img1)
      cv2.imshow("out_img2", out_img2)
      cv2.waitKey(0)
      cv2.destroyAllWindows()
      

      參考:http://www.rzrgm.cn/wangguchangqing/p/4333873.html

      https://blog.csdn.net/claroja/article/details/83411108

      posted @ 2021-08-21 18:07  silence_cho  閱讀(7142)  評(píng)論(0)    收藏  舉報(bào)
      主站蜘蛛池模板: 亚洲欧美日韩国产精品一区二区| 日本丰满白嫩大屁股ass| 日本一区二区三区在线 |观看| 国产区精品福利在线熟女| 亚洲另类无码一区二区三区| 2021亚洲国产精品无码| 激情动态图亚洲区域激情| 福利一区二区不卡国产| 激情伊人五月天久久综合 | 色伦专区97中文字幕| 亚洲午夜理论无码电影| 亚洲情综合五月天| 国产精品亚洲mnbav网站| 日日摸夜夜添夜夜添国产三级| 久久不见久久见www日本| 香港日本三级亚洲三级| 国产蜜臀一区二区三区四区| 久久天天躁夜夜躁狠狠85| 免费无码又爽又刺激网站直播| 国产亚洲精品日韩av在| 人妻中文字幕在线视频无码| 国产精品免费中文字幕| 色吊丝免费av一区二区| 高清无码18| 免费无码影视在线观看mov| 噜噜噜噜私人影院| www夜插内射视频网站| 丰满人妻一区二区三区色| 国产成人AV在线免播放观看新| 无码人妻精品一区二区三区下载| 起碰免费公开97在线视频| 91福利一区二区三区| 日本精品一区二区不卡| 色综合久久一区二区三区| 精品日韩亚洲av无码| 狠狠做五月深爱婷婷天天综合| 国产亚洲精品日韩av在| 无码人妻丝袜在线视频| 成人3d动漫一区二区三区| 久久综合免费一区二区三区| 香蕉在线精品一区二区|