opencv ORB特征檢測(cè)識(shí)別樂(lè)譜符號(hào)

ORB算法簡(jiǎn)介

最近學(xué)習(xí)了opencv的相關(guān)操作退腥,更新一下對(duì)樂(lè)譜的識(shí)別技術(shù)。首先介紹關(guān)鍵操作:ORB特征在python下的使用:
ORB算法的參數(shù)是使用ORB_create()函數(shù)設(shè)置的纱意。 ORB_create()函數(shù)的參數(shù)及其默認(rèn)值如下所示:

cv2.ORB_create(nfeatures = 500,
scaleFactor = 1.2,
nlevels = 8,
edgeThreshold = 31,
firstLevel = 0,
WTA_K = 2,
scoreType = HARRIS_SCORE,
patchSize = 31,
fastThreshold = 20)

參數(shù)解釋?zhuān)?/h3>
  • nfeatures - int
    確定要查找的功能(關(guān)鍵點(diǎn))的最大數(shù)量洽洁。

  • scaleFactor - float
    金字塔抽取比率必須大于1.ORB使用圖像金字塔來(lái)查找要素,因此您必須提供金字塔中每層之間的比例因子和金字塔所具有的層數(shù)订晌。 scaleFactor = 2表示古典金字塔虏辫,每個(gè)下一個(gè)級(jí)別的像素比前一個(gè)像素少4倍。大比例因子將減少找到的功能數(shù)量锈拨。

  • nlevels - int
    金字塔等級(jí)的數(shù)量砌庄。最小級(jí)別的線性大小等于input_image_linear_size / pow(scaleFactor,nlevels)奕枢。

  • edgeThreshold - - int
    未檢測(cè)到要素的邊框的大小娄昆。由于關(guān)鍵點(diǎn)具有特定的像素大小,因此圖像的邊緣必須從搜索中排除缝彬。 edgeThreshold的大小應(yīng)該等于或大于patchSize參數(shù)萌焰。

  • firstLevel - int
    此參數(shù)允許您確定哪個(gè)級(jí)別應(yīng)視為金字塔中的第一級(jí)。在當(dāng)前的實(shí)現(xiàn)中它應(yīng)該是0谷浅。通常扒俯,具有統(tǒng)一比例的金字塔等級(jí)被認(rèn)為是第一等級(jí)。

  • WTA_K - int
    用于產(chǎn)生定向的BRIEF描述符的每個(gè)元素的隨機(jī)像素的數(shù)量一疯『承可能的值是2,3和4,其中2是默認(rèn)值墩邀。例如掌猛,3的值意味著一次選擇三個(gè)隨機(jī)像素來(lái)比較它們的亮度。最亮像素的索引被返回眉睹。由于有3個(gè)像素荔茬,返回的索引將為0,1或2只盹。

  • scoreType - int
    該參數(shù)可以設(shè)置為HARRIS_SCORE或FAST_SCORE。默認(rèn)的HARRIS_SCORE表示Harris corner算法用于對(duì)要素進(jìn)行排名兔院。該分?jǐn)?shù)僅用于保留最佳功能殖卑。 FAST_SCORE產(chǎn)生的穩(wěn)定關(guān)鍵點(diǎn)稍低,但計(jì)算速度稍快坊萝。

  • patchSize - int
    面向BRIEF描述符使用的補(bǔ)丁大小孵稽。當(dāng)然,在較小的金字塔層上十偶,由特征覆蓋的感知圖像區(qū)域?qū)⒏蟆?/p>

# Import copy to make copies of the training image
import copy

# Set the default figure size
plt.rcParams['figure.figsize'] = [14.0, 7.0]

# Set the parameters of the ORB algorithm by specifying the maximum number of keypoints to locate and
# the pyramid decimation ratio
orb = cv2.ORB_create(200, 2.0)

# Find the keypoints in the gray scale training image and compute their ORB descriptor.
# The None parameter is needed to indicate that we are not using a mask.
keypoints, descriptor = orb.detectAndCompute(training_gray, None)

# Create copies of the training image to draw our keypoints on
keyp_without_size = copy.copy(training_image)
keyp_with_size = copy.copy(training_image)

# Draw the keypoints without size or orientation on one copy of the training image 
cv2.drawKeypoints(training_image, keypoints, keyp_without_size, color = (0, 255, 0))

"""
下面的方法就是把關(guān)鍵點(diǎn)以及范圍描述出來(lái)
"""
# Draw the keypoints with size and orientation on the other copy of the training image
cv2.drawKeypoints(training_image, keypoints, keyp_with_size, flags = cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)

# Display the image with the keypoints without size or orientation
plt.subplot(121)
plt.title('Keypoints Without Size or Orientation')
plt.imshow(keyp_without_size)

