五线定位&分谱脚本(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()#开始时间

    print("imagePath="+imagePath)
    pdfDoc = fitz.open(pdfPath)
    for pg in range(pdfDoc.pageCount):
        page = pdfDoc[pg]
        rotate = int(0)
        # 每个尺寸的缩放系数为1.3,这将为我们生成分辨率提高2.6的图像。
        # 此处若是不做设置,默认图片大小为: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) # 若图片文件夹不存在就创建

        pix.writePNG(imagePath+'/'+'%s.png' % pg)#将图片写入指定的文件夹内

    endTime_pdf2img = datetime.datetime.now()#结束时间
    print('pdf2img时间=',(endTime_pdf2img - startTime_pdf2img).seconds)


主函数调用

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类检测五线
#导入乐谱图片
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()
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,793评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,567评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,342评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,825评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,814评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,680评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,033评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,687评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,175评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,668评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,775评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,419评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,020评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,206评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,092评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,510评论 2 343

推荐阅读更多精彩内容