image = cv2.imread("0.0/01.pgm", cv2.COLOR_BGR2GRAY)


def get_coords_by_threshold(image: np.ndarray, threshold: int = 150) -> tuple:
    """Gets pixel coords with intensity more then 'theshold'."""
    coords = np.where(image > threshold)
    return coords


def delete_pixels_by_min_threshold(
        image: np.ndarray, min_threshold: int = 100
) -> np.ndarray:
    """Deletes coords from image and returns this image."""
    anti_coords = np.where(image < min_threshold)
    image[anti_coords] = 0
    return image


def get_neigh_nums_list(
        coords: tuple, kernel_size: int = 3
) -> list:
    """
    Gets list with number of neighborhoods by kernel.
    Returns list like [[x1, y1, N1], [x2, y2, N2]],
    Where N - neighborhood's number.
    """
    neigh_nums = []
    offset = (kernel_size - 1) // 2

    for x, y in zip(coords[0], coords[1]):
        if x < 0 + offset or x > image.shape[0] - offset:
            continue
        if y < 0 + offset or y > image.shape[1] - offset:
            continue
        
        kernel = image[x-offset:x+offset+1, y-offset:y+offset+1]
        step_neigh_num = np.count_nonzero(kernel) - 1
        neigh_nums.append([x, y, step_neigh_num])

    return neigh_nums


def sort_neight_nums_by_N(neigh_nums: list) -> np.ndarray:
    """
    Sort neigh_nums by N parameter.
    Removes N=-1, N=0 and sorts by N desc. 
    """
    np_neigh_nums = np.array(neigh_nums)

    np_neigh_nums = np_neigh_nums[
        (np_neigh_nums[:, 2] != -1) & (np_neigh_nums[:, 2] != 0)]

    np_neigh_nums = np_neigh_nums[
        np.argsort(-np_neigh_nums[:, 2])]

    return np_neigh_nums


def get_potential_points_coords(
        sorted_niegh_nums: np.ndarray, potential_points_num: int = 30
) -> np.ndarray:
    """
    Gets best candidates, potential points coords only.
    Returns np.ndarray like [[x1, y1], [x2, y2]].
    """
    sorted_neigh_nums = np.delete(sorted_niegh_nums, 2, axis=1)
    return sorted_neigh_nums[:potential_points_num]


def get_best_lines(potential_points: np.ndarray) -> np.ndarray:
    """
    Gets all combinations of lines by all points.
    Line y = kx + b.
    Returns np.ndarray like [[k1, b1], [k2, b2]].
    """
    combinations_points = []
    
    # Create combinations of points without using itertools.combinations
    for i in range(len(potential_points)):
        for j in range(i + 1, len(potential_points)):
            combinations_points.append((potential_points[i], potential_points[j]))

    # Погрешность для значений параметров k и b
    tolerance_k = 0.1
    tolerance_b = 10
    tolerance_distance = 2  # tolerance for distance from the line

    # Список для хранения уникальных уравнений прямых
    unique_equations = []

    # Словарь для хранения количества точек, лежащих на каждой прямой
    points_count = {}

    # Проходимся по каждой комбинации точек
    for combo in combinations_points:
        # Координаты первой точки
        x1, y1 = combo[0]
        # Координаты второй точки
        x2, y2 = combo[1]
        
        # Находим уравнение прямой
        if x2 - x1 != 0:  # Избегаем деления на ноль
            k = (y2 - y1) / (x2 - x1)
            b = y1 - k * x1
            
            # Проверяем, есть ли уже похожая прямая в списке уникальных уравнений
            is_similar = False
            for equation in unique_equations:
                k_unique, b_unique = equation
                # Проверяем погрешности для значений параметров k и b
                if abs(k - k_unique) <= tolerance_k and abs(b - b_unique) <= tolerance_b:
                    is_similar = True
                    break
            
            # Если это уникальная прямая, добавляем ее в список уникальных уравнений и словарь количества точек
            if not is_similar:
                equation = (k, b)
                unique_equations.append(equation)
                points_count[equation] = 0

    # Проходимся по каждой точке из potential_points
    for point in potential_points:
        # Координаты точки
        x, y = point
        
        # Проверяем расстояние точки до прямой
        for equation in unique_equations:
            k, b = equation
            
            # Calculate the distance from the point to the line
            distance = abs(k * x - y + b) / ((k ** 2 + 1) ** 0.5)
            
            # Check if the distance is within the tolerance
            if distance <= tolerance_distance:
                # Увеличиваем счетчик точек для данной прямой
                points_count[equation] += 1

    # Сортируем словарь количества точек по убыванию количества точек
    sorted_points_count = sorted(points_count.items(), key=lambda x: x[1], reverse=True)

    # Выбираем три лучшие прямые
    best_equations = [equation for equation, count in sorted_points_count[:3]]

    # Выводим результаты
    print("Лучшие уравнения прямых:")
    for equation in best_equations:
        k, b = equation
        print(f"y = {k}x + {b}")

    best_lines = sorted_points_count[:3]
    print("Количество точек на каждой из лучших прямых:")
    for equation, count in sorted_points_count[:3]:
        print(f"Уравнение прямой: {equation}, Количество точек: {count}")

    return best_lines




# main
coords = get_coords_by_threshold(image)

image = delete_pixels_by_min_threshold(image)

neigh_nums = get_neigh_nums_list(coords)

sorted_neigh_nums = sort_neight_nums_by_N(neigh_nums)

potential_points = get_potential_points_coords(sorted_neigh_nums)

best_lines = get_best_lines(potential_points)
print(best_lines)

# Visualization
plt.imshow(image, cmap="gray")
plt.scatter(potential_points[:, 1], potential_points[:, 0], color="red", marker="o")
plt.show()

# Plot the lines on the image
for equation in best_lines:
    k, b = equation
    x = np.arange(0, image.shape[1])
    y = k * x + b
    plt.plot(x, y, color="green")
plt.show()

получаю ошибку:
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-15-32adb554dc77> in <cell line: 180>()
    181     k, b = equation
    182     x = np.arange(0, image.shape[1])
--> 183     y = k * x + b
    184     plt.plot(x, y, color="green")
    185 plt.show()

ValueError: operands could not be broadcast together with shapes (2,) (500,) 

как best_lines возвращать типа [[k1,b1], [k2, b2]]?