五線定位&分譜腳本(python)

help.py

import cv2
import numpy as np
import matplotlib.pyplot as plt
import os
import copy
import collections
import pandas as pd
import time
import copy


class Score(object):
    def __init__(self):
        self.figure_index = 0
        self.score_page={}
    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
        self.picture = self.picture_list[i]
        
        
        
            

    
    def show_pic(self):
        plt.figure(self.figure_index)
        self.figure_index +=1
        plt.imshow(self.picture)
    def proc_one(self,pidx):
        print('start  {}'.format(pidx))
        self.continues = True
        lll=None
        f5=None
        finallist=None
        linenew=None
        lista=None
        listmid = None
        grouplist=None
        gob_list=None
        glob_delt_list=None
        col=None
        stdd=None
        gob_list1=None
        gob_list2=None
        
        self.select_pic(pidx)
        
        f5 = find5lines(self.picture)
        f5.getall_lines()
        
        if len(f5.linelist)<20:
            self.continues =False
            return
        lll = Lines(f5.linelist)
        gob_list2 =process_one(lll,self)
        self.score_page[pidx] = gob_list2
        self.f5 = f5
        
        
    def proc_all(self):
        for i in range(len(self.picture_list)):
            self.proc_one(i)
            
    def show_line(self,idx):
        listend = []
        for i in self.score_page[idx]:
            listend.append(i.pos1)
            listend.append(i.pos2)
            listend.append(i.pos3)
            listend.append(i.pos4)
            listend.append(i.pos5)

        plt.imshow(self.picture_list[idx])
        for mm in listend:
            plt.axhline(y=mm,ls=":",c="b")#添加水平直線
        
        
        
        
    @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]
        
        (new_w,new_h) = (2592,3456)
        
        #picture_list = [cv2.resize(i, (new_w,new_h) ) for i in picture_list]
        return picture_list
  
class find5lines(object):
    def __init__(self,pic,thsize=10):
        
        thsize = 10
        #thsize =100
        pic = cv2.cvtColor(pic, cv2.COLOR_BGR2GRAY)
        pic[pic>253]=255
        pic[pic<=253]=0
        #plt.matshow(pic)
        _, labels, _, _ = cv2.connectedComponentsWithStats(pic,4)
        self.labels = labels
        self.linelist=[]
        counter1 = collections.Counter((labels.reshape(1,-1)[0]))
        th =thsize
        
        
        self.df =  pd.DataFrame(pd.DataFrame(labels).stack()).reset_index().set_index(0)
        self.df = self.df.reset_index().groupby([0,'level_0']).count().reset_index().set_index(0)
        self.countdf = pd.DataFrame(self.df.reset_index().groupby(0)['level_0'].sum())
        
        self.count2 = list(self.countdf[self.countdf>th].dropna().index)
        #print(len(self.count2))
    def isline(self,idx):
        
        
        lens = self.countdf.loc[idx,'level_0']
        midf=self.df.loc[idx,:]
        #if isinstance(midf['level_1'],int):return
        #self.midf = midf
        if len(midf.shape)==1:
            return
        
        
        mid = list(midf['level_1'])
        #print(len(mid))
        mid2 = list(midf['level_0'])


        #print(mid2[-1])
        
        upcount =mid[-1]
        downcount =mid[0]
        thlen = int(np.sqrt(lens)*0.5)
        #print(thlen)
        #print(upcount)
        #print(downcount)

        #print(thlen)
        if (upcount>thlen):
            self.linelist.append (mid2[-1])
        elif (downcount>thlen):
            self.linelist.append (mid2[0])
    def getall_lines(self):
        
        for i in self.count2:
            self.isline(i) 
        self.linelist =list(set(self.linelist))
        self.linelist = sorted(self.linelist,reverse=False)

class Lines(object):
    def __init__(self,lines):
        self.lines =lines
        self.colculate()
        self.colculate2()
    def colculate(self):
        self.Llist =[]
        for i in range(len(self.lines)):
            line = Line()
            line.set_pos(self.lines[i])
            self.Llist.append(line)
    def colculate2(self):
        for i in range(len(self.Llist)):
            if i==0:
                self.Llist[i].set_deltal(400)
                nd =  self.Llist[i+1]. get_pos()
                td =  self.Llist[i]. get_pos()
                self.Llist[i].set_deltan(nd-td)
                
            elif i ==(len(self.Llist)-1):
                self.Llist[i].set_deltan(400)
                ld = self.Llist[i-1]. get_pos()
                td =  self.Llist[i]. get_pos()
                self.Llist[i].set_deltal(td-ld)
            
            else:
                ld = self.Llist[i-1]. get_pos()
                nd =  self.Llist[i+1]. get_pos()
                td =  self.Llist[i]. get_pos()

                self.Llist[i].set_deltal(td-ld)
                self.Llist[i].set_deltan(nd-td)
            
