У меня есть сгенерированный набор изображений, и моя задача - определить, у кого есть аномалия. Изображения в сгенерированном наборе всегда будут иметь одинаковый размер, но цвет неизвестен, поэтому я не могу фильтровать по определенному цвету и т. Д.
Моя первоначальная мысль заключалась в том, чтобы использовать метод стандартных отклонений. Я рассматривал возможность сбора каждого цветового канала из каждого изображения и поиска выбросов.
def find_anomalies(data, deviation=1):
anomalies = []
std = np.std(data)
median = np.median(data)
print("std:", std)
print("median:", median)
anomaly_threshold = std * deviation
lower_limit = median - anomaly_threshold
upper_limit = median + anomaly_threshold
print("upper limit:", upper_limit)
print("lower_limit", lower_limit)
for outlier in data:
if outlier > upper_limit or outlier < lower_limit:
anomalies.append(outlier)
return anomalies
К сожалению, вышеупомянутый подход не надежен. Чтобы выявить аномалии, я должен использовать порог низкого отклонения, который создает много ложных срабатываний.
Есть ли здесь более надежный подход? Как избежать ложных срабатываний?
Набор данных с аномалией
означает канал цвета для каждого изображения (вПорядок BGR):
[array([ 57.16513605, 78.57134354, 219.78511905]),
array([ 68.34270042, 61.33552743, 209.65704641]),
array([ 51.3882803 , 112.60033038, 231.52756042]), # anomaly
array([ 55.9156033 , 89.1537716 , 221.49717332]),
array([ 68.89410256, 60.19700855, 210.46179487])]
стандартные отклонения для каждого изображения (также в порядке BGR):
[array([31.63484434, 30.85018405, 24.33004357]),
array([35.63240512, 28.23304456, 30.03271386]),
array([29.90787446, 38.49502507, 16.46772441]), #anomaly
array([31.30206573, 38.42344265, 26.11348659]),
array([35.73322784, 26.78139566, 28.99681079])]
Набор данных без аномалий
Для полноты,Вот другой набор изображений, где нет аномалий, но я получаю ложные срабатывания.
означает:
[array([ 49.51721236, 92.86826805, 227.2369951 ]),
array([ 48.61022019, 76.32031575, 224.15105941]),
array([ 51.79616963, 87.86684907, 223.92673659]),
array([ 47.83266254, 109.75719814, 232.76904025]),
array([ 52.66608098, 84.64163484, 222.76928953])]
стандартотклонения:
[array([25.93041916, 28.60078108, 18.99398738]),
array([22.85396012, 18.91722547, 14.04923793]),
array([27.47452402, 31.51487936, 22.9319416 ]),
array([21.34988674, 32.60073378, 15.94599248]),
array([29.21103562, 29.62855599, 20.87369572])]
Мои текущие результаты
Поиск выбросов только в красном канале в двух вышеупомянутых наборах данных
>>> find_anomalies(red_channels_from_dataset_with_anomaly)
[219.78511904761902, 209.6570464135021, 231.52756042427401, 221.497173316104, 210.46179487179487]
std: 8.03897659600765
median: 219.78511904761902
upper limit: 234.25527692043278
lower_limit 205.31496117480526
# => no anomalies detected (false negative)
>>> find_anomalies(red_channels_from_dataset_with_no_anomalies)
[227.23699510403915, 224.151059410054, 223.9267365861073, 232.76904024767802, 222.7692895339954]
std: 3.615494221208812
median: 224.151059410054
upper limit: 230.65894900822985
lower_limit 217.64316981187812
# => anomalies [232.76904024767802] (false positive)