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

potential_points_num = 200
image_threshold = 100

def hough_line(edge):
theta = np.arange(0, 180, 1)
cos = np.cos(np.deg2rad(theta))
sin = np.sin(np.deg2rad(theta))

rho_range = round(math.sqrt(edge.shape[0]2 + edge.shape[1]2))
accumulator = np.zeros((2 * rho_range, len(theta)), dtype=np.uint8)

edge_pixels = np.where(edge == 255)
coordinates = list(zip(edge_pixels[0], edge_pixels[1]))

for p in range(len(coordinates)):
for t in range(len(theta)):
rho = int(round(coordinates[p][1] * cos[t] + coordinates[p][0] * sin[t]))
accumulator[rho, t] += 2

return accumulator

def get_coords_by_threshold(
image: np.ndarray,
) -> tuple:
“”“Gets coordinates with intensity more than ‘image_threshold’.”“”
coords = np.where(image > image_threshold)
return coords

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_neigh_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
) -> 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]


image = cv2.imread(“0.0/00.pgm”, cv2.COLOR_BGR2GRAY)

# my code
coords_by_threshold = get_coords_by_threshold(image)
neigh_nums = get_neigh_nums_list(coords_by_threshold)
sorted_neigh_nums = sort_neigh_nums_by_N(neigh_nums)
potential_points = get_potential_points_coords(sorted_neigh_nums)
# end my code

accumulator = hough_line(potential_points)


# lines
edge_pixels = np.where(accumulator > 110)
coordinates = list(zip(edge_pixels[0], edge_pixels[1]))


for i in range(0, len(coordinates)):
a = np.cos(np.deg2rad(coordinates[i][1]))
b = np.sin(np.deg2rad(coordinates[i][1]))
x0 = acoordinates[i][0]
y0 = bcoordinates[i][0]
x1 = int(x0 + 1000(-b))
y1 = int(y0 + 1000(a))
x2 = int(x0 - 1000(-b))
y2 = int(y0 - 1000(a))

cv2.line(image, (x1, y1), (x2, y2), (0, 255, 0), 1)

plt.subplot(121), plt.imshow(image)
plt.subplot(122), plt.imshow(accumulator)
plt.show()


edge_pixels = np.where(accumulator > 110)
coordinates = list(zip(edge_pixels[0], edge_pixels[1]))

# Найти три наиболее точных пикселя аккумулятора
sorted_coordinates = sorted(coordinates, key=lambda c: accumulator[c[0], c[1]], reverse=True)[:3]

lines = []

rho_range = round(math.sqrt(potential_points.shape[0]**2 + potential_points.shape[1]**2))
theta_resolution = 100

for rho, theta in sorted_coordinates:
# Преобразование из индексов аккумулятора к физическим единицам (например, пиксели -> метры)
rho_physical = rho - rho_range / 2 # или другое соответствующее преобразование
theta_deg = theta * theta_resolution
theta_rad = np.deg2rad(theta_deg)

# Применение уравнения прямой
a = -np.cos(theta_rad) / np.sin(theta_rad)
b = rho_physical / np.sin(theta_rad)

lines.append((a, b))

# Применение полученных уравнений прямых
for a, b in lines:
x = np.arange(image.shape[1])
y = a * x + b
plt.plot(x, y, “r”)


plt.imshow(image)
plt.show()

Код должен был находить три прямых, а не может найти ни одной