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)