docs: 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