# Display the image with the keypoints with size and orientation
plt.subplot(122)
plt.title('Keypoints With Size and Orientation')
plt.imshow(keyp_with_size)
plt.show()

# Print the number of keypoints detected
print("\nNumber of keypoints Detected: ", len(keypoints))
運(yùn)行結(jié)果.png

特征比對(duì)

cv2.BFMatcher(normType = cv2.NORM_L2,
crossCheck = false)

  • normType
    指定用于確定匹配質(zhì)量的度量菩鲜。默認(rèn)情況下,normType = cv2.NORM_L2惦积,它測(cè)量?jī)蓚€(gè)描述符之間的距離接校。但是,對(duì)于由ORB創(chuàng)建的二進(jìn)制描述符狮崩,海明度量標(biāo)準(zhǔn)更適合蛛勉。漢明度量通過(guò)計(jì)算二進(jìn)制描述符之間的不相似位的數(shù)量來(lái)確定距離。當(dāng)使用WTA_K = 2創(chuàng)建ORB描述符時(shí)睦柴,選擇兩個(gè)隨機(jī)像素并在亮度上進(jìn)行比較诽凌。最亮像素的索引返回為0或1.這種輸出只占用1位,因此應(yīng)該使用cv2.NORM_HAMMING度量坦敌。另一方面侣诵,如果使用WTA_K = 3創(chuàng)建ORB描述符,則選擇三個(gè)隨機(jī)像素并在亮度上進(jìn)行比較狱窘。最亮像素的索引返回為0,1或2.這樣的輸出將占用2位杜顺,因此稱(chēng)為cv2.NORM_HAMMING2(2代表2位)的漢明距離的特殊變體應(yīng)該是代替使用。然后蘸炸,對(duì)于選擇的任何度量躬络,當(dāng)比較訓(xùn)練和查詢圖像中的關(guān)鍵點(diǎn)時(shí),具有較小度量(它們之間的距離)的對(duì)被認(rèn)為是最佳匹配幻馁。

  • crossCheck - bool
    一個(gè)布爾變量洗鸵,可以設(shè)置為T(mén)rue或False越锈。交叉檢查對(duì)于消除錯(cuò)誤匹配非常有用仗嗦。通過(guò)兩次執(zhí)行匹配程序進(jìn)行交叉檢查。第一次將訓(xùn)練圖像中的關(guān)鍵點(diǎn)與查詢圖像中的關(guān)鍵點(diǎn)進(jìn)行比較;然而甘凭,第二次將查詢圖像中的關(guān)鍵點(diǎn)與訓(xùn)練圖像中的關(guān)鍵點(diǎn)進(jìn)行比較(即稀拐,比較是向后完成的)。當(dāng)啟用交叉檢查時(shí)丹弱,只有在訓(xùn)練圖像中的關(guān)鍵點(diǎn)A是查詢圖像中關(guān)鍵點(diǎn)B的最佳匹配(反之亦然)(即德撬,如果查詢圖像中的關(guān)鍵點(diǎn)B是訓(xùn)練圖像中的點(diǎn)A)铲咨。

# Set the default figure size
plt.rcParams['figure.figsize'] = [34.0, 34.0]

# Create a Brute Force Matcher object. We set crossCheck to True so that the BFMatcher will only return consistent
# pairs. Such technique usually produces best results with minimal number of outliers when there are enough matches.
bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck = True)

# Perform the matching between the ORB descriptors of the training image and the query image
matches = bf.match(descriptors_train, descriptors_query)

# The matches with shorter distance are the ones we want. So, we sort the matches according to distance
matches = sorted(matches, key = lambda x : x.distance)

# Connect the keypoints in the training image with their best matching keypoints in the query image.
# The best matches correspond to the first elements in the sorted matches list, since they are the ones
# with the shorter distance. We draw the first 85 mathces and use flags = 2 to plot the matching keypoints
# without size or orientation.
result = cv2.drawMatches(training_gray, keypoints_train, query_gray, keypoints_query, matches[:85], query_gray, flags = 2)

# we display the image
plt.title('Best Matching Points', fontsize = 30)
plt.imshow(result)
plt.show()

# Print the number of keypoints detected in the training image
print("Number of Keypoints Detected In The Training Image: ", len(keypoints_train))

# Print the number of keypoints detected in the query image
print("Number of Keypoints Detected In The Query Image: ", len(keypoints_query))

# Print total number of matching Keypoints between the training and query images
print("\nNumber of Matching Keypoints Between The Training and Query Images: ", len(matches))
image.png

樂(lè)譜中的應(yīng)用

