class ImageService:
“”“Service for image manipulations.”“”
@staticmethod
def get_binary_image(image: np.ndarray) -> np.ndarray:
“”“Gets binary image from image.”“”
binary_image = image.copy()
binary_image[np.where(binary_image != 0)] = 255
return binary_image

@staticmethod
def count_zero_pixels(image_gray: np.ndarray) -> int:
“”“Counts pixels with 0 intensity on black-white image.”“”
zero_pixels = np.count_nonzero(image_gray == 0)
return zero_pixels

@staticmethod
def calculate_zero_pixel_percentage(image: np.ndarray) -> float:
“”“Calculates zero intensity pixel’s percentage.”“”
total_pixels = image.size
zero_pixels = ImageService.count_zero_pixels(image)
zero_percentage = zero_pixels / total_pixels * 100
return zero_percentage


class TimeService:
“”“Service for time management.”“”
def init(self, time_max: float):
self.time_max = time_max
self.start_time = None

def start_timer(self) -> None:
“”“Start time point. Sets ‘self.start_time’.”“”
self.start_time = time.time()

def check_timer(self):
“”“Checks if time more than ‘self.time_max’.”“”
end_time = time.time()
delta_time = end_time - self.start_time
if delta_time > self.time_max:
return False
return delta_time

POTENTIAL_POINTS_NUM = 200
ITERATIONS_NUM = 1000
THRESHOLD_DISTANCE = 3
THRESHOLD_K = 0.5
THRESHOLD_B = 20
NOISE_LESS = 75
IMAGE_THRESHOLD_MIN = 0
IMAGE_THRESHOLD_MAX = 100
TIME_MAX = 1.8

class CornerDetector(object):
“”“Class for corner detection on image.”“”
def init(
self,
potential_points_num: int = POTENTIAL_POINTS_NUM,
iterations_num: int = ITERATIONS_NUM,
threshold_distance: int = THRESHOLD_DISTANCE,
threshold_k: float = THRESHOLD_K,
threshold_b: int = THRESHOLD_B
):
self.potential_points_num = potential_points_num
self.iterations_num = iterations_num
self.threshold_distance = threshold_distance
self.threshold_k = threshold_k
self.threshold_b = threshold_b
self.image = None
self.image_threshold = None
self.time_service = TimeService(TIME_MAX)
self.random_answer = np.array([[1, 1], [2, 2], [3, 3]])

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

def __get_neigh_nums_list(
self,
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 > self.image.shape[0] - offset:
continue
if y < 0 + offset or y > self.image.shape[1] - offset:
continue

kernel = self.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

@staticmethod
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] != 0]
sorted_indices = np.argsort(-np_neigh_nums[:, 2])
np_neigh_nums = np_neigh_nums[sorted_indices]
return np_neigh_nums

