def _guess_lines(ys, max_lines=50, confidence_minimum=0.0):
        """guesses and returns text inter-line distance, number of lines, y_position of first line"""
        ys = ys.astype(numpy.float32)
        compactness_list, means_list, diffs, deviations = [], [], [], []
        start_n = 1
        for k in range(start_n, min(len(ys), max_lines)):
            compactness, classified_points, means = cv2.kmeans(data=ys, K=k, bestLabels=None, criteria=(
            cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_MAX_ITER, 1, 10), attempts=2, flags=cv2.KMEANS_PP_CENTERS)
            means = numpy.sort(means, axis=0)
            means_list.append(means)
            compactness_list.append(compactness)
            if k < 3:
                tmp1 = [1, 2, 500, 550]  # forge data for bad clusters
            else:
                # calculate the center of each cluster. Assuming lines are equally spaced...
                tmp1 = numpy.diff(means, axis=0)  # diff will be equal or very similar
            tmp2 = numpy.std(tmp1) / numpy.mean(means)  # so variance is minimal
            tmp3 = numpy.sum((tmp1 - numpy.mean(tmp1)) ** 2)  # root mean square deviation, more sensitive than std
            diffs.append(tmp1)
            deviations.append(tmp3)

        compactness_list = numpy.diff(
            numpy.log(numpy.array(compactness_list) + 0.01))  # sum small amount to avoid log(0)
        deviations = numpy.array(deviations[1:])
        deviations[0] = numpy.mean(deviations[1:])
        compactness_list = (compactness_list - numpy.mean(compactness_list)) / numpy.std(compactness_list)
        deviations = (deviations - numpy.mean(deviations)) / numpy.std(deviations)
        aglomerated_metric = 0.1 * compactness_list + 0.9 * deviations

        i = numpy.argmin(aglomerated_metric) + 1
        lines = means_list[i]

        # calculate confidence
        betterness = numpy.sort(aglomerated_metric, axis=0)
        confidence = (betterness[1] - betterness[0]) / (betterness[2] - betterness[1])
        if confidence < confidence_minimum:
            raise Exception("low confidence")
        return lines
def _guess_lines ( ys , max_lines = 50 , confidence_minimum = 0.0 ) : ys = ys . astype ( numpy . float32 ) compactness_list , means_list , diffs , deviations = [ ] , [ ] , [ ] , [ ] start_n = 1 for k in range ( start_n , min ( len ( ys ) , max_lines ) ) : compactness , classified_points , means = cv2 . kmeans ( data = ys , K = k , bestLabels = None , criteria = ( cv2 . TERM_CRITERIA_EPS | cv2 . TERM_CRITERIA_MAX_ITER , 1 , 10 ) , attempts = 2 , flags = cv2 . KMEANS_PP_CENTERS ) means = numpy . sort ( means , axis = 0 ) means_list . append ( means ) compactness_list . append ( compactness ) if k < 3 : tmp1 = [ 1 , 2 , 500 , 550 ] else : tmp1 = numpy . diff ( means , axis = 0 ) tmp2 = numpy . std ( tmp1 ) / numpy . mean ( means ) tmp3 = numpy . sum ( ( tmp1 - numpy . mean ( tmp1 ) ) ** 2 ) diffs . append ( tmp1 ) deviations . append ( tmp3 ) compactness_list = numpy . diff ( numpy . log ( numpy . array ( compactness_list ) + 0.01 ) ) deviations = numpy . array ( deviations [ 1 : ] ) deviations [ 0 ] = numpy . mean ( deviations [ 1 : ] ) compactness_list = ( compactness_list - numpy . mean ( compactness_list ) ) / numpy . std ( compactness_list ) deviations = ( deviations - numpy . mean ( deviations ) ) / numpy . std ( deviations ) aglomerated_metric = 0.1 * compactness_list + 0.9 * deviations i = numpy . argmin ( aglomerated_metric ) + 1 lines = means_list [ i ] betterness = numpy . sort ( aglomerated_metric , axis = 0 ) confidence = ( betterness [ 1 ] - betterness [ 0 ] ) / ( betterness [ 2 ] - betterness [ 1 ] ) if confidence < confidence_minimum : raise Exception ( "low confidence" ) return lines
guesses and returns text inter-line distance, number of lines, y_position of first line