class Line(object):
    def __init__(self):
        self.pos =None
        self.dis =None
        self.L5 =None
        self.deltal =None
        self.deltan =None

    def get_pos(self):
        return self.pos
    def set_pos(self,pos):
        self.pos = pos

        

        
    def get_deltal(self):
        return self.deltal
    def set_deltal(self,deltal):
        self.deltal = deltal
        
    def get_deltan(self):
        return self.deltan
    def set_deltan(self,deltan):
        self.deltan = deltan
    
    
    def get_5(self):
        return self.L5
    def set_5(self,L5):
        self.L5 = L5
        
    
    def get_dis(self):
        return self.dis
    def set_dis(self,di):
        self.dis = dis
    
    def __str__(self):
        return "pos:{}\tl5:{}\tdistribute:{}\tlast:{}\tnext:{}".format(self.get_pos(),
                                                                       self.get_5(),
                                                                       self.get_dis(),
                                                                   self.get_deltal(),
                                                                   self.get_deltan(),)
        #print(strings)
        
        
        
class GroupLine(object):
    def __init__(self,linelist):
        self.linelist = linelist
        self.pos1 =None 
        self.pos2 = None
        self.pos3 = None
        self.pos4 = None
        self.pos5 = None
        self.cheack()
    
    def cheack(self):
        if len(self.linelist)>5:
            self.pos1 = self.linelist[-5].get_pos()
            self.pos2 = self.linelist[-4].get_pos()
            self.pos3 = self.linelist[-3].get_pos()
            self.pos4 = self.linelist[-2].get_pos()
            self.pos5 = self.linelist[-1].get_pos()
        
        if len(self.linelist)==5:
            self.pos1 = self.linelist[0].get_pos()
            self.pos2 = self.linelist[1].get_pos()
            self.pos3 = self.linelist[2].get_pos()
            self.pos4 = self.linelist[3].get_pos()
            self.pos5 = self.linelist[4].get_pos()
        elif len(self.linelist )==4:            
            deltas = int((self.linelist[1].get_deltan()+self.linelist[2].get_deltan())/2)
            self.pos1 = self.linelist[0].get_pos()-deltas 
            self.pos2 = self.linelist[0].get_pos()
            self.pos3 = self.linelist[1].get_pos()
            self.pos4 = self.linelist[2].get_pos()
            self.pos5 = self.linelist[3].get_pos()
        elif len(self.linelist )==3:            
            deltas = int(min(self.linelist[1].get_deltan(),self.linelist[2].get_deltan()))
            self.pos1 = self.linelist[0].get_pos()-deltas 
            self.pos2 = self.linelist[0].get_pos()
            self.pos3 = self.linelist[1].get_pos()
            self.pos4 = self.linelist[2].get_pos()
            self.pos5 = self.linelist[2].get_pos()+deltas
        
        else:
            pass
           
        
    def adjust(self,stdd):
        self.pos1 = self.pos5 -4*stdd
        self.pos2 = self.pos5 -3*stdd
        self.pos3 = self.pos5 -2*stdd
        self.pos4 = self.pos5 -stdd
        
        

