-
Notifications
You must be signed in to change notification settings - Fork 5
/
staffLine.py
86 lines (77 loc) · 3.18 KB
/
staffLine.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
from skimage.transform import hough_line, hough_line_peaks
import numpy as np
from scipy import stats
from skimage.draw import line
import skimage.io as io
def staffLineRemoval(thresholdedImg, thicknessThresholdFraction):
img = np.copy(thresholdedImg) # for convinience :)
height, width = img.shape
# Invert the input binary image
imgBinary = 255 - img
# apply hough lines to detect stafflines
hspace, angles, dists = hough_line(imgBinary)
hspace, angles, dists = hough_line_peaks(hspace, angles, dists)
new_dists = []
for i in range(len(dists)):
if abs(angles[i] - np.pi / 2) < 0.02:
new_dists.append(dists[i])
dists = new_dists
staffLines = np.sort(np.round(dists).astype('int32'))
# find most common black pixel run length (white pixel run length in binary image due to inversion)
# This should correspond to staff line thickness
staffLineThickness = verticalRunLengthMode(imgBinary, 255, width, height)
# TODO: check whether the addition is needed
staffLineSpacing = verticalRunLengthMode(imgBinary, 0, width, height)
threshold = staffLineSpacing / 2 # TODO: check whether needed
for staffLineRow in staffLines:
for x in range(width-1, 0, -1):
if img[staffLineRow, x] != 0:
for j in range(1, round(threshold/2)):
if img[staffLineRow + j, x] == 0:
staffLineRow = staffLineRow + j
break
if img[staffLineRow - j, x] == 0:
staffLineRow = staffLineRow - j
break
verticalThresholdResult = testVerticalThreshold(
img, x, staffLineRow, staffLineThickness*thicknessThresholdFraction)
if(verticalThresholdResult[0]):
rr, cc = line(
verticalThresholdResult[1], x, verticalThresholdResult[2], x)
img[rr, cc] = 255
# TODO: fix with morphology the broken objects
return (img, staffLines, staffLineSpacing, staffLineThickness)
# Returns the mode vertical run length of the given colour in the input image
def verticalRunLengthMode(img, colour, width, height):
runLengths = []
for x in range(0, width):
inColour = False
currentRun = 0
for y in range(0, height):
if (img[y, x] == colour):
if (inColour):
currentRun = currentRun + 1
else:
currentRun = 1
inColour = True
else:
if (inColour):
runLengths.append(currentRun)
inColour = False
return int(stats.mode(runLengths)[0][0])
# to check whether the point in the staff line coincide with a note
# providing a threshold for the thickness of the stafflines
def testVerticalThreshold(img, x, y, threshold):
upperY = y
lowerY = y
while (upperY >= 0):
if (img[upperY-1, x] == 0):
upperY -= 1
else:
break
while (lowerY <= len(img)):
if (img[lowerY+1, x] == 0):
lowerY += 1
else:
break
return (lowerY - upperY <= threshold), upperY, lowerY