import cv2
import numpy as np
import matplotlib.pyplot as plt
import os
import copy

"""
使用順序:
upload_pic(path) 傳入文件夾路徑
select_pic(i) 選定第i個(gè)圖
show_pic()  查看此圖像
show_area(x,xx,y,yy) 展示圖片區(qū)域
set_aim_area()  將展示的區(qū)域設(shè)為目標(biāo)圖像
show_feature()  以默認(rèn)參數(shù)運(yùn)行ORB   set_cv_parements()修改參數(shù)
serch_featrue() 在當(dāng)前圖片中搜索匹配
plot_result()   將搜索到的部分展示出來(lái)(最大30 張)
"""
class Score(object):
    
    def upload_pic(self,path):
        piclistdr=self.walkFile_item(path)
        self.picture_list=self.read_picture(piclistdr)
        self.len = len(self.picture_list)
        
    def select_pic(self,i):
        if i>=self.len:
            print('retry, max len is {}'.format(len(self.len)))
        else:
            self.i = i
            
    def show_area(self,x,xx,y,yy):
        if not self.i:
            self.i = 0

        self.picture = self.picture_list[self.i]
        self.area = self.picture[x:xx,y:yy,:]
        plt.imshow(self.area)
        
    def set_aim_area(self):
            self.aim_area = self.area

    def show_pic(self):
        plt.imshow(self.picture)
    
        
    def show_feature(self):
        self.set_cv_parements()
        self.aim_area_gray = cv2.cvtColor(self.aim_area, cv2.COLOR_BGR2GRAY)

        self.aimkeypoints, self.aimdescriptor = self.orb.detectAndCompute(self.aim_area_gray , None)

        # Create copies of the training image to draw our keypoints on
        keyp_without_size = copy.copy(self.aim_area)
        keyp_with_size = copy.copy(self.aim_area)
        cv2.drawKeypoints(self.aim_area, self.aimkeypoints, keyp_without_size, color = (0, 255, 0))
        cv2.drawKeypoints(self.aim_area, self.aimkeypoints, keyp_with_size, flags = cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)

        # Display the image with the keypoints without size or orientation
        plt.subplot(121)
        plt.title('Keypoints Without Size or Orientation')
        plt.imshow(keyp_without_size)

        # Display the image with the keypoints with size and orientation
        plt.subplot(122)
        plt.title('Keypoints With Size and Orientation')
        plt.imshow(keyp_with_size)
        plt.show()

        # Print the number of keypoints detected
        print("\nNumber of keypoints Detected: ", len(self.aimkeypoints))
        
    def serch_featrue(self,mid_step,thread):
        dx,dy,cc = self.aim_area.shape
        self.mid_step=mid_step
        self.dx = dx
        self.dy = dy
        aa,bb,cc = self.picture.shape
        xstep ,ystep= int((aa-dx)/mid_step),int((bb-dy)/mid_step)

        self.anserlist=[]
        for xs in range(xstep):
            for ys in range(ystep):
                query_image = self.picture[(xs)*self.mid_step:(xs)*self.mid_step+dx,
                                   (ys)*self.mid_step:(ys)*self.mid_step+dy,:]


                query_gray = cv2.cvtColor(query_image, cv2.COLOR_BGR2GRAY)
                keypoints_query, descriptors_query = self.orb.detectAndCompute(query_gray, None)
                          
                bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck = True)
                try:
                    matches = bf.match(self.aimdescriptor, descriptors_query)
                    matches = sorted(matches, key = lambda x : x.distance)
                    #print(xs,ys)
                    if len(matches)>thread:
                        self.anserlist.append([xs,ys,len(matches)])
                except:
                    pass
                                          
    def plot_result(self):

        for i,j in enumerate(self.anserlist[:30]):
            
            xs,ys,i=j[0],j[1],i+1
            ax = plt.subplot(5,6,i)        
            mid_step = self.mid_step
            query_image = self.picture[(xs)*mid_step:(xs)*mid_step+self.dx,
                               (ys)*mid_step:(ys)*mid_step+self.dy,:]
            query_gray = cv2.cvtColor(query_image, cv2.COLOR_BGR2GRAY)

            ax.imshow(query_gray)
            ax.set_title("location_{}_{}".format(xs,ys))

   
    def set_cv_parements(self,mount=200,vec=1.3,edge=21,WTA=2,patch=10,fast=10):
        self.orb = cv2.ORB_create(mount,vec,edgeThreshold = edge,
               firstLevel = 0,
               WTA_K = WTA,
               patchSize = patch,
               fastThreshold = fast)

    def show(self,xs,ys,i):
        ax = plt.subplot(5,6,i)
        
        mid_step = self.mid_step
        query_image = self.picture[(xs)*mid_step:(xs)*mid_step+dx,
                           (ys)*mid_step:(ys)*mid_step+dy,:]
        query_gray = cv2.cvtColor(query_image, cv2.COLOR_BGR2GRAY)

        ax.imshow(query_gray)
        ax.set_title("location_{}_{}".format(xs,ys))


    @staticmethod
    def walkFile_F(file):
        filelist = []
        for root, dirs, files in os.walk(file):
            for d in dirs:
                filelist.append(os.path.join(root, d))
        return filelist
    
    @staticmethod
    def walkFile_item(file):
        piclist=[]
        for root, dirs, files in os.walk(file):
            for f in files:
                piclist.append(os.path.join(root, f))
        return piclist
    
    @staticmethod
    def read_picture(path):
        picture_list = [cv2.imread(i) for i in path]
        picture_list = [cv2.cvtColor(i,cv2.COLOR_BGR2RGB) for i in picture_list]
        return picture_list

