def test_find_sudoku_sqare(): pic_file_path = '../resource/example_pics/sample14.dataset.jpg' gray_pic_array = cv2.imread(pic_file_path, 0) color_pic_array = cv2.imread(pic_file_path) gray_pic_array = cv2_helper.resize_with_fixed_height(gray_pic_array) color_pic_array = cv2_helper.resize_with_fixed_height(color_pic_array) # threshed_pic_array = cv2.adaptiveThreshold(gray_pic_array,WHITE, # cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY_INV, 19, 2) ''' I've tried 3,3 19,2, 5,5 9,2''' threshed_pic_array = cv2.adaptiveThreshold(gray_pic_array,WHITE, cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY_INV, blockSize=5, C=2) # cv2_helper.show_pic(color_pic_array) cv2_helper.show_pic(threshed_pic_array) max_contour = find_sudoku_sqare(threshed_pic_array) cv2_helper.show_contours_in_pic(color_pic_array, [max_contour])
def find_sudoku_number_binary_arr(gray_pic_arr): ''' Find all numbers from a picture in which there is a soduku puzzle. The number form is a binary numpy.array in which number parts are 1, the others are 0. ''' ''' notice: the threshold_value is the key, if it directly impact the binary matrix. ''' threshed_pic_array = cv2_helper.threshold_white_with_mean_percent(gray_pic_arr,0.8) cv2_helper.show_pic(threshed_pic_array) square = find_max_square(threshed_pic_array) # cv2_helper.show_contours_in_pic(threshed_pic_array, [square]) square_rect=cv2.boundingRect(square) number_rects = cv2_helper.Rect.cal_split_ragion_rects(square_rect, 9, 9) # cv2_helper.show_rects_in_pic(gray_pic_arr, number_rects) binary_pic = numpy_helper.transfer_values_quickly(threshed_pic_array, {BLACK:0, WHITE:1}) number_binary_ragions = map(lambda c: cv2_helper.get_rect_ragion_with_rect(binary_pic, c), number_rects) number_binary_ragions = map(remove_border, number_binary_ragions) non_empty_indexs, number_binary_ragions = get_nonzero_ragions_and_indexs(number_binary_ragions) # indexs.pp() # cv2_helper.show_same_size_ragions_as_pic(number_binary_ragions, 9) number_binary_ragions = map(remove_margin, number_binary_ragions) number_binary_ragions = map(enlarge, number_binary_ragions) # cv2_helper.show_pic(threshed_pic_array) # cv2_helper.show_same_size_ragions_as_pic(number_binary_ragions, 9) return number_binary_ragions, non_empty_indexs
def remove_horizontal_lines(gray_pic): kernely = cv2.getStructuringElement(cv2.MORPH_RECT,(4,1)) # dy = gray_pic dy = cv2.Sobel(gray_pic,cv2.CV_16S,0,1) dy = cv2.convertScaleAbs(dy) cv2.normalize(dy,dy,0,255,cv2.NORM_MINMAX) ret,close = cv2.threshold(dy,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU) close = cv2.morphologyEx(close,cv2.MORPH_DILATE,kernely, iterations = 1) # close = cv2.morphologyEx(close,cv2.MORPH_OPEN,kernely, iterations = 1) contour, hier = cv2.findContours(close,cv2.MORPH_CLOSE,cv2.CHAIN_APPROX_SIMPLE) # contour = cv2_helper.find_contours(close, accuracy_percent_with_perimeter=0.001) for cnt in contour: x,y,w,h = cv2.boundingRect(cnt) if w/h > 10: cv2.drawContours(close,[cnt],0,255,-1) cv2.drawContours(gray_pic,[cnt],0,255,-1) else: cv2.drawContours(close,[cnt],0,0,-1) close = cv2.morphologyEx(close,cv2.MORPH_DILATE,None,iterations = 2) closey = close.copy() cv2_helper.show_pic(close) return gray_pic
def remove_vertical_lines(gray_pic): dx = cv2.Sobel(gray_pic,cv2.CV_16S,1,0) # dx = cv2.Sobel(gray_pic,cv2.CV_32F,1,0) dx = cv2.convertScaleAbs(dx) cv2.normalize(dx,dx,0,255,cv2.NORM_MINMAX) cv2_helper.show_pic(dx) # ret,close = cv2.threshold(dx,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU) # # close = cv2.adaptiveThreshold(dx,255, # # cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY_INV, blockSize=3, C=2) close = dx kernelx = cv2.getStructuringElement(cv2.MORPH_RECT,(1,4)) close = cv2.morphologyEx(close,cv2.MORPH_DILATE,kernelx,iterations = 1) # close = cv2.morphologyEx(close,cv2.MORPH_CLOSE,kernelx,iterations = 1) # close = cv2.morphologyEx(close,cv2.MORPH_GRADIENT,kernelx,iterations = 1) cv2_helper.show_pic(close) # contours, hier = cv2.findContours(close,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE) contours, hier = cv2.findContours(close,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE) # contours = cv2_helper.find_contours(close, None, 0.1) len(contours).pp() def filter_func(contour): x,y,w,h = cv2.boundingRect(contour) return h/w > 9 contours = filter(filter_func, contours) len(contours).pp() mask = cv2_helper.Image.generate_mask(gray_pic.shape) mask = cv2_helper.Image.fill_contours(mask,contours) cv2_helper.show_pic(mask) # cv2_helper.show_contours_in_color_pic(mask, contours) # for cnt in contours: # x,y,w,h = cv2.boundingRect(cnt) # if h/w > 5: # cv2.drawContours(close,[cnt],0,255,-1) # cv2.drawContours(gray_pic,[cnt],0,255,-1) # else: # cv2.drawContours(close,[cnt],0,0,-1) # close = cv2.morphologyEx(close,cv2.MORPH_CLOSE,None,iterations = 2) # closex = close.copy() # cv2_helper.show_pic(gray_pic) return gray_pic
def show_square(pic_file_path): ''' 7, 11 get wrong number, 8 clip too much, 9, 12, 13, 14 get more number, 7 is so special, put it at last 8 is almost ok ''' pic_file_path = '../resource/example_pics/sample01.dataset.jpg' pic_file_path.pp() gray_pic_array = cv2.imread(pic_file_path, 0) color_pic_array = cv2.imread(pic_file_path) gray_pic_array = cv2_helper.Image.resize_keeping_ratio_by_height(gray_pic_array) color_pic_array = cv2_helper.Image.resize_keeping_ratio_by_height(color_pic_array) # threshed_pic_array = cv2.adaptiveThreshold(gray_pic_array,WHITE, # cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY_INV, 19, 2) threshed_pic_array = cv2.adaptiveThreshold(gray_pic_array,WHITE, cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY_INV, blockSize=7, C=2) max_contour = find_sudoku_sqare(threshed_pic_array) max_contour.pp() cv2_helper.show_contours_in_pic(color_pic_array, [max_contour]) def warp_square(pic_array, approximated_square): ''' let the approximated_square become a true square. ''' square_rect = cv2.boundingRect(approximated_square) square_rect = cv2_helper.Rect.adjust_to_minimum(square_rect) # square_rect_contour = cv2_helper.rect_to_contour(square_rect) # approximated_square.pp() # square_rect_contour.pp() # approximated_square.shape is (4,1,2) approximated_square_float = numpy.float32(approximated_square.copy()) approximated_square_float = cv2_helper.Quadrilateral.vertices(approximated_square_float) # square_rect_contour_float = numpy.float32(square_rect_contour.copy()) square_rect_contour_float = numpy.float32(cv2_helper.Rect.vertices(square_rect)) retval = cv2.getPerspectiveTransform(approximated_square_float,square_rect_contour_float) dsize = pic_array.shape[::-1] warp = cv2.warpPerspective(pic_array,retval,dsize) return warp, square_rect # four_endpoints = cv2_helper.Quadrilateral.vertices(max_contour) # # top_points = cv2_helper.Points.cal_step_points(four_endpoints[:2], 10) # internal_points = cv2_helper.Points.cal_internal_points(four_endpoints,10,10) # cv2_helper.Image.show_points_with_color(gray_pic_array, internal_points) # warp, max_rect = warp_square(gray_pic_array, max_contour) # cv2_helper.show_rect(warp, max_rect) # cv2_helper.show_pic(warp) # cv2_helper.show_pic(gray_pic_array) # cv2_helper.show_contours_in_pic(warp, [max_contour, rect_max_contour]) # sub_warp = gray_pic_array sub_warp = cv2_helper.get_rect_ragion_with_contour(threshed_pic_array, max_contour) # sub_warp = cv2_helper.get_rect_ragion_with_rect(gray_pic_array, max_rect) cv2_helper.show_pic(sub_warp) sub_warp = remove_vertical_lines(sub_warp) sub_warp = remove_horizontal_lines(sub_warp)