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()