def process_one(lll,self):
    
    contrals_delta = max(int(self.picture.shape[0]/450),1)
    finallist=[]
    lock =0
    for i in range(len(lll.Llist)):

        if lock:
            lock = 0
            continue

        if (lll.Llist[i].get_deltan()<contrals_delta):
            linenew = Line()
            linenew.set_pos(int(lll.Llist[i].get_pos()+lll.Llist[i].get_deltan()/2))
            linenew.set_deltan(int(lll.Llist[i].get_deltan()/2+lll.Llist[i+1].get_deltan()))
            linenew.set_deltal(lll.Llist[i].get_deltal())
            finallist.append(linenew)
            lock = 1
        else:
            finallist.append(lll.Llist[i])

    thethet = int(self.picture.shape[0]/240)

    for i in (finallist):
        if (i.get_deltan()>thethet) and(i.get_deltal()<=thethet):
            i.set_5(5)
        elif (i.get_deltan()<=thethet ) and(i.get_deltal()>thethet):
            i.set_5(1)




    lista = (finallist)
    listmid = []
    grouplist=[]
    for i in lista:

        if i.get_5()!=5:
            listmid .append(i)
        elif i.get_5() ==5:
            listmid .append(i)
            #print('q')
            #print(len(listmid))
            if len(listmid)>2:
                grouplist .append(listmid)
            else:
               #print('小于3',listmid[1].get_pos())
                pass
            listmid=[]


    gob_list=[]
    for i in grouplist:
        gl = GroupLine(i)
        gob_list.append(gl)
    gob_list1=[]
    for i in gob_list:
        if (i.pos1)and((i.pos2))and(i.pos3)and(i.pos4):
            gob_list1.append(i)
    glob_delt_list=[]
    for i in gob_list1:
        glob_delt_list . append((i.pos5-i.pos1))

    col = collections.Counter(glob_delt_list)
    minid =int(self.picture.shape[0]/550)
    if (int(col.most_common(1)[0][0]/4)> minid) and (int(col.most_common(1)[0][0]/4)< 20) :
        
        stdd  =int(col.most_common(1)[0][0]/4)
    elif (int(col.most_common(2)[0][0]/4)> minid) and (int(col.most_common(2)[0][0]/4)< 20) :
        stdd  =int(col.most_common(2)[0][0]/3)
    elif (int(col.most_common(3)[0][0]/4)> minid) and (int(col.most_common(3)[0][0]/4)< 20) :
        stdd  =int(col.most_common(3)[0][0]/3)
    else:
        stdd = 11
    gob_list2=[]
    for i in gob_list1:
        i.adjust(stdd)
        gob_list2.append(i)
    return  gob_list2          
            
    