if __name__== "main":
    score = Score()
    score.upload_pic(r'C:\Users\86355\Desktop\score_detector\img_pdf')
    score.select_pic(7)
    score.show_area(360,480,355,405)
    score.set_aim_area()
    score.show_feature()A
    score.select_pic(15)
    score.serch_featrue(25,9)
    score.aim_area.shape
    %matplotlib qt5
    print(len(score.anserlist))
    score.plot_result()
 
show feature
匹配到的符號(hào)

切換其他片段:


休止符
休止符特征

修改參數(shù)后運(yùn)行

    score.select_pic(15)
    score.set_cv_parements(mount=200,vec=1.4,edge=15,WTA=2,patch=8,fast=15)
    score.serch_featrue(25,15)
    score.aim_area.shape
    %matplotlib qt5
    print(len(score.anserlist))
    score.plot_result()
運(yùn)行結(jié)果:有少數(shù)錯(cuò)誤

總結(jié)

單純使用ORB特征算法匹配效果勉強(qiáng),但是由于此類(lèi)圖像形狀單一蜓洪,默認(rèn)參數(shù)檢測(cè)不到特征纤勒,參數(shù)需要手工調(diào)整。對(duì)每一種類(lèi)型的符號(hào)這樣調(diào)整是不現(xiàn)實(shí)的隆檀。此算法在識(shí)譜中可以作為深度學(xué)習(xí)前期摇天,半自動(dòng)處理圖數(shù)據(jù)時(shí)作為篩選過(guò)濾器使用。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末恐仑,一起剝皮案震驚了整個(gè)濱河市泉坐,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌裳仆,老刑警劉巖腕让,帶你破解...
    沈念sama閱讀 211,042評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異歧斟,居然都是意外死亡纯丸,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門(mén)静袖,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)液南,“玉大人,你說(shuō)我怎么就攤上這事勾徽』梗” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,674評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵喘帚,是天一觀的道長(zhǎng)畅姊。 經(jīng)常有香客問(wèn)我,道長(zhǎng)吹由,這世上最難降的妖魔是什么若未? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,340評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮倾鲫,結(jié)果婚禮上粗合,老公的妹妹穿的比我還像新娘。我一直安慰自己乌昔,他們只是感情好隙疚,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,404評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著磕道,像睡著了一般供屉。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,749評(píng)論 1 289
  • 那天伶丐,我揣著相機(jī)與錄音悼做,去河邊找鬼。 笑死哗魂,一個(gè)胖子當(dāng)著我的面吹牛肛走,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播录别,決...
    沈念sama閱讀 38,902評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼羹与,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了庶灿?” 一聲冷哼從身側(cè)響起纵搁,我...
    開(kāi)封第一講書(shū)人閱讀 37,662評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎往踢,沒(méi)想到半個(gè)月后腾誉,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,110評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡峻呕,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年利职,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片瘦癌。...
    茶點(diǎn)故事閱讀 38,577評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡猪贪,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出讯私,到底是詐尸還是另有隱情热押,我是刑警寧澤,帶...
    沈念sama閱讀 34,258評(píng)論 4 328
  • 正文 年R本政府宣布斤寇,位于F島的核電站桶癣,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏娘锁。R本人自食惡果不足惜牙寞,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,848評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望莫秆。 院中可真熱鬧间雀,春花似錦、人聲如沸镊屎。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,726評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)杯道。三九已至匪煌,卻和暖如春责蝠,著一層夾襖步出監(jiān)牢的瞬間党巾,已是汗流浹背萎庭。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,952評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留齿拂,地道東北人驳规。 一個(gè)月前我還...
    沈念sama閱讀 46,271評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像署海,于是被迫代替她去往敵國(guó)和親吗购。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,452評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容