def __get_potential_points_coords(
self,
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[:self.potential_points_num]

def __get_best_lines(
self,
potential_points: np.ndarray
) -> np.ndarray:
“”“
Gets the best combinations of lines by all points.
Line y = kx + b.
Returns np.ndarray like [[k1, b1], [k2, b2]].
“””
remaining_points = 0
best_lines = []
num_lines = 0

while num_lines < 3:
if not self.time_service.check_timer():
return self.random_answer
if num_lines == 0:
remaining_points = np.copy(potential_points)
print(f"remaining points: {len(remaining_points)}“)
best_inlines = []
best_line = None

if len(remaining_points) == 0:
remaining_points = np.array([[1, 1], [2, 2], [3, 3], [4, 4]])

for i in range(self.iterations_num):
sample_indices = np.random.choice(
remaining_points.shape[0],
size=(self.iterations_num, 3), replace=True)
sample_points = remaining_points[sample_indices]
sample_x = sample_points[:, 1]
sample_y = sample_points[:, 0]
coefficients = np.polyfit(sample_x, sample_y, deg=1)
distances = np.abs(remaining_points[:, 0] - np.matmul(np.vstack((remaining_points[:, 1], np.ones_like(remaining_points[:, 1]))).T, coefficients)) / np.sqrt(coefficients[0] ** 2 + 1)
inlines = np.where(distances < self.threshold_distance)[0]

is_similar = False
for line in best_lines:
diff_k = abs(coefficients[0] - line[0])
diff_b = abs(coefficients[1] - line[1])

if diff_k <= self.threshold_k and diff_b <= self.threshold_b:
is_similar = True
break

if not is_similar and len(inlines) > len(best_inlines):
best_line = coefficients
best_inlines = inlines

if best_line is not None:
best_lines.append(best_line)
remaining_points = np.delete(remaining_points, best_inlines, axis=0)

num_lines += 1

return np.array(best_lines)

def find_corners(self, image: np.ndarray) -> np.ndarray:
“”“Finding triangle corners on image process.””"
self.time_service.start_timer()
self.image = image

zero_percentage = ImageService.calculate_zero_pixel_percentage(image)

if zero_percentage > NOISE_LESS:
self.image_threshold = IMAGE_THRESHOLD_MIN
else:
self.image_threshold = IMAGE_THRESHOLD_MAX

# Noise i cannot realise.
if zero_percentage < 45:
return self.random_answer

coords = self.__get_coords_by_threshold(image)
if not self.time_service.check_timer():
return self.random_answer

neigh_nums = self.__get_neigh_nums_list(coords)
if not self.time_service.check_timer():
return self.random_answer

sorted_neigh_nums = self.__sort_neigh_nums_by_N(neigh_nums)
if not self.time_service.check_timer():
return self.random_answer

potential_points = self.__get_potential_points_coords(sorted_neigh_nums)
if not self.time_service.check_timer():
return self.random_answer

best_lines = self.__get_best_lines(potential_points)
if not self.time_service.check_timer():
return self.random_answer

intersection_points = np.linalg.solve(
np.array([[best_lines[0][0], -1], [best_lines[1][0], -1]]),
[-best_lines[0][1], -best_lines[1][1]])
intersection_points = np.vstack((intersection_points, np.linalg.solve(
np.array([[best_lines[0][0], -1], [best_lines[2][0], -1]]),
[-best_lines[0][1], -best_lines[2][1]])))
intersection_points = np.vstack((intersection_points, np.linalg.solve(
np.array([[best_lines[1][0], -1], [best_lines[2][0], -1]]),
[-best_lines[1][1], -best_lines[2][1]])))

return intersection_points

class Solver(object):
def init(self):
self.alg = CornerDetector()

def solve(self, image_gray: np.ndarray) -> np.ndarray:
result = self.alg.find_corners(image_gray)
return result

image = cv2.imread(“0.3/02.pgm”, cv2.COLOR_BGR2GRAY)
solver = Solver()
solver.solve(image)

Все та же ошибка:
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-45-4c8a0c34fe22> in <cell line: 11>()
      9 image = cv2.imread("0.3/02.pgm", cv2.COLOR_BGR2GRAY)
     10 solver = Solver()
---> 11 solver.solve(image)

4 frames
<ipython-input-45-4c8a0c34fe22> in solve(self, image_gray)
      4 
      5     def solve(self, image_gray: np.ndarray) -> np.ndarray:
----> 6         result = self.alg.find_corners(image_gray)
      7         return result
      8 

<ipython-input-44-d6a27acf204a> in find_corners(self, image)
    167             return self.random_answer
    168 
--> 169         best_lines = self.__get_best_lines(potential_points)
    170         if not self.time_service.check_timer():
    171             return self.random_answer

<ipython-input-44-d6a27acf204a> in __get_best_lines(self, potential_points)
    110                 sample_x = sample_points[:, 1]
    111                 sample_y = sample_points[:, 0]
--> 112                 coefficients = np.polyfit(sample_y, sample_x, deg=1)
    113                 distances = np.abs(remaining_points[:, 0] - np.matmul(np.vstack((remaining_points[:, 1], np.ones_like(remaining_points[:, 1]))).T, coefficients)) / np.sqrt(coefficients[0] ** 2 + 1)
    114                 inlines = np.where(distances < self.threshold_distance)[0]

/usr/local/lib/python3.10/dist-packages/numpy/core/overrides.py in polyfit(*args, **kwargs)

/usr/local/lib/python3.10/dist-packages/numpy/lib/polynomial.py in polyfit(x, y, deg, rcond, full, w, cov)
    634         raise ValueError("expected deg >= 0")
    635     if x.ndim != 1:
--> 636         raise TypeError("expected 1D vector for x")
    637     if x.size == 0:
    638         raise TypeError("expected non-empty vector for x")

TypeError: expected 1D vector for x

Что делать??!?!?!