/// <summary>Логика выполнения - Сравнение картинок</summary> private async void OnComparisonOfNewWithCurrentExecuted(object p) { // todo создать методы из длинного кода try { _comparisonToken = true; _pHashCancellation = new CancellationTokenSource(); var cancellation = _pHashCancellation.Token; //var newImagesSelected = new List<PHashAndDataImage>(); // удаляем изображения разрешением меньше 1000 в длину, т.к. они нам не нужны for (int i = _newImagesList.Count - 1; i > -1; i--) { if (_newImagesList[i].Resolution.Width < 1000) { _newImagesList.Remove(_newImagesList[i]); } } // получить коллекцию перцептивного хеша полученных изображений await Task.Run(() => { Parallel.ForEach(_newImagesList, imageData => { _imagesService.GetPerceptualHashOfImageData(imageData); }); } ); // получить коллекцию перцептивного хеша, имеющихся в папке _oldImagesList = new List <PHashAndDataImage>(); var pathOldImages = new DirectoryInfo(_pathFolderMyImages).GetFiles().ToList(); //oldImagesPHash = _imagesService.GetPerceptualHashOfImagesList(pathOldImages); OutputForWin = "\nПроизводится анализ имеющихся изображений в выбранной папке"; try { await Task.Run(() => { var timer = Stopwatch.StartNew(); if (_imagesService != null) { _oldImagesList = _imagesService.GetPerceptualHashOfImagesList(pathOldImages, cancellation); } timer.Stop(); OutputForWin = $"\nИзображения проанализированы, потраченное время: {timer.Elapsed.TotalSeconds}," + $"Количество изображений {_oldImagesList.Count}\n"; }); } catch (OperationCanceledException) { OutputForWin = $"Операция отменена пользователем"; } catch (AggregateException ex) { OutputForWin = ex.InnerException is OperationCanceledException ? $"Операция принудительно отмена пользователем {ex.InnerException.Message}" : $"Обработка выдала несколько исключений {ex.InnerExceptions}"; } catch (Exception e) { OutputForWin = $"Произошла ошибка нахождения хеша изображения. {e.Message}"; } // todo сохранять коллекцию хеша в файл ассоциируя их с именем изображения и записываем дату последнего изменения // сравнить между собой await Task.Run(() => { var timer = Stopwatch.StartNew(); bool identityToken; _imagesNemberArray = new bool[_newImagesList.Count]; foreach (var newImage in _newImagesList) { // изначально изображение идентичное identityToken = true; foreach (var oldImage in _oldImagesList) { if ((newImage.Resolution.Width / newImage.Resolution.Height) == (oldImage.Resolution.Width / oldImage.Resolution.Height)) { // Счетчик совпадений байтов в массиве перцептивного хеша. int byteMatchCounter = 0; for (int i = 0; i < newImage.PerceptualHash.Length; i++) { if (newImage.PerceptualHash[i] == oldImage.PerceptualHash[i]) { byteMatchCounter++; } } // при полном совпадении - это одна и та же картинка. if (byteMatchCounter == 64) { OutputForWin = $"\nТочное совпадение картинки {newImage.Name} \nС картинкой {oldImage.Name}"; identityToken = false; } if (byteMatchCounter == 63) { OutputForWin = $"\nСовпадение 63 из 64 картинки {newImage.Name} \nС картинкой {oldImage.Name}"; } if (byteMatchCounter == 62) { OutputForWin = $"\nСовпадение 62 из 64 картинки {newImage.Name} \nС картинкой {oldImage.Name}"; } } } if (identityToken) { _imagesNemberArray[_newImagesList.IndexOf(newImage)] = true; } else { _imagesNemberArray[_newImagesList.IndexOf(newImage)] = false; } } timer.Stop(); OutputForWin = $"\nИзображения проанализированы, потраченное время: {timer.Elapsed.TotalSeconds},\n" + $"Количество новых изображений {_imagesNemberArray.Count(x => x == true)}"; }); } catch (Exception e) { OutputForWin = $"Произошла ошибка во время обработки. {e.Message}"; } finally { _comparisonToken = false; // Forcing the CommandManager to raise the RequerySuggested event CommandManager.InvalidateRequerySuggested(); } }