def segment_image(img, max_scale=defaults.CC_SCALE_MAX, min_scale=defaults.CC_SCALE_MIN): (h, w) = img.shape[:2] if arg.boolean_value('verbose'): print 'Segmenting ' + str(h) + 'x' + str(w) + ' image.' #create gaussian filtered and unfiltered binary images binary_threshold = arg.integer_value( 'binary_threshold', default_value=defaults.BINARY_THRESHOLD) if arg.boolean_value('verbose'): print 'binarizing images with threshold value of ' + str( binary_threshold) binary = clean.binarize(img, threshold=binary_threshold) binary_average_size = cc.average_size(binary) if arg.boolean_value('verbose'): print 'average cc size for binaryized grayscale image is ' + str( binary_average_size) ''' The necessary sigma needed for Gaussian filtering (to remove screentones and other noise) seems to be a function of the resolution the manga was scanned at (or original page size, I'm not sure). Assuming 'normal' page size for a phonebook style Manga is 17.5cmx11.5cm (6.8x4.5in). A scan of 300dpi will result in an image about 1900x1350, which requires a sigma of 1.5 to 1.8. I'm encountering many smaller images that may be nonstandard scanning dpi values or just smaller magazines. Haven't found hard info on this yet. They require sigma values of about 0.5 to 0.7. I'll therefore (for now) just calculate required (nonspecified) sigma as a linear function of vertical image resolution. ''' sigma = (0.8 / 676.0) * float(h) - 0.9 sigma = arg.float_value('sigma', default_value=sigma) if arg.boolean_value('verbose'): print 'Applying Gaussian filter with sigma (std dev) of ' + str(sigma) gaussian_filtered = scipy.ndimage.gaussian_filter(img, sigma=sigma) gaussian_binary = clean.binarize(gaussian_filtered, threshold=binary_threshold) #Draw out statistics on average connected component size in the rescaled, binary image average_size = cc.average_size(gaussian_binary) if arg.boolean_value('verbose'): print 'Binarized Gaussian filtered image average cc size: ' + str( average_size) max_size = average_size * max_scale min_size = average_size * min_scale #primary mask is connected components filtered by size mask = cc.form_mask(gaussian_binary, max_size, min_size) #secondary mask is formed from canny edges canny_mask = clean.form_canny_mask(gaussian_filtered, mask=mask) #final mask is size filtered connected components on canny mask final_mask = cc.form_mask(canny_mask, max_size, min_size) #apply mask and return images cleaned = cv2.bitwise_not(final_mask * binary) text_only = cleaned2segmented(cleaned, average_size) #if desired, suppress furigana characters (which interfere with OCR) suppress_furigana = arg.boolean_value('furigana') if suppress_furigana: if arg.boolean_value('verbose'): print 'Attempting to suppress furigana characters which interfere with OCR.' furigana_mask = furigana.estimate_furigana(cleaned, text_only) furigana_mask = np.array(furigana_mask == 0, 'B') cleaned = cv2.bitwise_not(cleaned) * furigana_mask cleaned = cv2.bitwise_not(cleaned) text_only = cleaned2segmented(cleaned, average_size) (text_like_areas, nontext_like_areas) = filter_text_like_areas(img, segmentation=text_only, average_size=average_size) if arg.boolean_value('verbose'): print '**********there are ' + str( len(text_like_areas)) + ' text like areas total.' text_only = np.zeros(img.shape) cc.draw_bounding_boxes(text_only, text_like_areas, color=(255), line_size=-1) if arg.boolean_value('debug'): text_only = 0.5 * text_only + 0.5 * img #text_rows = 0.5*text_rows+0.5*gray #text_colums = 0.5*text_columns+0.5*gray #text_only = filter_text_like_areas(img, segmentation=text_only, average_size=average_size) segmented_image = np.zeros((h, w, 3), np.uint8) segmented_image[:, :, 0] = img segmented_image[:, :, 1] = text_only segmented_image[:, :, 2] = text_only return segmented_image
def segment_image(img, max_scale=defaults.CC_SCALE_MAX, min_scale=defaults.CC_SCALE_MIN): (h,w)=img.shape[:2] if arg.boolean_value('verbose'): print 'Segmenting ' + str(h) + 'x' + str(w) + ' image.' #create gaussian filtered and unfiltered binary images binary_threshold = arg.integer_value('binary_threshold',default_value=defaults.BINARY_THRESHOLD) if arg.boolean_value('verbose'): print 'binarizing images with threshold value of ' + str(binary_threshold) binary = clean.binarize(img,threshold=binary_threshold) binary_average_size = cc.average_size(binary) if arg.boolean_value('verbose'): print 'average cc size for binaryized grayscale image is ' + str(binary_average_size) ''' The necessary sigma needed for Gaussian filtering (to remove screentones and other noise) seems to be a function of the resolution the manga was scanned at (or original page size, I'm not sure). Assuming 'normal' page size for a phonebook style Manga is 17.5cmx11.5cm (6.8x4.5in). A scan of 300dpi will result in an image about 1900x1350, which requires a sigma of 1.5 to 1.8. I'm encountering many smaller images that may be nonstandard scanning dpi values or just smaller magazines. Haven't found hard info on this yet. They require sigma values of about 0.5 to 0.7. I'll therefore (for now) just calculate required (nonspecified) sigma as a linear function of vertical image resolution. ''' sigma = (0.8/676.0)*float(h)-0.9 sigma = arg.float_value('sigma',default_value=sigma) if arg.boolean_value('verbose'): print 'Applying Gaussian filter with sigma (std dev) of ' + str(sigma) gaussian_filtered = scipy.ndimage.gaussian_filter(img, sigma=sigma) gaussian_binary = clean.binarize(gaussian_filtered,threshold=binary_threshold) #Draw out statistics on average connected component size in the rescaled, binary image average_size = cc.average_size(gaussian_binary) if arg.boolean_value('verbose'): print 'Binarized Gaussian filtered image average cc size: ' + str(average_size) max_size = average_size*max_scale min_size = average_size*min_scale #primary mask is connected components filtered by size mask = cc.form_mask(gaussian_binary, max_size, min_size) #secondary mask is formed from canny edges canny_mask = clean.form_canny_mask(gaussian_filtered, mask=mask) #final mask is size filtered connected components on canny mask final_mask = cc.form_mask(canny_mask, max_size, min_size) #apply mask and return images cleaned = cv2.bitwise_not(final_mask * binary) text_only = cleaned2segmented(cleaned, average_size) #if desired, suppress furigana characters (which interfere with OCR) suppress_furigana = arg.boolean_value('furigana') if suppress_furigana: if arg.boolean_value('verbose'): print 'Attempting to suppress furigana characters which interfere with OCR.' furigana_mask = furigana.estimate_furigana(cleaned, text_only) furigana_mask = np.array(furigana_mask==0,'B') cleaned = cv2.bitwise_not(cleaned)*furigana_mask cleaned = cv2.bitwise_not(cleaned) text_only = cleaned2segmented(cleaned, average_size) (text_like_areas, nontext_like_areas) = filter_text_like_areas(img, segmentation=text_only, average_size=average_size) if arg.boolean_value('verbose'): print '**********there are ' + str(len(text_like_areas)) + ' text like areas total.' text_only = np.zeros(img.shape) cc.draw_bounding_boxes(text_only, text_like_areas,color=(255),line_size=-1) if arg.boolean_value('debug'): text_only = 0.5*text_only + 0.5*img #text_rows = 0.5*text_rows+0.5*gray #text_colums = 0.5*text_columns+0.5*gray #text_only = filter_text_like_areas(img, segmentation=text_only, average_size=average_size) segmented_image = np.zeros((h,w,3), np.uint8) segmented_image[:,:,0] = img segmented_image[:,:,1] = text_only segmented_image[:,:,2] = text_only return segmented_image