victor@2: import sys victor@2: import cv2 victor@2: import numpy as np victor@2: import math victor@2: import copy victor@2: victor@2: from gamera.core import * victor@2: from gamera.toolkits.musicstaves import musicstaves_rl_roach_tatem victor@2: from gamera.toolkits.musicstaves import musicstaves_rl_fujinaga victor@2: from gamera.toolkits.musicstaves import stafffinder_miyao victor@2: from gamera.toolkits.musicstaves import stafffinder_dalitz victor@2: from gamera.toolkits.musicstaves import stafffinder_projections victor@2: from gamera.plugins import numpy_io victor@2: init_gamera() victor@2: victor@2: #import ossiafinder_dalitz victor@2: victor@2: def intersect(r1,r2): victor@2: """Returns the intersection of two rectangles""" victor@2: x1 = max(r1['x'], r2['x']) victor@2: y1 = max(r1['y'], r2['y']) victor@2: x2 = min(r1['x'] + r1['width'], r2['x'] + r2['width']) victor@2: y2 = min(r1['y'] + r1['height'], r2['y'] + r2['height']) victor@2: result = {"x": x1, "y": y1, "width": x2 - x1, "height": y2-y1} victor@2: result['area'] = result['width'] * result['height'] victor@2: return(result) victor@2: victor@2: def ydist(r1,r2): victor@2: """distance on y-axis between two non-interecting rectangles""" victor@2: top1 = r1['y'] victor@2: bottom1 = r1['y'] + r1['height'] victor@2: victor@2: top2 = r2['y'] victor@2: bottom2 = r2['y'] + r2['height'] victor@2: return(min(abs(top1-bottom2), abs(top2-bottom1))) victor@2: victor@2: victor@2: def show(img, factor=0.5): victor@2: """ show an image until the escape key is pressed victor@2: :param factor: scale factor (default 0.5, half size) victor@2: """ victor@2: if factor != 1.0: victor@2: img = cv2.resize(img, (0,0), fx=factor, fy=factor) victor@2: victor@2: cv2.imwrite('show.png',img) victor@2: # while(1): victor@2: # k = cv2.waitKey(0) victor@2: # if k==27: # Esc key to quit victor@2: # cv2.destroyAllWindows() victor@2: # exit() victor@2: # if k==32: # Space to stop victor@2: # cv2.destroyAllWindows() victor@2: # break victor@2: victor@2: victor@2: def max_staff_height(blob): victor@2: result = 0 victor@2: for staff in blob['staves']: victor@2: top = staff[0].y_list[0] victor@2: bottom = staff[-1].y_list[0] victor@2: result = max(result, bottom-top) victor@2: return(result) victor@2: victor@2: victor@2: def deskew(img): victor@2: """Deskews the given image based on lines detected with opencv's victor@2: HoughLines function.""" victor@2: print "Deskewing." victor@2: imgHeight, imgWidth, imgDepth = img.shape victor@2: img_gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) victor@2: img_edges = cv2.Canny(img_gray,50,150,apertureSize = 3) victor@2: minLineLength = int(imgWidth*0.5) victor@2: houghThresh = int(imgWidth*0.15) victor@2: maxLineGap = 10 victor@2: #lines = cv2.HoughLinesP(img_edges,1,np.pi/(180*1),houghThresh,minLineLength,maxLineGap) victor@2: lines = cv2.HoughLines(img_edges,1,np.pi/(180*3),houghThresh) victor@2: victor@2: angles = [] victor@2: for rho,theta in lines[0]: victor@2: angles.append((theta - (np.pi / 2))) victor@2: victor@2: a = np.cos(theta) victor@2: b = np.sin(theta) victor@2: x0 = a*rho victor@2: y0 = b*rho victor@2: x1 = int(x0 + imgWidth*(-b)) victor@2: y1 = int(y0 + imgWidth*(a)) victor@2: x2 = int(x0 - imgWidth*(-b)) victor@2: y2 = int(y0 - imgWidth*(a)) victor@2: #cv2.line(img,(x1,y1),(x2,y2),(255,0,0),2) victor@2: victor@2: middle = np.median(angles) victor@2: middle_deg = middle * (180/np.pi) victor@2: victor@2: rotation = cv2.getRotationMatrix2D((imgWidth/2,imgHeight/2),middle_deg,1.0) victor@2: victor@2: # rotate while inverted. the background is filled with zeros victor@2: # (black), this inversion means that ends up white victor@2: deskewed = cv2.bitwise_not(cv2.warpAffine(cv2.bitwise_not(img), victor@2: rotation, victor@2: (imgWidth,imgHeight)) victor@2: ) victor@2: return(deskewed) victor@2: victor@2: class PreOMR(object): victor@2: stavelineWidthThresh = 0.5 victor@2: victor@2: def __init__(self, infile, deskew=False): victor@2: self.debug = True victor@2: self.infile = infile victor@2: self.img = cv2.imread(self.infile) victor@2: if deskew: victor@2: self.img = deskew(self.img) victor@2: self.original = self.img victor@2: self.imgHeight, self.imgWidth, self.imgDepth = self.img.shape victor@2: self.img_gray = cv2.cvtColor(self.img,cv2.COLOR_BGR2GRAY) victor@2: if self.debug: victor@2: self.debug_img = self.img.copy() victor@2: ret2,self.img_binary = cv2.threshold(self.img_gray, victor@2: 0,255,cv2. victor@2: THRESH_BINARY+cv2. victor@2: THRESH_OTSU) victor@2: victor@2: def staffline_removal(self): victor@2: gamera_img = numpy_io.from_numpy(self.img) victor@2: #self.save('tmp.png') victor@2: #gamera_img = load_image('tmp.png') victor@2: victor@2: #ms = musicstaves_rl_roach_tatem.MusicStaves_rl_roach_tatem(gamera_img) victor@2: ms = musicstaves_rl_fujinaga.MusicStaves_rl_fujinaga(gamera_img) victor@2: cv2.imwrite('tmp.png', self.img) victor@2: ms.remove_staves(crossing_symbols = 'bars') victor@2: ms.image.save_PNG("tmpb.png") victor@2: staffless = cv2.imread("tmp.png", cv2.CV_LOAD_IMAGE_GRAYSCALE) victor@2: return(staffless) victor@2: victor@2: def find_staves(self, img): victor@2: gamera_img = numpy_io.from_numpy(img) victor@2: #sf = stafffinder_projections.StaffFinder_projections(gamera_img) victor@2: #sf.find_staves(follow_wobble=True,preprocessing=0) victor@2: #sf = stafffinder_dalitz.StaffFinder_dalitz(gamera_img) victor@2: sf = stafffinder_miyao.StaffFinder_miyao(gamera_img) victor@2: sf.find_staves() victor@2: #sf.find_staves(debug=2) victor@2: victor@2: staves = sf.get_skeleton() victor@2: # if self.debug: victor@2: # for i, staff in enumerate(staves): victor@2: # print "Staff %d has %d staves:" % (i+1, len(staff)) victor@2: # for j, line in enumerate(staff): victor@2: # print(" %d. line at (%d,%d)" % (j+1,line.left_x,line.y_list[0])) victor@2: return(staves) victor@2: victor@2: def find_blobs(self, img_binary): victor@2: """Find blobs in the given image, returned as a list of associative victor@2: lists containing various cheap metrics for each blob.""" victor@2: victor@2: blobs = [] victor@2: img_inverted = cv2.bitwise_not(img_binary) victor@2: contours, hierarchy = cv2.findContours(img_inverted,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE) victor@2: for (i, c) in enumerate(contours): victor@2: blob = {} victor@2: blobs.append(blob) victor@2: victor@2: blob['area'] = cv2.contourArea(c) victor@2: victor@2: m = cv2.moments(c) victor@2: if m['m00'] == 0: # When would this be true? victor@2: blob['x'] = 0 victor@2: blob['y'] = 0 victor@2: else: victor@2: blob['x'] = m['m10'] / m['m00'] victor@2: blob['y'] = m['m01'] / m['m00'] victor@2: victor@2: blob['contour'] = c victor@2: victor@2: rect = cv2.boundingRect(c) victor@2: blob['rect'] = {'x': rect[0], victor@2: 'y': rect[1], victor@2: 'width': rect[2], victor@2: 'height': rect[3] victor@2: } victor@2: blob['boundingRect'] = rect victor@2: blob['hull'] = hull = cv2.convexHull(c) victor@2: blob['hull_area'] = abs(cv2.contourArea(hull)) victor@2: blob['system'] = False victor@2: blob['parent'] = None victor@2: #blob['perimeter'] = perimeter = cv2.arcLength(c, True) victor@2: #blob['roundness'] = (perimeter * 0.282) / math.sqrt(area) victor@2: #(centre, axes, orientation) = cv2.fitEllipse(c) victor@2: #blob['orientation'] = orientation / 180 victor@2: #print "orientation: %f" % orientation victor@2: #blob['aspect'] = float(rect[1]) / float(rect[3]) victor@2: victor@2: return blobs victor@2: victor@2: def find_bars(self, system): victor@2: staffless = self.staffline_removal() victor@2: blobs = self.blobs victor@2: victor@2: """Finds the barlines in the system, given a binary image, a hash of victor@2: info about the system, and blobs detected in the image. victor@2: victor@2: """ victor@2: img = system['image'] victor@2: victor@2: for staff in system['staves']: victor@2: min_x = 0 victor@2: max_x = self.imgWidth victor@2: victor@2: for line in staff: victor@2: min_x = max(min_x, line.left_x) victor@2: max_x = min(max_x, line.left_x + len(line.y_list)) victor@2: victor@2: if self.debug: victor@2: for (i,y) in enumerate(line.y_list): victor@2: x = line.left_x + i victor@2: cv2.line(self.debug_img,(x,y),(x,y),(0,255,0),3) victor@2: victor@2: # cv2.line(img,(0,int(start)),(imgWidth,int(start)),(0,255,255),3) victor@2: # cv2.line(img,(0,int(stop)),(imgWidth,int(stop)),(0,255,255),3) victor@2: # cv2.line(img,(0,int(first_staveline)),(imgWidth,int(first_staveline)),(255,255,0),3) victor@2: # cv2.line(img,(0,int(last_staveline)),(imgWidth,int(last_staveline)),(255,255,0),3) victor@2: victor@2: # assuming single staff for now.. victor@2: barlines = [0] victor@2: system['barlines'] = barlines victor@2: victor@2: x_projection = [] victor@2: victor@2: for x in range(min_x, max_x): victor@2: first_staveline = staff[0].y_list[x - staff[0].left_x] victor@2: last_staveline = staff[-1].y_list[x - staff[-1].left_x] victor@2: victor@2: #print("Stavelines: first %d last %d" % (first_staveline, last_staveline)) victor@2: stave_height = last_staveline - first_staveline victor@2: victor@2: # mean distance between stavelines victor@2: avg_inter = float(stave_height) / float(len(staff)-1) victor@2: #print("avg_inter: %f" % (avg_inter,)) victor@2: victor@2: # where to look a bit above and below the stave for whitespace victor@2: # above a barline victor@2: gap = avg_inter / 2.0 victor@2: start = first_staveline - gap victor@2: stop = last_staveline + gap victor@2: victor@2: # above stave, stave and below stave victor@2: top = float(gap - victor@2: cv2.countNonZero(staffless[start:first_staveline, victor@2: x:x+1])) / float(gap) victor@2: mid = float(stave_height - victor@2: cv2.countNonZero(staffless[first_staveline:last_staveline, victor@2: x:x+1]) victor@2: ) / float(stave_height) victor@2: bot = float(gap - victor@2: cv2.countNonZero(staffless[last_staveline:stop, x:x+1]) victor@2: ) / float(gap) victor@2: x_projection.append((top,mid,bot)) victor@2: victor@2: barline_start = -1 victor@2: gap_dist = avg_inter/4 victor@2: gap_min = (avg_inter/float(stave_height)) * 0.3 victor@2: gap_tolerance = int(avg_inter/10) victor@2: victor@2: margin = int(avg_inter*2) victor@2: victor@2: for x in range(min_x+margin, max_x-margin): victor@2: (top,mid,bot) = x_projection[x - min_x] victor@2: #if self.debug: victor@2: #cv2.line(system['image'],(x,first_staveline),(x,int(first_staveline+((last_staveline-first_staveline)*mid))),(255,255,0),1) victor@2: victor@2: # found start of barline candidate victor@2: if top < 0.6 and bot < 0.6 and mid > 0.95: victor@2: if barline_start < 0: victor@2: barline_start = x victor@2: else: victor@2: if barline_start > 0: victor@2: # check there is nothing either side of 'barline' victor@2: barline_stop = x-1 victor@2: barline_mid = barline_stop - ((barline_stop - barline_start)/2) victor@2: #print("barline start %d stop %d mid %d" % (barline_start, barline_stop, barline_mid)) victor@2: left = int(max(0,barline_start-gap_dist)) victor@2: right = int(min(system['width']-1,(x-1)+gap_dist)) victor@2: victor@2: total = 0 victor@2: for i in range(left-gap_tolerance, left+gap_tolerance+1): victor@2: total = total + x_projection[i-min_x][1] victor@2: left_avg = total / ((gap_tolerance*2)+1) victor@2: victor@2: total = 0 victor@2: for i in range(right-gap_tolerance, right+gap_tolerance+1): victor@2: total = total + x_projection[i-min_x][1] victor@2: right_avg = total / ((gap_tolerance*2)+1) victor@2: victor@2: cv2.line(img,(left,first_staveline),(left,last_staveline),(255,0,255),1) victor@2: cv2.line(img,(right,first_staveline),(right,last_staveline),(255,0,255),1) victor@2: victor@2: if (left_avg <= gap_min and right_avg <= gap_min): victor@2: #print("success: left_avg %f right_avg %f" % (left_avg, right_avg)) victor@2: cv2.line(img,(barline_mid,first_staveline),(barline_mid,last_staveline),(255,0,0),3) victor@2: barlines.append(barline_mid) victor@2: else: victor@2: #print("fail: left_avg %f right_avg %f" % (left_avg, right_avg)) victor@2: cv2.line(img,(barline_mid,first_staveline),(barline_mid,last_staveline),(0,255,0),3) victor@2: #show(img) victor@2: barline_start = -1 victor@2: (x1, y1, x2, y2) = system['location'] victor@2: #show(system['image'][y1:y2, x1:x2]) victor@2: victor@2: def extract_bars(self, system, blobs): victor@2: """Given information about a system (including identified barlines), victor@2: and all the blobs on a page returns a list of bars in the system, victor@2: each an associative array containing image and location. victor@2: victor@2: """ victor@2: victor@2: img = system['image'] victor@2: victor@2: barlines = system['barlines'] victor@2: victor@2: result = [] victor@2: victor@2: for i in range(0,len(barlines)): victor@2: barstart = barlines[i] victor@2: if i == (len(barlines)-1): victor@2: barstop = system['width'] victor@2: else: victor@2: barstop = barlines[i+1] victor@2: #print("barstart %d barstop %d" % (barstart, barstop)) victor@2: contours = [system['contour']] victor@2: x1 = barstart victor@2: y1 = system['location'][1] victor@2: x2 = barstop victor@2: y2 = system['location'][3] victor@2: h = y2 - y1 victor@2: w = x2 - x1 victor@2: #print("height %d width %d" % (h, w)) victor@2: for blob in blobs: victor@2: if blob['parent'] == system: victor@2: if blob['rect']['x'] >= barstart and blob['rect']['x'] + blob['rect']['width'] <= barstop: victor@2: contours.append(blob['contour']) victor@2: victor@2: mask = np.zeros((self.imgHeight,self.imgWidth,1), np.uint8) victor@2: victor@2: cv2.drawContours(mask, contours, -1, 255, -1); victor@2: victor@2: inv = cv2.bitwise_not(img) victor@2: dest = cv2.bitwise_and(inv,inv,mask = mask) victor@2: dest = cv2.bitwise_not(dest) victor@2: img_bar = dest[y1:y2, x1:x2] victor@2: bar = {'image': img_bar, victor@2: 'page': dest, victor@2: 'location': [x1,y1,x2,y2] victor@2: } victor@2: result.append(bar) victor@2: #show(img_bar) victor@2: return(result) victor@2: victor@2: victor@2: victor@2: def find_staveblobs(self, cutstaves=False,img=None): victor@2: if img == None: victor@2: img = self.img victor@2: img_binary = self.img_binary victor@2: else: victor@2: img_gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) victor@2: ret2,img_binary = cv2.threshold(img_gray, victor@2: 0,255,cv2. victor@2: THRESH_BINARY+cv2. victor@2: THRESH_OTSU) victor@2: victor@2: staves = self.find_staves(img) victor@2: blobs = self.find_blobs(img_binary) victor@2: victor@2: staveblobs = [] victor@2: otherblobs = [] victor@2: victor@2: if self.debug: victor@2: for staff in staves: victor@2: for line in staff: victor@2: y = line.y_list[0] victor@2: cv2.line(self.debug_img,(0,y),(self.imgWidth,y),(0,255,0),3) victor@2: for blob in blobs: victor@2: rect = blob['rect'] victor@2: blob['staves'] = [] victor@2: blob['system'] = False victor@2: # large enough to contain a stave? victor@2: blob['large'] = False victor@2: if rect['width'] > (self.imgWidth * self.stavelineWidthThresh): victor@2: blob['large'] = True victor@2: if self.debug: victor@2: cv2.drawContours(self.debug_img,[blob['contour']],-1, (0, 255,255),2) victor@2: for staff in staves: victor@2: inside = True victor@2: for staveline in staff: victor@2: leftmost = staveline.y_list[0] victor@2: # all stafflines have to be in blob victor@2: if leftmost < rect['y'] or leftmost > (rect['y'] + rect['height']): victor@2: inside = False victor@2: break victor@2: if inside: victor@2: blob['system'] = True victor@2: blob['staves'].append(staff) victor@2: if blob['system']: victor@2: staveblobs.append(blob) victor@2: print("found system with %d staves" % len(blob['staves'])) victor@2: if self.debug: victor@2: cv2.drawContours(self.debug_img,[blob['contour']],-1, (0, 0,255), 2) victor@2: else: victor@2: otherblobs.append(blob) victor@2: victor@2: return(staveblobs, otherblobs) victor@2: victor@2: def find_systems(self): victor@2: img = self.img_binary victor@2: #print "finding staves" victor@2: (staveblobs, otherblobs) = self.find_staveblobs() victor@2: #print("found %d staves" % (len(staveblobs),)) victor@2: blobs = staveblobs + otherblobs victor@2: self.blobs = blobs victor@2: # systems = [] victor@2: systems = staveblobs victor@2: victor@2: # attach disconnected bits in bounding box victor@2: tidied = 0 victor@2: for blob in blobs: victor@2: if not blob['system']: victor@2: blob['parent'] = None victor@2: for system in systems: victor@2: rect = intersect(system['rect'], blob['rect']) victor@2: if (rect['height'] > 0 and rect['width'] > 0): victor@2: # Biggest intersection wins victor@2: if (blob['parent'] == None) or (rect['area'] > blob['intersection']['area']): victor@2: blob['parent'] = system victor@2: blob['intersection'] = rect victor@2: victor@2: # Just assign to closest bounding rectangle on y-axis victor@2: if blob['parent'] == None: victor@2: mindist = None victor@2: for system in systems: victor@2: dist = ydist(system['rect'], blob['rect']) victor@2: if mindist == None or mindist > dist: victor@2: blob['parent'] = system victor@2: mindist = dist victor@2: if blob['parent'] == None: victor@2: print "wtf" victor@2: else: victor@2: tidied = tidied + 1 victor@2: #print "tidied %d" % tidied victor@2: victor@2: # create new image for systems victor@2: for system in systems: victor@2: contours = [system['contour']] victor@2: x1 = system['rect']['x'] victor@2: y1 = system['rect']['y'] victor@2: x2 = system['rect']['x'] + system['rect']['width'] victor@2: y2 = system['rect']['y'] + system['rect']['height'] victor@2: victor@2: children = 0 victor@2: for blob in blobs: victor@2: if blob['parent'] == system: victor@2: children = children + 1 victor@2: contours.append(blob['contour']) victor@2: # include blob in image size/location victor@2: x1 = min(x1, blob['rect']['x']) victor@2: y1 = min(y1, blob['rect']['y']) victor@2: x2 = max(x2, blob['rect']['x'] + blob['rect']['width']) victor@2: y2 = max(y2, blob['rect']['y'] + blob['rect']['height']) victor@2: victor@2: #print("found %d children" % children) victor@2: victor@2: mask = np.zeros((self.imgHeight,self.imgWidth,1), np.uint8) victor@2: victor@2: cv2.drawContours(mask, contours, -1, 255, -1); victor@2: #src = img[x1:y1, x2:y2] victor@2: #srcMask = mask[y1:y2, x1:x2] victor@2: kernel = np.ones((4,4),np.uint8) victor@2: mask=cv2.dilate(mask,kernel,iterations=3) victor@2: victor@2: inv = cv2.bitwise_not(self.img) victor@2: dest = cv2.bitwise_and(inv,inv,mask = mask) victor@2: dest = cv2.bitwise_not(dest) victor@2: victor@2: (h,w,d) = dest.shape victor@2: system['image'] = dest victor@2: system['location'] = (x1, y1, x2, y2) victor@2: system['height'] = h victor@2: system['width'] = w victor@2: victor@2: min_x = self.imgWidth victor@2: victor@2: for staff in system['staves']: victor@2: for line in staff: victor@2: min_x = min(min_x, line.left_x) victor@2: victor@2: system['stave_min_x'] = min_x victor@2: victor@2: #self.find_bars(system) victor@2: #system['bar_images'] = self.extract_bars(system, blobs) victor@2: if self.debug: victor@2: cv2.imwrite('debug.png', self.debug_img) victor@2: return(systems,blobs) victor@2: victor@2: def blob_image(self,img,blob): victor@2: r = blob['rect'] victor@2: y1 = r['y'] victor@2: x1 = r['x'] victor@2: y2 = r['y'] + r['height'] victor@2: x2 = r['x'] + r['width'] victor@2: return(img[y1:y2, x1:x2]) victor@2: victor@2: # def join_broken_staves(self): victor@2: # img = self.img victor@2: # (staveblobs, otherblobs) = self.find_staveblobs() victor@2: # for i in range(0, len(staveblobs)-1): victor@2: # for j in range(i, len(staveblobs)): victor@2: # a = staveblobs[i] victor@2: # b = staveblobs[j] victor@2: # atop = a['rect']['x'] victor@2: # abot = a['rect']['x'] + a['rect']['height'] victor@2: # btop = b['rect']['x'] victor@2: # bbot = b['rect']['x'] + b['rect']['height'] victor@2: # if atop > btop and a victor@2: victor@2: victor@2: def remove_ossia(self): victor@2: img = self.img victor@2: victor@2: ossia_mask = np.ones(self.img.shape[:2], dtype="uint8") * 255 victor@2: victor@2: (staveblobs, otherblobs) = self.find_staveblobs() victor@2: staff_heights = map(lambda s: max_staff_height(s), staveblobs) victor@2: staff_height = max(staff_heights) victor@2: height_thresh = staff_height * 0.75 victor@2: victor@2: ossias = filter(lambda s: max_staff_height(s) < height_thresh, staveblobs) victor@2: victor@2: print("blobs %d/%d" % (len(staveblobs), len(otherblobs))) victor@2: #staves = self.find_staves(img) victor@2: victor@2: working_img = img.copy() victor@2: victor@2: for blob in staveblobs: victor@2: miny = self.imgHeight victor@2: for staff in blob['staves']: victor@2: staffline = staff[0] victor@2: miny = min(min(staffline.y_list),miny) victor@2: cv2.line(working_img, (0,miny-4), (self.imgWidth,miny-4), (255,255,255), 4) victor@2: victor@2: cv2.imwrite('test.png', working_img) victor@2: victor@2: (staveblobs, otherblobs) = self.find_staveblobs(img=working_img) victor@2: print("blobs %d/%d" % (len(staveblobs), len(otherblobs))) victor@2: i = 0 victor@2: # for blob in otherblobs[112:113]: victor@2: for blob in otherblobs: victor@2: if blob['rect']['width'] < (self.imgWidth / 50): victor@2: continue victor@2: # if blob['rect']['width'] > (self.imgWidth / 2): victor@2: # continue victor@2: victor@2: src = self.img victor@2: mask = np.zeros((self.imgHeight,self.imgWidth,1), np.uint8) victor@2: cv2.drawContours(mask, [blob['contour']], -1, (255,255,255), -1); victor@2: inv = cv2.bitwise_not(src) victor@2: dest = cv2.bitwise_and(inv,inv,mask = mask) victor@2: dest = cv2.bitwise_not(dest) victor@2: cropped = self.blob_image(dest, blob) victor@2: victor@2: gi = numpy_io.from_numpy(cropped) victor@2: #sf = stafffinder_projections.StaffFinder_projections(gi) victor@2: #sf = stafffinder_miyao.StaffFinder_miyao(gi) victor@2: sf = stafffinder_dalitz.StaffFinder_dalitz(gi) victor@2: sf.find_staves() victor@2: staves = sf.get_skeleton() victor@2: victor@2: if (len(staves) > 0): victor@2: maxlines = max(map(len, staves)) victor@2: else: victor@2: maxlines = 0 victor@2: if maxlines >= 4: victor@2: print("aha ossia with %d lines" % (maxlines,)) victor@2: ossias.append(blob) victor@2: for ossia in ossias: victor@2: if self.debug: victor@2: fn = 'removed_%d.png' % i victor@2: cv2.imwrite(fn, cropped) victor@2: i = i + 1 victor@2: cv2.drawContours(ossia_mask, [ossia['contour']], -1, 0, -1) victor@2: victor@2: # erode a little to get rid of 'ghosting' around ossia victor@2: kernel = np.ones((4,4),np.uint8) victor@2: ossia_mask=cv2.erode(ossia_mask,kernel,iterations=4) victor@2: victor@2: #cv2.imwrite('posterode.png', mask) victor@2: victor@2: result = img.copy() victor@2: inverted = cv2.bitwise_not(result) victor@2: result = cv2.bitwise_or(inverted,inverted,mask=ossia_mask) victor@2: result = cv2.bitwise_not(result) victor@2: victor@2: if self.debug: victor@2: cv2.imwrite('debug.png', self.debug_img) victor@2: victor@2: self.img = result victor@2: victor@2: def split_movements(self, outfileA, outfileB): victor@2: # 2% of page width victor@2: indentThresh = 0.02 * self.imgWidth victor@2: victor@2: systems, blobs = self.find_systems() victor@2: victor@2: # Top - down order victor@2: systems = sorted(systems, key=lambda system: system['rect']['y']) victor@2: victor@2: xs = [] victor@2: for system in systems: victor@2: xs.append(system['stave_min_x']) victor@2: threshold = min(xs) + indentThresh victor@2: victor@2: # Skip the first one, we don't split if the movement starts at top victor@2: # of page victor@2: found = None victor@2: for i in range(0,len(systems)): victor@2: #cv2.imwrite("system%d.png" %i, systems[i]['image']) victor@2: if xs[i] > threshold: victor@2: if found != None: victor@2: print "Oops, more than one movement found." victor@2: found = i victor@2: print("New movement at system %d" % (i+1)) victor@2: victor@2: if (found == 0): victor@2: self.save_systems(outfileA, systems) victor@2: else: victor@2: self.save_systems(outfileA, systems[:found]) victor@2: self.save_systems(outfileB, systems[found:]) victor@2: return(found) victor@2: victor@2: def save(self, outfile): victor@2: cv2.imwrite(outfile, self.img) victor@2: victor@2: def save_systems(self, outfile, systems): victor@2: print "saving %s" % outfile victor@2: contours = [] victor@2: for system in systems: victor@2: contours.append(system['contour']) victor@2: victor@2: for blob in self.blobs: victor@2: if blob['parent'] == system: victor@2: contours.append(blob['contour']) victor@2: victor@2: mask = np.zeros((self.imgHeight,self.imgWidth,1), np.uint8) victor@2: victor@2: cv2.drawContours(mask, contours, -1, 255, -1); victor@2: victor@2: kernel = np.ones((4,4),np.uint8) victor@2: mask=cv2.dilate(mask,kernel,iterations=1) victor@2: victor@2: inv = cv2.bitwise_not(self.img) victor@2: dest = cv2.bitwise_and(inv,inv,mask = mask) victor@2: dest = cv2.bitwise_not(dest) victor@2: cv2.imwrite(outfile,dest)