Добавил:
chrysler_a57_mltbnk
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:
from os import listdir, system
from os.path import isfile
from time import perf_counter_ns
import typing as typ
from math import pi
import numpy as np
import numpy.typing as npt
import matplotlib.pyplot as plt #type: ignore
from skimage.io import imread #type: ignore
#Функция считывания названий файлов
def f_name(s: str) -> typ.List[str]:
lt = listdir(s)
return lt
#Функция создания списков изображений
def img_read(ls: typ.List[str],path: str) -> typ.List[npt.NDArray[np.float32]]:
array: typ.List[npt.NDArray[np.float32]] = []
for i in ls:
if i.startswith("Forest"):
array.append(\
np.array(imread(f'{path}/{i}'),dtype=np.float32))
return array
#Функция «спрямления» изображений
def img_flatten(ls:typ.List[npt.NDArray[np.float32]]) -> None:
for i in ls:
i.shape = (len(i)*len(i[0])*3) #type: ignore
i = i.T
#Функция нормирования параметров
def norm(arr: npt.NDArray[np.float32],\
mn: npt.NDArray[np.float32],\
st: npt.NDArray[np.float32]) -> None:
for i in range(len(arr)):
arr[i] = (arr[i] - mn[i])/st[i]
#Функция создания аргументов для построения двумерного графика
def plot2d_params(f: typ.Callable[...,typ.Any],\
x_lim: typ.Tuple[typ.Any, typ.Any],\
y_lim: typ.Tuple[typ.Any, typ.Any],\
m: typ.List[np.float32],\
s: typ.List[np.float32],
grid_n: int = 100)\
-> typ.Tuple[typ.Any, typ.Any, typ.Any]:
x1_p: npt.NDArray[np.float32] = np.linspace(x_lim[0], x_lim[1],\
grid_n, dtype=np.float32)
x2_p: npt.NDArray[np.float32] = np.linspace(y_lim[0], y_lim[1],\
grid_n, dtype=np.float32)
x1_p, x2_p = np.meshgrid(x1_p, x2_p)
s: typ.Tuple[int, ...] = x1_p.shape
r: npt.NDArray[np.float32] = f(x1_p.flatten(), x2_p.flatten(), m, s)
r.shape = s
return (x1_p, x2_p, r)
#Функция нормального распределения
def gauss_2d(x: npt.NDArray[np.float32],\
y: npt.NDArray[np.float32],\
m: typ.List[np.float32] = [np.float32(0.0),np.float32(0.0)],\
st: typ.List[np.float32] = [np.float32(1.0),np.float32(1.0)])\
-> npt.NDArray[np.float32]:
##Определение параметров двумерного нормального распределения
z1: npt.NDArray[np.float32] = (-1)*(x-m[0])**2/(2*st[0]**2)
z2: npt.NDArray[np.float32] = (-1)*(y-m[1])**2/(2*st[1]**2)
return 1/(2*pi*st[0]*st[1])*np.exp(z1+z2)
#Функция определения аномалий
def anom_search(P: npt.NDArray[np.float32],\
brd: float) -> npt.NDArray[np.float32]:
H: npt.NDArray[np.float32] =\
np.zeros(len(P), dtype=np.float32)
c: int = 0
for i in P:
if i < brd:
H[c] = 1
c += 1
return H
#Функция расчёта методики F-score
def F_score(y_orig: npt.NDArray[np.float32],\
y_anom: npt.NDArray[np.float32]) -> np.float32:
#Истинноположительные
TP: np.float32 = np.sum(np.logical_and(y_anom,y_orig))
#Ложноположительные
FP: np.float32 = np.sum(np.logical_not(np.logical_or(np.logical_not(y_anom),y_orig)))
#Ложноотрицательные
FN: np.float32 = np.sum(np.logical_and(np.logical_not(y_anom),y_orig))
#Метрика Persision (точность)
P: np.float32
if FP+TP != 0:
P = TP/(FP+TP)
else:
P = np.float32(0.0)
#Метрика Recall (полнота)
R: np.float32
if FN+TP != 0:
R = TP/(FN+TP)
else:
R =np.float32(0.0)
#Метрика F1
if P+R != 0:
return (2*P*R)/(P+R)
else:
return np.float32(0.0)
#Очистка окна консоли
system('cls')
#Запуск таймера
t1: float = perf_counter_ns()
#Создание списка названий файлов в папке
trees_list: typ.List[str] = f_name("Trees")
#Создание списка изображений в папке
trees_img_list: typ.List[npt.NDArray[np.float32]] =\
img_read(trees_list, "Trees")
del trees_list
##Изображение для дальнейшего включения в выборку аномалий
img: npt.NDArray[np.float32] = np.copy(trees_img_list[6])
#Создание массива изображений
##«Спрямление» массива изображений
img_flatten(trees_img_list)
##Создание массива из списка
X: npt.NDArray[np.float32] = np.array(trees_img_list, dtype=np.float32)
del trees_img_list
#Метод главных координат
##Максимальное количество параметров
max_par: int = 2
##Среднее нормирование
mean: npt.NDArray[np.float32] = np.mean(X.T, axis=1, dtype=np.float32)
std: npt.NDArray[np.float32] = np.std(X.T, axis=1, dtype=np.float32)
norm(X.T,mean,std)
##Создание матрицы собственных векторов для ковариационной матрицы
U: npt.NDArray[np.float32]
p: bool = isfile('U_matrix.npy')
if p == True:
##Создание матрицы преобразований
U = np.load('U_matrix.npy')
elif p == False:
##Создание ковариационной матрицы
sigma: npt.NDArray[np.float32] = np.cov(X.T,bias=True)
##Создание матрицы преобразований
U, S, Vh = np.linalg.svd(sigma)
np.save('U_matrix.npy', U[::, :max_par:])
del sigma, S, Vh
X_cmprs: npt.NDArray[np.float32] = X@U #Компрессия изображений
del X, p, mean, std, max_par
#Двумерное нормальное распределение
##Определение параметров двумерного нормального распределения
m_x: np.float32 = np.mean(X_cmprs.T[0], dtype=np.float32) #среднее для икса
st_x: np.float32 = np.std(X_cmprs.T[0], dtype=np.float32) #отклонение для икса
m_y: np.float32 = np.mean(X_cmprs.T[1], dtype=np.float32) #среднее для игрека
st_y: np.float32 = np.std(X_cmprs.T[1], dtype=np.float32) #отклонение для игрека
#Построение изображений в двух главных координатах
##График исходных данных
plt.figure(1)
plt.scatter(X_cmprs.T[0],X_cmprs.T[1],alpha=0.3, label="Изображения") #Построение графика
plt.title("Изображения в двух главных координатах до выделения аномалий")
plt.legend()
##График после определения аномалий
plt.figure(2)
plt.scatter(X_cmprs.T[0],X_cmprs.T[1],alpha=0.3, label="Изображения") #Построение графика
plt.title("Изображения в двух главных координатах после выделения аномалий")
plt.legend()
#Построение контурного графика нормального распределения
x, y, z = plot2d_params(gauss_2d,\
(np.min(X_cmprs.T[0]), np.max(X_cmprs.T[0])),\
(np.min(X_cmprs.T[1]), np.max(X_cmprs.T[1])),\
[m_x,m_y],\
[st_x,st_y]) #Создание аргументов
##График исходных данных
plt.figure(1)
plt.contour(x, y, z, levels=5, linestyles="dashed") #Построение графика
##График после определения аномалий
plt.figure(2)
plt.contour(x, y, z, levels=5, linestyles="dashed") #Построение графика
del x, y, z
#Формирование аномалий
img_a1: npt.NDArray[np.float32] = img/5 #Слишком тёмное
img_a2: npt.NDArray[np.float32] = img*5*(img<52) + 255*(img>51) #Пересвеченное
img_a3: npt.NDArray[np.float32] = np.copy(img) #С чёрными и белыми точками
img_a3[::2,::2,:] = 0
img_a3[1::2, 1::2, :] = 255
img_a4: npt.NDArray[np.float32] = np.copy(img) #C перепутанными 0 и 2 каналами
img_a4[:,:,2], img_a4[:,:,0] = img_a4[:,:,0], img_a4[:,:,2]
anomalies: typ.List[npt.NDArray[np.float32]] =\
[img_a1,img_a2,img_a3,img_a4] #Список аномалий
img_flatten(anomalies) #«Спрямление» аномалий
anomalies_arr: npt.NDArray[np.float32] =\
np.array(anomalies, dtype=np.float32) #Массив аномалий
##Нормирование массива аномалий
mean_a: npt.NDArray[np.float32] =\
np.mean(anomalies_arr.T, axis=1, dtype=np.float32)
std_a: npt.NDArray[np.float32] =\
np.std(anomalies_arr.T, axis=1, dtype=np.float32)
norm(anomalies_arr.T,mean_a,std_a)
anomalies_arr = anomalies_arr@U #Компрессия аномалий
X_cmprs = np.vstack((X_cmprs, anomalies_arr),dtype=np.float32) #Добавление аномалий
Y_cmprs: npt.NDArray[np.float32] #Исходный массив наличия аномалий
Y_cmprs = np.hstack((np.zeros(len(X_cmprs)-4),np.ones(4)),dtype=np.float32)
plt.figure(1)
plt.scatter(anomalies_arr.T[0],anomalies_arr.T[1],alpha=1,c='r',label="Аномалии") #Построение графика
plt.legend()
del img_a1, img_a2, img_a3, img_a4, anomalies, anomalies_arr, mean_a, std_a, U
#Определение оптимального порога
P: npt.NDArray[np.float32] =\
gauss_2d(X_cmprs.T[0],X_cmprs.T[1],[m_x,m_y],[st_x,st_y])
metric: typ.List[typ.List[typ.Any]] =\
[[i/(10**6) for i in range(11)],[]]
for i in metric[0]:
anom: npt.NDArray[np.float32] = anom_search(P,i)
metric[1].append(F_score(Y_cmprs,anom))
max_Fscore = max(metric[1]) #Максимальное значение метрики
optimal_brd = metric[0][metric[1].index(max_Fscore)] #Оптимальный порог
print(f'Optimal decision border: {optimal_brd:.1e}.')
Y_cmprs = anom_search(P,optimal_brd)
##График после определения аномалий
plt.figure(2)
plt.scatter(X_cmprs.T[0,Y_cmprs==1],X_cmprs.T[1,Y_cmprs==1],alpha=1,c='r',label="Аномалии") #Построение графика
plt.legend()
del P, metric, max_Fscore, optimal_brd, X_cmprs, Y_cmprs, m_x, m_y, st_x, st_y
#Вывод времени выполнения программы
print(f'\nTotal program execution time: \
{(perf_counter_ns()-t1)/10**9:.5f} seconds.')
del t1
plt.show()
Соседние файлы в папке лабы
