from matplotlib import pyplot as plt
import numpy as np
import math
import cv2

potential_points_num = 200
image_threshold = 0

import numpy as np
import math


def fast_hough_line(img, angle_step=1, lines_are_white=True, value_threshold=5):
    """
    Hough line using vectorized numpy operations.
    May take more memory, but takes much less time.
    """
    # Rho and Theta ranges
    thetas = np.deg2rad(np.arange(-90.0, 90.0, angle_step)) #can be changed
    width, height = img.shape
    diag_len = int(np.ceil(np.sqrt(width * width + height * height)))
    rhos = np.linspace(-diag_len, diag_len, diag_len * 2)

    # Cache some resuable values
    cos_theta = np.cos(thetas)
    sin_theta = np.sin(thetas)
    num_thetas = len(thetas)

    # Hough accumulator array of theta vs rho
    accumulator = np.zeros((2 * diag_len, num_thetas))
    are_edges = img > value_threshold if lines_are_white else img < value_threshold
    #are_edges = cv2.Canny(img,50,150,apertureSize = 3)
    y_idxs, x_idxs = np.nonzero(are_edges)  # (row, col) indexes to edges
    # Vote in the hough accumulator
    xcosthetas = np.dot(x_idxs.reshape((-1,1)), cos_theta.reshape((1,-1)))
    ysinthetas = np.dot(y_idxs.reshape((-1,1)), sin_theta.reshape((1,-1)))
    rhosmat = np.round(xcosthetas + ysinthetas) + diag_len
    rhosmat = rhosmat.astype(np.int16)
    for i in range(num_thetas):
        rhos,counts = np.unique(rhosmat[:,i], return_counts=True)
        accumulator[rhos,i] = counts
    return accumulator, thetas, rhos


def show_hough_line(img, accumulator, thetas, rhos):
    import matplotlib.pyplot as plt

    fig, ax = plt.subplots(1, 2, figsize=(10, 10))

    ax[0].imshow(img)
    ax[0].set_title("Input image")
    ax[0].axis("image")

    ax[1].imshow(
        accumulator, cmap="jet",
        extent=[np.rad2deg(thetas[-1]), np.rad2deg(thetas[0]), rhos[-1], rhos[0]])
    ax[1].set_aspect("equal", adjustable="box")
    ax[1].set_title("Hough transform")
    ax[1].set_xlabel("Angles (degrees)")
    ax[1].set_ylabel("Distance (pixels)")
    ax[1].axis("image")

    plt.show()


if __name__ == "__main__":
    image = cv2.imread("0.0/00.pgm", cv2.COLOR_BGR2GRAY)
    accumulator, thetas, rhos = fast_hough_line(image)
    show_hough_line(image, accumulator, thetas, rhos)
    
    # Obtaining the lines from the accumulator
    sorted_idxs = np.dstack(np.unravel_index(np.argsort(accumulator.ravel()), accumulator.shape))[0][::-1]
    lines = []
    for i, j in sorted_idxs:
        if accumulator[i, j] > 0:
            theta = np.deg2rad(thetas[j])
            rho = rhos[i] - int(accumulator.shape[0] / 2)
            a = np.cos(theta)
            b = np.sin(theta)
            x0 = a * rho
            y0 = b * rho
            x1 = int(x0 + 1000*(-b))
            y1 = int(y0 + 1000*(a))
            x2 = int(x0 - 1000*(-b))
            y2 = int(y0 - 1000*(a))
            lines.append(((x1, y1), (x2, y2)))

    # Printing the equations of the lines
    for line in lines:
        (x1, y1), (x2, y2) = line
        slope = (y2 - y1) / (x2 - x1) if (x2 - x1) != 0 else math.inf # @@@
        intercept = y1 - slope * x1
        print(f"y = {slope}x + {intercept}")
НА ЭТОТ КОД ПОЛУЧАЮ ОШИБКУ:
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-22-10a89d2e0053> in <cell line: 66>()
     75         if accumulator[i, j] > 0:
     76             theta = np.deg2rad(thetas[j])
---> 77             rho = rhos[i] - int(accumulator.shape[0] / 2)
     78             a = np.cos(theta)
     79             b = np.sin(theta)

IndexError: index 889 is out of bounds for axis 0 with size 298
ЧТО ДЕЛАТЬ?!