class forme_pages(object):
    def __init__(self,insrument_dic):
        self.insrument_dic=insrument_dic
        self.w =int( insrument_dic[2][3].shape[1])
        self.limit = int(self.w*1.62)
        self.instrument_pages_dic={}
    def get_h(self,lista):
        count = 0
        w=30
        for i in lista:
            count+=i.shape[0]
            count+=w
        count =count+w
        return count 
    def got_1_1_pages_(self,instru_i):
        pagelist=[]
        instr = self.insrument_dic[instru_i]
        h = self.get_h(instr)
        items = len(instr)
        self.pages = int(h//self.limit +1)
        average =int( items//self.pages+1)
        #print(self.pages)
        
        page_counter = 0
        for pagi in range(self.pages):
            
            pagecontent = (np.ones((self.limit,self.w,3))*255).astype('int')
            memori = 30
            for row in range(average) :
                try:
                    dh = instr[page_counter*average+row].shape[0]
                    pagecontent[memori:memori+dh,:,:] =instr[page_counter*average+row]
                    memori+=dh
                    memori+=30
                except:
                    pass
            pagelist.append(pagecontent)
            page_counter+=1
        self.instrument_pages_dic[instru_i] =   pagelist 
        
    def got_all_inst(self):
        for i in self.insrument_dic:
            self.got_1_1_pages_(i)
                
                
    def save_image(self,path,i,j):
        A = self.instrument_pages_dic[i][j]
        cv2.imwrite(path+"\\istru_{}_page{}.jpg".format(i,j),A)
    
    def save_all(self):
        for i in self.insrument_dic:
            for j in range(len(self.instrument_pages_dic[i])):
                self.save_image("done",i,j)
        
        

def get_on_inst(score,insrument_dic,idx):
    one_inst_list =[]
    for i in [i for i in score.score_page]:
        p1 =score.score_page[i][idx].pos1
        p5 =score.score_page[i][idx].pos5
        middelta = p5-p1
        pia = score.picture_list[i][p1-int(2.3*middelta):p5+int(1.3*middelta),:,:]
        #plt.imshow(pia)
        #print(p1,p5)
        one_inst_list.append(pia)
    insrument_dic[idx] = one_inst_list
 
def getall_ins(score):
    insrument_dic={}
    for idx in range(len(score.score_page[4])):
        get_on_inst(score,insrument_dic,idx)
    return insrument_dic
import sys, fitz, os, datetime

def pyMuPDF_fitz(pdfPath, imagePath):
    startTime_pdf2img = datetime.datetime.now()#開始時(shí)間

    print("imagePath="+imagePath)
    pdfDoc = fitz.open(pdfPath)
    for pg in range(pdfDoc.pageCount):
        page = pdfDoc[pg]
        rotate = int(0)
        # 每個(gè)尺寸的縮放系數(shù)為1.3拣技,這將為我們生成分辨率提高2.6的圖像断箫。
        # 此處若是不做設(shè)置乏盐,默認(rèn)圖片大小為:792X612, dpi=96
        zoom_x = 4 #(1.33333333-->1056x816)   (2-->1584x1224)
        zoom_y = 4
        mat = fitz.Matrix(zoom_x, zoom_y).preRotate(rotate)
        pix = page.getPixmap(matrix=mat, alpha=False)

        if not os.path.exists(imagePath):#判斷存放圖片的文件夾是否存在
            os.makedirs(imagePath) # 若圖片文件夾不存在就創(chuàng)建

        pix.writePNG(imagePath+'/'+'%s.png' % pg)#將圖片寫入指定的文件夾內(nèi)

    endTime_pdf2img = datetime.datetime.now()#結(jié)束時(shí)間
    print('pdf2img時(shí)間=',(endTime_pdf2img - startTime_pdf2img).seconds)


主函數(shù)調(diào)用

from  help import Score,find5lines,Lines,Line,GroupLine,process_one,forme_pages,getall_ins,pyMuPDF_fitz
## 輸出pdf為圖片

pdfPath = 'orient_pdf/1171_2.0_A Cartoon Christmas.pdf'
imagePath = 'img_pdf/'
pyMuPDF_fitz(pdfPath, imagePath)

##使用Score類檢測五線
#導(dǎo)入樂譜圖片
score = Score()
score.upload_pic(r'img_pdf')
#對所有圖片操作
score.proc_all()
# 檢測分段是否正確
 for i in score.score_page:
    print(i,len(score.score_page[i]))
# 排版輸出成圖片(豎版)
insrument_dic=getall_ins(score)
FG = forme_pages(insrument_dic)
FG.got_all_inst()
FG.save_all()
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市妒蔚,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖幻林,帶你破解...
    沈念sama閱讀 217,542評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件终吼,死亡現(xiàn)場離奇詭異镀赌,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)际跪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評論 3 394
  • 文/潘曉璐 我一進(jìn)店門商佛,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人姆打,你說我怎么就攤上這事良姆。” “怎么了幔戏?”我有些...
    開封第一講書人閱讀 163,912評論 0 354
  • 文/不壞的土叔 我叫張陵玛追,是天一觀的道長。 經(jīng)常有香客問我,道長痊剖,這世上最難降的妖魔是什么韩玩? 我笑而不...
    開封第一講書人閱讀 58,449評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮陆馁,結(jié)果婚禮上找颓,老公的妹妹穿的比我還像新娘。我一直安慰自己叮贩,他們只是感情好叮雳,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著妇汗,像睡著了一般帘不。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上杨箭,一...
    開封第一講書人閱讀 51,370評論 1 302
  • 那天寞焙,我揣著相機(jī)與錄音,去河邊找鬼互婿。 笑死捣郊,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的慈参。 我是一名探鬼主播呛牲,決...
    沈念sama閱讀 40,193評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼驮配!你這毒婦竟也來了娘扩?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,074評論 0 276
  • 序言:老撾萬榮一對情侶失蹤壮锻,失蹤者是張志新(化名)和其女友劉穎琐旁,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體猜绣,經(jīng)...
    沈念sama閱讀 45,505評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡灰殴,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了掰邢。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片牺陶。...
    茶點(diǎn)故事閱讀 39,841評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖辣之,靈堂內(nèi)的尸體忽然破棺而出掰伸,到底是詐尸還是另有隱情,我是刑警寧澤召烂,帶...
    沈念sama閱讀 35,569評論 5 345
  • 正文 年R本政府宣布碱工,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏怕篷。R本人自食惡果不足惜历筝,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望廊谓。 院中可真熱鬧梳猪,春花似錦、人聲如沸蒸痹。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽叠荠。三九已至匿沛,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間榛鼎,已是汗流浹背逃呼。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留者娱,地道東北人抡笼。 一個(gè)月前我還...
    沈念sama閱讀 47,962評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像黄鳍,于是被迫代替她去往敵國和親推姻。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評論 2 354

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