Перейти к содержимому
Поиск
Php Разработка

PHP: полный мануал с примерами, функциями и ООП

Практический мануал PHP: от переменных и читаемого кода до безопасных форм, интеграций, базы данных и ООП на примере магазина. Учебный маршрут, поиск функций, подробные примеры, разбор ошибок и исходники для скачивания.

Александр НекрасовИзменено:
Практический мануал PHP: от переменных и функций к объектной модели интернет-магазина
PHP 8.5.11468 глав6256 карточек справочника
Дерево руководства

Глава 389 · После объектов, копий и последовательностей изображений; совместимость с IM6

Imagick: убрать точечный шум, сохранить детали и усреднить выровненные кадры

Понять medianFilterImage, reduceNoiseImage и averageImages на настоящих картинках: полезный результат, неподходящий фильтр, потеря деталей и призраки при сдвиге.

Очистить точечные дефекты и увидеть цену для мелкой надписи

На товарной схеме появились отдельные чёрные и белые точки. Нужно подготовить аккуратное превью и сохранить мелкую надпись MUG01. Это две конкурирующие цели: сильная локальная очистка убирает не только точки, но и настоящую тонкую линию. Если есть несколько одинаково выровненных снимков, можно уменьшить контраст шума средним между кадрами. Сначала посмотрим на реальные картинки, затем различим эти операции.

Собственный чистый рисунок, точечные повреждения и настоящий результат медианы: меньше точек, но потеря тонкой детали
Собственный чистый рисунок, точечные повреждения и настоящий результат медианы: меньше точек, но потеря тонкой детали
$filtered = clone $noisy;
$filtered->medianFilterImage(3);

$noisy хранит один повреждённый кадр; clone создаёт отдельный объект $filtered. Стрелка -> вызывает его метод. Число 3 внутри скобок — размер соседства в исследованном IM6-коде; точка с запятой завершает инструкцию. Вызов меняет картинку, но не выводит её и не сохраняет файл сам. Поэтому полная программа ниже создаёт реальный PNG. При этом чистый исходник и шумный кадр остаются отдельно для сравнения.

Наш собственный рисунок коробки и кружки имеет размер 400 × 320. Учебные повреждения добавлены детерминированно: 2 000 операций point с чередованием black/white и фиксированными координатными формулами для трёх разных кадров. Готовые PNG сохранены, входят в архивы и восстанавливаются по SHA; случайный генератор при запуске не используется. Это модель отдельных дефектов, а не обещание восстановить неизвестную фотографию или любой шум камеры.

Убрать отдельные точки медианой и увидеть цену для тонкой детали

В точке (27,45) чёрный дефект стал белым. MAE к известному учебному оригиналу уменьшилась с 1.9914 до 0.6366, но надпись MUG01 и тонкое подчёркивание повреждены. Очищенный результат не объявляется точным восстановлением.

Убрать отдельные точки медианой и увидеть цену для тонкой деталиПример для указанного окружения
<?php
declare(strict_types=1);
require __DIR__.'/legacy-noise-average-fixture.php';
naRestore();
$clean=naClean();$before=naHash($clean);
$frames=naFrames();$frameHashes=naFrameHashes($frames);
$image=clone $frames[0];
$call=naCall('median3',fn()=>$image->medianFilterImage(3));
$result=naImage($image,$clean,'legacy-noise-average-median.png');
$input=naImage($frames[0],$clean,'median-noisy8.png');naSave($clean,'source-preview8.png');
naDiagnostic('legacy-noise-median-minimal',['executed_api'=>'medianFilterImage','radius'=>3,'call'=>naRecord($call),'images'=>['noisy'=>$input,'median'=>$result],
    'source_unchanged'=>naHash($clean)===$before,'input_frames_unchanged'=>naFrameHashes($frames)===$frameHashes,
    'checks'=>['true_two_warnings'=>$call['value']===true&&$call['deprecations']===2,
        'actual_change'=>naHash($image)!==naHash($frames[0]),'impulse_removed'=>$result['samples']['impulse1']['r']==1.0,
        'fixture_MAE_lower'=>$result['error_to_clean_PIXEl_CHAR_before_PNG8']['MAE']<$input['error_to_clean_PIXEl_CHAR_before_PNG8']['MAE'],
        'source_preserved'=>naHash($clean)===$before&&naFrameHashes($frames)===$frameHashes]]);
echo "legacy-noise-average-median.png\nsource-preview8.png\nmedian-noisy8.png\nmetrics.json\nmedian-radius=3 deprecations=2 impulse-removed=1 input-preserved=1\n";

В точке (27,45) чёрный дефект стал белым. MAE к известному учебному оригиналу уменьшилась с 1.9914 до 0.6366, но надпись MUG01 и тонкое подчёркивание повреждены. Очищенный результат не объявляется точным восстановлением. Каждый ZIP самостоятельный: example.php, пять PNG в base64 и legacy-noise-average-fixture.php. Распакуйте рядом и выполните php example.php. naRestore проверяет SHA и восстанавливает точные входы; шум не генерируется заново. naFrames открывает три кадра, naFreshSequence добавляет их копии в новый Imagick и ставит первый итератор; изучаемый averageImages остаётся виден в основном коде. naCall временно сохраняет только E_DEPRECATED и восстанавливает handler через finally. naImage измеряет объект до отдельной записи PNG8; naCompare составляет нативную полосу без масштабирования. Полный helper открыт в последнем разделе. Проверенная среда: PHP 8.3.6 / Imagick 3.7.0 / IM6.9.12-98 Q16, Ubuntu WSL; исполнение устаревших median/reduce в Windows IM7 не заявлено.

Ожидаемый вывод проверенной программы
legacy-noise-average-median.png
source-preview8.png
median-noisy8.png
metrics.json
median-radius=3 deprecations=2 impulse-removed=1 input-preserved=1

На полученном PNG точки очищены, но тонкое подчёркивание исчезает и MUG01 теряет чёткость. Числовая ошибка к известному чистому учебному исходнику стала меньше; это не доказывает, что результат лучше для чтения этикетки. Для реальной фотографии чистая истина обычно неизвестна. Копии изображений и пиксели помогут понять, что именно меняется.

Различить локальную медиану, Nonpeak и среднее между кадрами

Два разных пути данных: соседние пиксели в одном кадре и одна координата в трёх выровненных кадрах
Два разных пути данных: соседние пиксели в одном кадре и одна координата в трёх выровненных кадрах
ОперацияКакие данные сравниваютсяРезультат в точке (27,45)
Медиана 3 × 3Компоненты соседних пикселей одного кадра.Чёрный импульс сменился белым окружением.
Nonpeak 3 × 3Другая ранговая статистика того же локального соседства.В нашем случае чёрная точка осталась; результат хуже по MAE.
Среднее трёх кадровЗначение одной координаты в каждом выровненном кадре.Black/white/white даёт (0 + 1 + 1) / 3 = 2/3, точка ослаблена, но не исчезла.

Медиана — центральное значение в отсортированном наборе, а не сумма, поделённая на количество. Статистика применяется к компонентам цвета; полученный RGB не обязан быть целым цветом одного из соседних пикселей. Среднее серии использует другую ось: берёт одинаковую координату в разных кадрах. Оно не двигает изображения, чтобы найти кружку. Поэтому одинаковый размер ещё не означает правильное совмещение.

Слово radius в старом API требует аккуратности. Официальный текст описывает радиус, но в проверенной устаревшей реализации ImageMagick 6 значение radius после приведения к size_t передаётся прямо как ширина и высота StatisticImage. Здесь 3 означает 3 × 3, а не 7 × 7. Значение 1 оставило вход прежним; 0 выбирает размер автоматически. В наблюдении 0 совпал с 5: это не обещание наилучшего окна. Отрицательные или дробные настройки не используются как прикладная политика.

MAE в примерах — средняя абсолютная разница всех RGB-компонент в шкале 0…255 по сравнению с известным чистым рисунком. RMSE — корень из средней квадратичной разницы, сильнее учитывающий большие ошибки. Оба числа относятся к данному учебному эталону и не измеряют смысл или читаемость надписи. Они вычислены через PIXEL_CHAR до отдельной записи PNG8; рядом сохранены точные RGB16-хеши и сведения о реально закодированных файлах.

Запустить простой фильтр и правильно получить среднее последовательности

Три реальные операции над подготовленными входами: медиана, неподходящий Nonpeak и новое среднее трёх кадров
Три реальные операции над подготовленными входами: медиана, неподходящий Nonpeak и новое среднее трёх кадров

Каждый самостоятельный ZIP содержит example.php, пять PNG в base64 и полный legacy-noise-average-fixture.php. naRestore проверяет контрольные суммы и восстанавливает файлы; naFrames читает три шумных кадра, naClean читает известный чистый рисунок. naCall выполняет видимую строку через короткую функцию fn()=>..., временно сохраняет только E_DEPRECATED и возвращает прежний обработчик через finally. Helper не выбирает за вас фильтр и не делает скрытого усреднения. Стрелочные функции, функции и исключения объясняют эту служебную часть.

Nonpeak не является универсальным улучшением

$filtered = clone $noisy;
$filtered->reduceNoiseImage(3);

Синтаксис похож на медианный вызов, но алгоритм другой. Точная IM6-реализация выбирает NonpeakStatistic; это не обещание безопасно сгладить любой контур. Следующий пример намеренно сохраняет неподходящий результат, чтобы было понятно: true означает выполненную операцию, а не повышение качества.

Увидеть реальный результат Nonpeak, который не подошёл этому рисунку

Вызов вернул true и изменил картинку, однако точка (27,45) осталась чёрной, а MAE выросла примерно до 15.9989. Здесь reduceNoiseImage не улучшил исходник. Это полезный отрицательный результат, а не успешная очистка по одному имени метода.

Увидеть реальный результат Nonpeak, который не подошёл этому рисункуПример для указанного окружения
<?php
declare(strict_types=1);
require __DIR__.'/legacy-noise-average-fixture.php';
naRestore();
$clean=naClean();$before=naHash($clean);
$frames=naFrames();$frameHashes=naFrameHashes($frames);
$image=clone $frames[0];
$call=naCall('reduce3',fn()=>$image->reduceNoiseImage(3));
$result=naImage($image,$clean,'legacy-noise-average-reduce.png');
$input=naImage($frames[0],$clean,'reduce-noisy8.png');
naDiagnostic('legacy-noise-reduce-minimal',['executed_api'=>'reduceNoiseImage','radius'=>3,'call'=>naRecord($call),'images'=>['noisy'=>$input,'reduce'=>$result],
    'source_unchanged'=>naHash($clean)===$before,'input_frames_unchanged'=>naFrameHashes($frames)===$frameHashes,
    'checks'=>['true_two_warnings'=>$call['value']===true&&$call['deprecations']===2,
        'actual_change'=>naHash($image)!==naHash($frames[0]),'not_claimed_improvement'=>$result['error_to_clean_PIXEl_CHAR_before_PNG8']['MAE']>$input['error_to_clean_PIXEl_CHAR_before_PNG8']['MAE'],
        'impulse_can_remain'=>$result['samples']['impulse1']['r']==0.0,
        'source_preserved'=>naHash($clean)===$before&&naFrameHashes($frames)===$frameHashes]]);
echo "legacy-noise-average-reduce.png\nreduce-noisy8.png\nmetrics.json\nreduce-radius=3 returned=1 deprecations=2 fixture-error-increased=1 input-preserved=1\n";

Вызов вернул true и изменил картинку, однако точка (27,45) осталась чёрной, а MAE выросла примерно до 15.9989. Здесь reduceNoiseImage не улучшил исходник. Это полезный отрицательный результат, а не успешная очистка по одному имени метода. Каждый ZIP самостоятельный: example.php, пять PNG в base64 и legacy-noise-average-fixture.php. Распакуйте рядом и выполните php example.php. naRestore проверяет SHA и восстанавливает точные входы; шум не генерируется заново. naFrames открывает три кадра, naFreshSequence добавляет их копии в новый Imagick и ставит первый итератор; изучаемый averageImages остаётся виден в основном коде. naCall временно сохраняет только E_DEPRECATED и восстанавливает handler через finally. naImage измеряет объект до отдельной записи PNG8; naCompare составляет нативную полосу без масштабирования. Полный helper открыт в последнем разделе. Проверенная среда: PHP 8.3.6 / Imagick 3.7.0 / IM6.9.12-98 Q16, Ubuntu WSL; исполнение устаревших median/reduce в Windows IM7 не заявлено.

Ожидаемый вывод проверенной программы
legacy-noise-average-reduce.png
reduce-noisy8.png
metrics.json
reduce-radius=3 returned=1 deprecations=2 fixture-error-increased=1 input-preserved=1

Один объект-последовательность и новый объект-результат

$sequence = new Imagick();
$sequence->addImage($frame1);
$sequence->addImage($frame2);
$sequence->addImage($frame3);
$sequence->setFirstIterator();
$mean = $sequence->averageImages();

new Imagick создаёт пустой контейнер, три addImage добавляют кадры в него. Это не PHP-массив параметров averageImages: у изучаемого метода скобки пустые. setFirstIterator явно выбирает первый кадр перед вызовом. Переменная $mean получает другой объект с усреднённой картинкой; если не сохранить возвращённый объект, исходная последовательность сама не станет результатом. В архиве исходные кадры добавлены как clone, чтобы каждый опыт имел независимые данные. Последовательности Imagick объясняют устройство контейнера.

Усреднить три выровненных кадра и сохранить новый результат

Один Imagick содержит три кадра; averageImages без параметров вернул отдельный объект с одним кадром 400 × 320. В точке (27,45) среднее black/white/white равно 2/3. Точки стали менее контрастными, но не исчезли; подпись и подчёркивание сохраняются лучше, чем после медианы.

Усреднить три выровненных кадра и сохранить новый результатПример для указанного окружения
<?php
declare(strict_types=1);
require __DIR__.'/legacy-noise-average-fixture.php';
naRestore();
$clean=naClean();$before=naHash($clean);
$frames=naFrames();$frameHashes=naFrameHashes($frames);
$sequence=new Imagick();
$sequence->addImage(clone $frames[0]);$sequence->addImage(clone $frames[1]);$sequence->addImage(clone $frames[2]);
$sequence->setFirstIterator();$iteratorBefore=$sequence->getIteratorIndex();
$call=naCall('average',fn()=>$sequence->averageImages());
$mean=$call['value'];
$result=naImage($mean,$clean,'legacy-noise-average-average.png');
foreach($frames as $index=>$frame){naSave($frame,'average-frame'.($index+1).'-8.png');}
naDiagnostic('legacy-noise-average-minimal',['executed_api'=>'averageImages','call'=>naRecord($call),'images'=>['mean'=>$result],
    'sequence'=>['count'=>$sequence->getNumberImages(),'iterator_before'=>$iteratorBefore,'iterator_after'=>$sequence->getIteratorIndex()],
    'returned_new_object'=>$mean!==$sequence,'input_frames_unchanged'=>naFrameHashes($frames)===$frameHashes,'source_unchanged'=>naHash($clean)===$before,
    'checks'=>['new_single_image'=>$mean instanceof Imagick&&$mean!==$sequence&&$mean->getNumberImages()===1,
        'three_frames_first_iterator'=>$sequence->getNumberImages()===3&&$iteratorBefore===0&&$sequence->getIteratorIndex()===0,
        'no_runtime_deprecation'=>$call['deprecations']===0,'same_coordinate_mean'=>naClose($result['samples']['impulse1']['r'],2/3),
        'fixture_max_error_85'=>$result['error_to_clean_PIXEl_CHAR_before_PNG8']['max']===85,
        'source_preserved'=>naHash($clean)===$before&&naFrameHashes($frames)===$frameHashes]]);
echo "legacy-noise-average-average.png\naverage-frame1-8.png\naverage-frame2-8.png\naverage-frame3-8.png\nmetrics.json\nframes=3 result-images=1 returned-new=1 iterator=0 input-preserved=1\n";

Один Imagick содержит три кадра; averageImages без параметров вернул отдельный объект с одним кадром 400 × 320. В точке (27,45) среднее black/white/white равно 2/3. Точки стали менее контрастными, но не исчезли; подпись и подчёркивание сохраняются лучше, чем после медианы. Каждый ZIP самостоятельный: example.php, пять PNG в base64 и legacy-noise-average-fixture.php. Распакуйте рядом и выполните php example.php. naRestore проверяет SHA и восстанавливает точные входы; шум не генерируется заново. naFrames открывает три кадра, naFreshSequence добавляет их копии в новый Imagick и ставит первый итератор; изучаемый averageImages остаётся виден в основном коде. naCall временно сохраняет только E_DEPRECATED и восстанавливает handler через finally. naImage измеряет объект до отдельной записи PNG8; naCompare составляет нативную полосу без масштабирования. Полный helper открыт в последнем разделе. Проверенная среда: PHP 8.3.6 / Imagick 3.7.0 / IM6.9.12-98 Q16, Ubuntu WSL; исполнение устаревших median/reduce в Windows IM7 не заявлено.

Ожидаемый вывод проверенной программы
legacy-noise-average-average.png
average-frame1-8.png
average-frame2-8.png
average-frame3-8.png
metrics.json
frames=3 result-images=1 returned-new=1 iterator=0 input-preserved=1

В проверенном запуске среднее сохранило мелкую линию лучше локальной медианы, но оставило больше бледных точек. В точке (27,45) один из кадров чёрный, два белые, поэтому значение 2/3 не является полностью белым. Для всех трёх кадров предмет должен стоять в одинаковом месте, а цветовое представление должно совпадать; метод не проверяет эти смысловые условия за пользователя.

Выбрать подходящий компромисс и перенести конкретный алгоритм

Реальные современные алгоритмы, среднее смещённых кадров и более сильная медиана: перенос кода не отменяет потери деталей и призраков
Реальные современные алгоритмы, среднее смещённых кадров и более сильная медиана: перенос кода не отменяет потери деталей и призраков

Для старого редактора подготовим сравнение на одном известном входе: чистый рисунок, первый повреждённый кадр, медиана, Nonpeak и среднее выровненной серии. Каждый локальный фильтр работает на clone. Для среднего создаётся свежая последовательность с первым итератором. Массивы $calls и $images сохраняют подписанные результаты, предупреждения и измерения; это удобная организация уже знакомых коротких операций. Массивы не заменяют сам объект-последовательность.

Выбрать обработку товарной схемы по реальным результатам и ограничениям

Сравнены известный чистый рисунок, повреждённый кадр, медиана, Nonpeak и среднее трёх выровненных кадров. Ни один bool не выбирает лучший вариант: учитываем точки, читаемость MUG01, тонкую линию и допустимые изменения.

Выбрать обработку товарной схемы по реальным результатам и ограничениямПример для указанного окружения
<?php
declare(strict_types=1);
require __DIR__.'/legacy-noise-average-fixture.php';
naRestore();
$clean=naClean();$before=naHash($clean);
$frames=naFrames();$frameHashes=naFrameHashes($frames);
$median=clone $frames[0];$reduce=clone $frames[0];
$calls['median']=naCall('median',fn()=>$median->medianFilterImage(3));
$calls['reduce']=naCall('reduce',fn()=>$reduce->reduceNoiseImage(3));
$sequence=naFreshSequence($frames);$sequence->setFirstIterator();
$calls['average']=naCall('average',fn()=>$sequence->averageImages());$mean=$calls['average']['value'];
$images=['clean'=>naImage($clean,$clean,'workflow-clean8.png'),'noisy'=>naImage($frames[0],$clean,'workflow-noisy8.png'),
    'median'=>naImage($median,$clean,'workflow-median8.png'),'reduce'=>naImage($reduce,$clean,'workflow-reduce8.png'),'mean'=>naImage($mean,$clean,'workflow-mean8.png')];
$rects=naCompare([$clean,$frames[0],$median,$reduce,$mean],'legacy-noise-average-workflow.png');
naDiagnostic('legacy-noise-average-workflow',['executed_apis'=>['medianFilterImage','reduceNoiseImage','averageImages'],'radius'=>3,'frame_count'=>3,
    'calls'=>array_map('naRecord',$calls),'images'=>$images,'panel_keys'=>['clean','noisy','median','reduce','mean'],'panel_geometry'=>$rects,
    'source_unchanged'=>naHash($clean)===$before,'input_frames_unchanged'=>naFrameHashes($frames)===$frameHashes,
    'checks'=>['median_success'=>$calls['median']['value']===true&&$calls['median']['deprecations']===2,
        'reduce_success_not_quality'=>$calls['reduce']['value']===true&&$calls['reduce']['deprecations']===2,
        'mean_new_object'=>$mean instanceof Imagick&&$mean!==$sequence&&$calls['average']['deprecations']===0,
        'median_fixture_MAE_lower'=>$images['median']['error_to_clean_PIXEl_CHAR_before_PNG8']['MAE']<$images['noisy']['error_to_clean_PIXEl_CHAR_before_PNG8']['MAE'],
        'reduce_fixture_MAE_higher'=>$images['reduce']['error_to_clean_PIXEl_CHAR_before_PNG8']['MAE']>$images['noisy']['error_to_clean_PIXEl_CHAR_before_PNG8']['MAE'],
        'mean_impulse_attenuated'=>naClose($images['mean']['samples']['impulse1']['r'],2/3),
        'source_preserved'=>naHash($clean)===$before&&naFrameHashes($frames)===$frameHashes]]);
echo "legacy-noise-average-workflow.png\nworkflow-clean8.png\nworkflow-noisy8.png\nworkflow-median8.png\nworkflow-reduce8.png\nworkflow-mean8.png\nmetrics.json\nmedian-MAE-lower=1 reduce-MAE-higher=1 mean-impulse-attenuated=1 input-preserved=1\n";

Сравнены известный чистый рисунок, повреждённый кадр, медиана, Nonpeak и среднее трёх выровненных кадров. Ни один bool не выбирает лучший вариант: учитываем точки, читаемость MUG01, тонкую линию и допустимые изменения. Каждый ZIP самостоятельный: example.php, пять PNG в base64 и legacy-noise-average-fixture.php. Распакуйте рядом и выполните php example.php. naRestore проверяет SHA и восстанавливает точные входы; шум не генерируется заново. naFrames открывает три кадра, naFreshSequence добавляет их копии в новый Imagick и ставит первый итератор; изучаемый averageImages остаётся виден в основном коде. naCall временно сохраняет только E_DEPRECATED и восстанавливает handler через finally. naImage измеряет объект до отдельной записи PNG8; naCompare составляет нативную полосу без масштабирования. Полный helper открыт в последнем разделе. Проверенная среда: PHP 8.3.6 / Imagick 3.7.0 / IM6.9.12-98 Q16, Ubuntu WSL; исполнение устаревших median/reduce в Windows IM7 не заявлено.

Ожидаемый вывод проверенной программы
legacy-noise-average-workflow.png
workflow-clean8.png
workflow-noisy8.png
workflow-median8.png
workflow-reduce8.png
workflow-mean8.png
metrics.json
median-MAE-lower=1 reduce-MAE-higher=1 mean-impulse-attenuated=1 input-preserved=1
Вариант точного учебного входаMAE до PNG8Что надо увидеть
Первый повреждённый кадр1.9914Отдельные чёрные/белые дефекты.
Медиана 3 × 30.6366Точек меньше, но тонкая линия и MUG01 повреждены.
Nonpeak 3 × 315.9989Неподходящее преобразование: ошибка выросла.
Среднее трёх выровненных кадров1.8238Меньше контраст дефектов, детали не усреднялись по соседству.
Среднее с третьим кадром, сдвинутым на 12 px4.9208Призрак и увеличенная ошибка из-за несовмещения.

Явные современные операции и ограничения

Для новой записи кода statisticImage позволяет назвать статистику и размеры окна явно. Для серии evaluateImages с EVALUATE_MEAN называет арифметическое среднее. В следующей программе каждая современная операция сравнивается со своим legacy-вызовом на точных одинаковых входах: MEDIAN соответствует медиане, NONPEAK — reduceNoise, Mean — averageImages. Совпадение не говорит, что все эти алгоритмы между собой одинаковы или одинаково полезны.

Перенести алгоритмы, показать смещённый призрак и три отказа

Современные MEDIAN/NONPEAK 3 × 3 и Mean совпали с соответствующими legacy-результатами по всем RGB16-компонентам этого входа. Смещение третьего кадра на 12 пикселей ухудшило среднее и создало призрачные контуры. Окно медианы 5 × 5 сильнее повредило детали; три пустых объекта дали исключения.

Перенести алгоритмы, показать смещённый призрак и три отказаПример для указанного окружения
<?php
declare(strict_types=1);
require __DIR__.'/legacy-noise-average-fixture.php';
naRestore();
$clean=naClean();$before=naHash($clean);
$frames=naFrames();$frameHashes=naFrameHashes($frames);
$legacyMedian=clone $frames[0];$legacyReduce=clone $frames[0];
$calls['legacy_median']=naCall('legacy_median',fn()=>$legacyMedian->medianFilterImage(3));
$calls['legacy_reduce']=naCall('legacy_reduce',fn()=>$legacyReduce->reduceNoiseImage(3));
$legacySequence=naFreshSequence($frames);$legacySequence->setFirstIterator();
$calls['legacy_mean']=naCall('legacy_mean',fn()=>$legacySequence->averageImages());$legacyMean=$calls['legacy_mean']['value'];
$median=clone $frames[0];$reduce=clone $frames[0];
$calls['modern_median']=naCall('modern_median',fn()=>$median->statisticImage(Imagick::STATISTIC_MEDIAN,3,3,Imagick::CHANNEL_DEFAULT));
$calls['modern_reduce']=naCall('modern_reduce',fn()=>$reduce->statisticImage(Imagick::STATISTIC_NONPEAK,3,3,Imagick::CHANNEL_DEFAULT));
$modernSequence=naFreshSequence($frames);$modernSequence->setFirstIterator();
$calls['modern_mean']=naCall('modern_mean',fn()=>$modernSequence->evaluateImages(Imagick::EVALUATE_MEAN));$mean=$calls['modern_mean']['value'];
$shifted=new Imagick(__DIR__.'/shifted-frame.png');
$badSequence=naFreshSequence([$frames[0],$frames[1],$shifted]);$badSequence->setFirstIterator();
$calls['ghost']=naCall('ghost',fn()=>$badSequence->averageImages());$ghost=$calls['ghost']['value'];
$median5=clone $frames[0];$calls['median5']=naCall('median5',fn()=>$median5->medianFilterImage(5));
$images=['modern_median'=>naImage($median,$clean,'alternatives-median8.png'),'modern_reduce'=>naImage($reduce,$clean,'alternatives-reduce8.png'),
    'modern_mean'=>naImage($mean,$clean,'alternatives-mean8.png'),'ghost'=>naImage($ghost,$clean,'alternatives-ghost8.png'),
    'median5'=>naImage($median5,$clean,'alternatives-median5-8.png')];
naSave($shifted,'alternatives-shifted-frame8.png');
$pairs=['median'=>naHash($median)===naHash($legacyMedian),'reduce'=>naHash($reduce)===naHash($legacyReduce),'mean'=>naHash($mean)===naHash($legacyMean)];
$errors=[];
foreach(['medianFilterImage'=>[3],'reduceNoiseImage'=>[3],'averageImages'=>[]] as $method=>$args){$empty=new Imagick();$errors[$method]=naRecord(naCall('empty_'.$method,fn()=>$empty->$method(...$args)));}
$checks=['three_actual_algorithm_pairs'=>$pairs===['median'=>true,'reduce'=>true,'mean'=>true],
    'modern_calls_no_warning'=>$calls['modern_median']['deprecations']===0&&$calls['modern_reduce']['deprecations']===0&&$calls['modern_mean']['deprecations']===0,
    'shift_has_larger_error'=>$images['ghost']['error_to_clean_PIXEl_CHAR_before_PNG8']['MAE']>$images['modern_mean']['error_to_clean_PIXEl_CHAR_before_PNG8']['MAE'],
    'larger_median_not_unconditionally_better'=>$images['median5']['error_to_clean_PIXEl_CHAR_before_PNG8']['MAE']>$images['modern_median']['error_to_clean_PIXEl_CHAR_before_PNG8']['MAE'],
    'source_preserved'=>naHash($clean)===$before&&naFrameHashes($frames)===$frameHashes];
foreach($errors as $name=>$record){$checks['empty_'.$name.'_caught']=($record['error']['class']??null)==='ImagickException';}
$rects=naCompare([$median,$reduce,$mean,$ghost,$median5],'legacy-noise-average-alternatives.png');
naDiagnostic('legacy-noise-average-alternatives',['executed_apis'=>['medianFilterImage','reduceNoiseImage','averageImages','statisticImage','evaluateImages'],
    'calls'=>array_map('naRecord',$calls),'images'=>$images,'RGB16_equal_legacy'=>$pairs,'errors'=>$errors,'third_frame_shift_pixels'=>[12,0],
    'panel_keys'=>['modern_median','modern_reduce','modern_mean','ghost','median5'],'panel_geometry'=>$rects,
    'source_unchanged'=>naHash($clean)===$before,'input_frames_unchanged'=>naFrameHashes($frames)===$frameHashes,'checks'=>$checks]);
echo "legacy-noise-average-alternatives.png\nalternatives-median8.png\nalternatives-reduce8.png\nalternatives-mean8.png\nalternatives-ghost8.png\nalternatives-median5-8.png\nalternatives-shifted-frame8.png\nmetrics.json\nalgorithm-pairs=3 equal=3 shifted-frame=12px failures=3 input-preserved=1\n";

Современные MEDIAN/NONPEAK 3 × 3 и Mean совпали с соответствующими legacy-результатами по всем RGB16-компонентам этого входа. Смещение третьего кадра на 12 пикселей ухудшило среднее и создало призрачные контуры. Окно медианы 5 × 5 сильнее повредило детали; три пустых объекта дали исключения. Каждый ZIP самостоятельный: example.php, пять PNG в base64 и legacy-noise-average-fixture.php. Распакуйте рядом и выполните php example.php. naRestore проверяет SHA и восстанавливает точные входы; шум не генерируется заново. naFrames открывает три кадра, naFreshSequence добавляет их копии в новый Imagick и ставит первый итератор; изучаемый averageImages остаётся виден в основном коде. naCall временно сохраняет только E_DEPRECATED и восстанавливает handler через finally. naImage измеряет объект до отдельной записи PNG8; naCompare составляет нативную полосу без масштабирования. Полный helper открыт в последнем разделе. Проверенная среда: PHP 8.3.6 / Imagick 3.7.0 / IM6.9.12-98 Q16, Ubuntu WSL; исполнение устаревших median/reduce в Windows IM7 не заявлено.

Ожидаемый вывод проверенной программы
legacy-noise-average-alternatives.png
alternatives-median8.png
alternatives-reduce8.png
alternatives-mean8.png
alternatives-ghost8.png
alternatives-median5-8.png
alternatives-shifted-frame8.png
metrics.json
algorithm-pairs=3 equal=3 shifted-frame=12px failures=3 input-preserved=1

Последний кадр контрпримера сдвинут вправо на 12 пикселей на белом холсте и заранее сохранён в shifted-frame.png. Это явное известное несовмещение, а не попытка автоматической регистрации. Размер всё ещё 400 × 320; среднее складывает несовпавшие детали в одной координате и даёт призрачные контуры. Окно медианы 5 × 5 также не стало безусловно лучше: MAE 0.8723 выше, чем у 3 × 3, а детали сильнее сглажены.

Три обращения к пустому объекту дали ImagickException «Can not process empty Imagick object» и сохранены отдельно. Нативная авария во время первичного исследования была другим событием: она не обещана как catchable PHP-ошибка. В наших программах для каждого average/evaluate создаётся отдельный контейнер и явно устанавливается первый итератор; опасный вторичный/nonzero-index эксперимент в архивы не включён. История двух наблюдений, из которых первое аварийно, сохранена честно.

Сохранить полные контракты, исходные примеры и границы обработки

Назначение, параметры и результат

Imagick::medianFilterImage(float $radius): bool

Медианный фильтр обрабатывает одно текущее изображение: вместо компоненты пикселя берётся среднее по порядку значение в соседстве. Это медиана, не арифметическое среднее. Входной объект изменяется, при успехе возвращается bool true. Сохраните исходный кадр и фильтруйте clone. Одноцветные точки могут исчезнуть, но настоящая тонкая линия и маленькие буквы тоже могут исчезнуть: алгоритм не знает, какая деталь была ошибкой.

ПараметрСмысл
$radiusОбязательный float. Официальный текст называет его радиусом соседства. В точной IM6-реализации deprecated Core передаёт (size_t)radius непосредственно как ширину и высоту StatisticImage: 3 означает 3 × 3, а не 7 × 7. Значение 1 в нашем наблюдении оставило вход прежним. При 0 размер подбирается автоматически. Для прикладной политики выбирайте понятные положительные целые размеры; не выдавайте приведение отрицательных или дробных чисел в size_t за полезный способ настройки.

Официальный пример сохраняется целиком: функция читает realpath($imagePath), применяет @ к вызову и отдаёт blob с заголовком image/jpg. В нашем самостоятельном примере @ заменён ограниченным журналом предупреждений, вход объявлен, а PNG явно закодирован. Заголовок HTTP сам по себе не преобразует формат файла; realpath может вернуть false для отсутствующего входа.

Официальная доступность: PECL imagick 2, PECL imagick 3. Все три XML помечены deprecated с PECL Imagick 3.4.4. Однако фактические bindings различаются: medianFilterImage/reduceNoiseImage ограничены IM6 и дали по два E_DEPRECATED в проверенной среде; averageImages имеет современную IM7-ветку в исследованных 3.7/3.8 исходниках и не дал такого предупреждения в IM6. Не переносите один общий статус доступности на всю группу. Для нового явного кода рассмотрены statisticImage и evaluateImages.

Официальный раздел ошибок указывает ImagickException. На пустом объекте каждый из трёх методов действительно дал «Can not process empty Imagick object». Это отличается от успешного вызова без изменения при размере 1 или успешного, но неподходящего по качеству Nonpeak. Предупреждения об устаревании сохраняются отдельно от ошибок; ввод и формат результата проверяются явно.

Полный официальный XML с описанием, параметрами, возвратом и оригинальным примером, если он есть
<?xml version="1.0" encoding="utf-8"?>
<!-- $Revision$ -->
<refentry xmlns="http://docbook.org/ns/docbook" xml:id="imagick.medianfilterimage">
 <refnamediv>
  <refname>Imagick::medianFilterImage</refname>
  <refpurpose>Applies a digital filter</refpurpose>
 </refnamediv>

 <refsynopsisdiv>
   &imagick.deprecated.function-3-4-4;
 </refsynopsisdiv>

 <refsect1 role="description">
  &reftitle.description;
  <methodsynopsis>
   <modifier>public</modifier> <type>bool</type><methodname>Imagick::medianFilterImage</methodname>
   <methodparam><type>float</type><parameter>radius</parameter></methodparam>
  </methodsynopsis>
  <para>
   Applies a digital filter that improves the quality of a
   noisy image.  Each pixel is replaced by the median in a
   set of neighboring pixels as defined by radius.
  </para>
 </refsect1>

 <refsect1 role="parameters">
  &reftitle.parameters;
  <para>
   <variablelist>
    <varlistentry>
     <term><parameter>radius</parameter></term>
     <listitem>
      <para>
      The radius of the pixel neighborhood.
      </para>
     </listitem>
    </varlistentry>
   </variablelist>
  </para>
 </refsect1>

 <refsect1 role="returnvalues">
  &reftitle.returnvalues;
  <para>
   &imagick.return.success;
  </para>
 </refsect1>

 <refsect1 role="errors">
  &reftitle.errors;
  <para>
   &imagick.imagick.throws;
  </para>
 </refsect1>



 <refsect1 role="examples">
  &reftitle.examples;
  <para>
    <example>
      <title> <function>Imagick::medianFilterImage</function></title>
      <programlisting role="php">
      <![CDATA[
<?php
function medianFilterImage($radius, $imagePath) {
    $imagick = new \Imagick(realpath($imagePath));
    @$imagick->medianFilterImage($radius);
    header("Content-Type: image/jpg");
    echo $imagick->getImageBlob();
}

?>
]]>
      </programlisting>
    </example>
  </para>
 </refsect1>

</refentry>

<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:t
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
indent-tabs-mode:nil
sgml-parent-document:nil
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
vim600: syn=xml fen fdm=syntax fdl=2 si
vim: et tw=78 syn=sgml
vi: ts=1 sw=1
-->

Назначение, параметры и результат

Imagick::reduceNoiseImage(float $radius): bool

Официальное описание говорит о сглаживании контуров с сохранением информации о границах и замене пикселя близким по значению соседом. Точная исследованная IM6-реализация делегирует StatisticImage с NonpeakStatistic. Это отдельная покомпонентная ранговая операция, а не синоним медианы или обещание выбрать правильный RGB-пиксель. В нашем контролируемом примере она ухудшила результат: успешный true не является оценкой качества.

ПараметрСмысл
$radiusОбязательный float. Согласно полному описанию соседство задаётся radius, а 0 выбирает подходящий размер автоматически. Точный IM6 Core передаёт (size_t)radius как ширину и высоту Nonpeak-окна; здесь 3 = 3 × 3. Автоматический 0 не гарантирует лучший размер: на этом входе в наблюдении результат 0 совпал с 5 и дал ещё большую ошибку. Метод меняет текущее изображение и возвращает bool true при успехе.

Полный официальный пример с функцией reduceNoiseImage($imagePath,$reduceNoise), @, realpath и HTTP-выводом сохранён. Наш код не подавляет все предупреждения и не предполагает, что название метода само подтверждает очистку. Для новых вызовов используйте явно выбранную statisticImage-операцию; её подходящий тип и размер всё равно определяются задачей.

Официальная доступность: PECL imagick 2, PECL imagick 3. Все три XML помечены deprecated с PECL Imagick 3.4.4. Однако фактические bindings различаются: medianFilterImage/reduceNoiseImage ограничены IM6 и дали по два E_DEPRECATED в проверенной среде; averageImages имеет современную IM7-ветку в исследованных 3.7/3.8 исходниках и не дал такого предупреждения в IM6. Не переносите один общий статус доступности на всю группу. Для нового явного кода рассмотрены statisticImage и evaluateImages.

Официальный раздел ошибок указывает ImagickException. На пустом объекте каждый из трёх методов действительно дал «Can not process empty Imagick object». Это отличается от успешного вызова без изменения при размере 1 или успешного, но неподходящего по качеству Nonpeak. Предупреждения об устаревании сохраняются отдельно от ошибок; ввод и формат результата проверяются явно.

Полный официальный XML с описанием, параметрами, возвратом и оригинальным примером, если он есть
<?xml version="1.0" encoding="utf-8"?>
<!-- $Revision$ -->
<refentry xmlns="http://docbook.org/ns/docbook" xml:id="imagick.reducenoiseimage">
 <refnamediv>
  <refname>Imagick::reduceNoiseImage</refname>
  <refpurpose>Smooths the contours of an image</refpurpose>
 </refnamediv>

 <refsynopsisdiv>
   &imagick.deprecated.function-3-4-4;
 </refsynopsisdiv>

 <refsect1 role="description">
  &reftitle.description;
  <methodsynopsis>
   <modifier>public</modifier> <type>bool</type><methodname>Imagick::reduceNoiseImage</methodname>
   <methodparam><type>float</type><parameter>radius</parameter></methodparam>
  </methodsynopsis>
  <para>
   Smooths the contours of an image while still preserving edge
   information. The algorithm works by replacing each pixel with
   its neighbor closest in value. A neighbor is defined by radius.
   Use a radius of 0 and Imagick::reduceNoiseImage() selects a
   suitable radius for you.
  </para>
 </refsect1>

 <refsect1 role="parameters">
  &reftitle.parameters;
  <para>
   <variablelist>
    <varlistentry>
     <term><parameter>radius</parameter></term>
     <listitem>
      <para>
      </para>
     </listitem>
    </varlistentry>
   </variablelist>
  </para>
 </refsect1>

 <refsect1 role="returnvalues">
  &reftitle.returnvalues;
  <para>
   &imagick.return.success;
  </para>
 </refsect1>

 <refsect1 role="errors">
  &reftitle.errors;
  <para>
   &imagick.imagick.throws;
  </para>
 </refsect1>



 <refsect1 role="examples">
  &reftitle.examples;
  <para>
    <example>
      <title> <function>Imagick::reduceNoiseImage</function></title>
      <programlisting role="php">
      <![CDATA[
<?php
function reduceNoiseImage($imagePath, $reduceNoise) {
    $imagick = new \Imagick(realpath($imagePath));
    @$imagick->reduceNoiseImage($reduceNoise);
    header("Content-Type: image/jpg");
    echo $imagick->getImageBlob();
}

?>
]]>
      </programlisting>
    </example>
  </para>
 </refsect1>

</refentry>

<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:t
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
indent-tabs-mode:nil
sgml-parent-document:nil
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
vim600: syn=xml fen fdm=syntax fdl=2 si
vim: et tw=78 syn=sgml
vi: ts=1 sw=1
-->

Назначение, параметры и результат

Imagick::averageImages(): Imagick

Аргументов нет. AverageImages читает последовательность кадров из самого объекта Imagick и возвращает новый Imagick с усреднённым изображением. Массив объектов не передаётся в скобки: кадры предварительно добавляют через addImage. В показанном сценарии один контейнер содержит три одинаково выровненных кадра; результат — другой контейнер с одним кадром. Исходные изображения не заменяются результатом автоматически.

Среднее считается по соответствующим координатам и компонентам кадров, а не по соседству одного кадра. Проверяйте одинаковую геометрию, смысловое выравнивание и согласованное цветовое представление заранее. Метод не совмещает объекты, не распознаёт движение и не исправляет разные экспозиции/профили. Смещённый третий кадр создаёт полупрозрачный призрак. Наша проверка 400 × 320 — политика примера, а не утверждение, что native API обязательно отвергнет любой другой размер.

Перед усреднением используем свежую последовательность и явный setFirstIterator. При первичном исследовании native-библиотека аварийно остановилась с C assertion после сохранения первого результата, до второго/nonzero-index результата и JSON. Точная подстадия state/call/output не установлена; мы не утверждаем, что index 2 всегда падает. Опасный путь не повторяется и не включён в архивы. Такая авария не является обычным PHP-исключением, которое обещано поймать через catch. Исправленное наблюдение и все учебные вызовы используют свежий контейнер с первым итератором.

Официальная доступность: PECL imagick 2, PECL imagick 3. Все три XML помечены deprecated с PECL Imagick 3.4.4. Однако фактические bindings различаются: medianFilterImage/reduceNoiseImage ограничены IM6 и дали по два E_DEPRECATED в проверенной среде; averageImages имеет современную IM7-ветку в исследованных 3.7/3.8 исходниках и не дал такого предупреждения в IM6. Не переносите один общий статус доступности на всю группу. Для нового явного кода рассмотрены statisticImage и evaluateImages.

Официальный раздел ошибок указывает ImagickException. На пустом объекте каждый из трёх методов действительно дал «Can not process empty Imagick object». Это отличается от успешного вызова без изменения при размере 1 или успешного, но неподходящего по качеству Nonpeak. Предупреждения об устаревании сохраняются отдельно от ошибок; ввод и формат результата проверяются явно.

Полный официальный XML с описанием, параметрами, возвратом и оригинальным примером, если он есть
<?xml version="1.0" encoding="utf-8"?>
<!-- $Revision$ -->
<refentry xmlns="http://docbook.org/ns/docbook" xml:id="imagick.averageimages">
 <refnamediv>
  <refname>Imagick::averageImages</refname>
  <refpurpose>Average a set of images</refpurpose>
 </refnamediv>

 <refsynopsisdiv>
   &imagick.deprecated.function-3-4-4;
 </refsynopsisdiv>

 <refsect1 role="description">
  &reftitle.description;
  <methodsynopsis>
   <modifier>public</modifier> <type>Imagick</type><methodname>Imagick::averageImages</methodname>
   <void/>
  </methodsynopsis>
  <para>
   Average a set of images.
  </para>
 </refsect1>

 <refsect1 role="parameters">
  &reftitle.parameters;
  &no.function.parameters;
 </refsect1>

 <refsect1 role="returnvalues">
  &reftitle.returnvalues;
  <para>
   Returns a new Imagick object on success.
  </para>
 </refsect1>

 <refsect1 role="errors">
  &reftitle.errors;
  <para>
   &imagick.imagick.throws;
  </para>
 </refsect1>

</refentry>

<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:t
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
indent-tabs-mode:nil
sgml-parent-document:nil
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
vim600: syn=xml fen fdm=syntax fdl=2 si
vim: et tw=78 syn=sgml
vi: ts=1 sw=1
-->

Входы, стоимость и воспроизводимость

Пять сохранённых входных PNG имеют одинаковые размер, RGB-представление и глубину 8 бит. Три шумных кадра созданы из собственной картинки: для i от 0 до 1999 координаты x = 8 + ((i × 73 + seed × 19) mod 384), y = 8 + ((i × 47 + seed × 37) mod 304), чётные i — black, нечётные — white, seed равен 1,2,3. Это 2 000 команд рисования на кадр, не обещание ровно 2 000 изменённых пикселей: некоторые значения уже совпадали с рисунком. Повторный запуск примеров открывает готовые файлы, не повторяет генерацию.

Для среднего нужно хранить несколько кадров и читать соответствующие пиксели каждого; больше кадров увеличивает объём работы и памяти. Локальный фильтр обрабатывает соседство каждого пикселя; размер окна меняет и стоимость, и характер сглаживания. Универсального ускорения или безопасного радиуса здесь нет. Подбирайте ограниченные варианты под задачу и сохраняйте исходники, особенно если важны мелкий текст и точные линии.

Проверенная среда — PHP 8.3.6 / Imagick 3.7.0 / ImageMagick 6.9.12-98 Q16 в Ubuntu WSL из официальных пакетов. Эти версии описывают реально выполненный сценарий, а не обещание любой последней сборки. Для соответствующей Ubuntu установка и запуск выглядят так:

sudo apt install php8.3-cli php8.3-imagick
php example.php

Упражнение: доступны три одинаково выровненных кадра этикетки, а тонкую линию обязательно сохранить. Сначала сравните среднее с исходными кадрами и проверьте, приемлемы ли оставшиеся бледные точки. Не выбирайте сильную медиану только потому, что число MAE меньше. Если третий кадр сместился, сначала решите задачу совмещения или исключите его по ясной политике; усреднение само не исправит ошибку.

Полный вспомогательный PHP каждого самостоятельного архива
<?php
declare(strict_types=1);
function naRestore():void {
    $hashes=json_decode('{"clean.png":"b6af02ed97020582a27e993a1565de41e23ea97ff7be11ac132d68204d56d483","noisy-1.png":"6a68283664f1a88154509548ea6a15d33d29393aed69d13c1b3eb845a42676da","noisy-2.png":"78801b897efe2fc0bf11850bc91fcaa3f8e1bfe9773e9142a62fa6e9f9a14e90","noisy-3.png":"3ea4c9c769735295ede4eaf51c7071979b7bc886b77669302e87b8160bfd2903","shifted-frame.png":"f7acc549ba3e6dfe0b8ffb214d5718142ba878f323fa5aaeba4c3771ba09c806"}',true,512,JSON_THROW_ON_ERROR);
    foreach($hashes as $filename=>$hash){
        $raw=base64_decode((string)file_get_contents(__DIR__.'/'.$filename.'.b64'),true);
        if($raw===false||hash('sha256',$raw)!==$hash||file_put_contents(__DIR__.'/'.$filename,$raw)===false){throw new RuntimeException('Own input PNG missing or changed');}
    }
}
function naClean():Imagick {return new Imagick(__DIR__.'/clean.png');}
function naFrames():array {return [new Imagick(__DIR__.'/noisy-1.png'),new Imagick(__DIR__.'/noisy-2.png'),new Imagick(__DIR__.'/noisy-3.png')];}
function naHash(Imagick $image):string {return hash('sha256',json_encode($image->exportImagePixels(0,0,400,320,'RGB',Imagick::PIXEL_SHORT),JSON_THROW_ON_ERROR));}
function naFrameHashes(array $frames):array {return array_map('naHash',$frames);}
function naFreshSequence(array $frames):Imagick {
    $sequence=new Imagick();
    foreach($frames as $frame){
        if($frame->getImageWidth()!==400||$frame->getImageHeight()!==320){throw new InvalidArgumentException('This project requires aligned 400x320 frames');}
        $sequence->addImage(clone $frame);
    }
    $sequence->setFirstIterator();return $sequence;
}
function naCall(string $label,callable $operation):array {
    $warnings=[];$out=['label'=>$label];
    set_error_handler(function(int $severity,string $message)use(&$warnings):bool {
        if($severity!==E_DEPRECATED){return false;}
        $warnings[]=['severity'=>$severity,'message'=>$message];return true;
    });
    try{$out['value']=$operation();}
    catch(Throwable $error){$out['error']=['class'=>get_class($error),'message'=>$error->getMessage()];}
    finally{restore_error_handler();}
    $out['warnings']=$warnings;$out['deprecations']=count($warnings);return $out;
}
function naRecord(array $call):array {
    if(array_key_exists('value',$call)){
        $value=$call['value'];unset($call['value']);
        $call['returned']=$value instanceof Imagick?['class'=>get_class($value),'count'=>$value->getNumberImages(),'geometry'=>[$value->getImageWidth(),$value->getImageHeight()]]:$value;
    }
    return $call;
}
function naSave(Imagick $image,string $filename):void {
    $copy=clone $image;$copy->stripImage();$copy->setImageFormat('png');$copy->setImageDepth(8);
    $copy->setOption('png:bit-depth','8');$copy->setOption('png:color-type','2');$copy->setOption('png:exclude-chunk','all');
    if(!$copy->writeImage(__DIR__.'/'.$filename)){throw new RuntimeException('PNG write failed');}
}
function naSamples(Imagick $image):array {
    $out=[];foreach(['corner'=>[0,0],'impulse1'=>[27,45],'inside'=>[120,120],'center'=>[200,160],'edge'=>[150,100]] as $key=>$xy){$out[$key]=$image->getImagePixelColor(...$xy)->getColor(1);}return $out;
}
function naError(Imagick $image,Imagick $clean):array {
    $a=$image->exportImagePixels(0,0,400,320,'RGB',Imagick::PIXEL_CHAR);$b=$clean->exportImagePixels(0,0,400,320,'RGB',Imagick::PIXEL_CHAR);
    $sum=0;$squares=0;$maximum=0;$changed=0;
    foreach($a as $i=>$value){$delta=abs($value-$b[$i]);$sum+=$delta;$squares+=$delta*$delta;$maximum=max($maximum,$delta);if($delta!==0){$changed++;}}
    return ['components'=>count($a),'changed_components'=>$changed,'max'=>$maximum,'MAE'=>$sum/count($a),'RMSE'=>sqrt($squares/count($a))];
}
function naImage(Imagick $image,Imagick $clean,string $filename):array {
    $row=['geometry'=>[$image->getImageWidth(),$image->getImageHeight()],'RGB16_sha256'=>naHash($image),'samples'=>naSamples($image),
        'error_to_clean_PIXEl_CHAR_before_PNG8'=>naError($image,$clean)];
    naSave($image,$filename);$encoded=new Imagick(__DIR__.'/'.$filename);
    $row['encoded_png']=['filename'=>$filename,'samples'=>naSamples($encoded),'RGB16_sha256'=>naHash($encoded)];return $row;
}
function naCompare(array $images,string $filename):array {
    $board=new Imagick();$board->newImage(400*count($images),320,'white','png');$rects=[];
    foreach($images as $i=>$image){$board->compositeImage($image,Imagick::COMPOSITE_OVER,400*$i,0);$rects[]=['x'=>400*$i,'y'=>0,'width'=>400,'height'=>320];}
    naSave($board,$filename);return $rects;
}
function naClose(float $a,float $b):bool {return abs($a-$b)<1.0e-10;}
function naDiagnostic(string $id,array $data):void {
    $doc=['schema'=>'aen-legacy-noise-average-program-diagnostics-v1','example_id'=>$id,
        'runtime'=>['php'=>PHP_VERSION,'imagick'=>phpversion('imagick'),'imagemagick'=>Imagick::getVersion()]]+$data;
    if(file_put_contents(__DIR__.'/metrics.json',json_encode($doc,JSON_PRETTY_PRINT|JSON_THROW_ON_ERROR)."\n")===false){throw new RuntimeException('Cannot write measurements');}
}

В helper нет генератора случайного шума и скрытого вызова median/reduce/average; изучаемые строки находятся в example.php. Новый контейнер и setFirstIterator являются явной политикой этих примеров. Нормализованные samples, RGB16-хеши и ошибки до PNG8 отделены от encoded_png после реальной записи. Для HTTP отправляйте бинарную картинку отдельно от журнала. Далее: локальная статистика, последовательности, глубина цвета и работа с известными цветовыми дефектами.

Функции и методы этой темы

Откройте карточку, чтобы увидеть договор функции, примеры, ограничения и связанные инструменты.

Imagick::medianFilterImageТочечный шум, сохранение мелких деталей и среднее выровненных кадров

PECL imagick 2, PECL imagick 3 · imagick

Imagick::medianFilterImage(float $radius): bool

Назначение, параметры и результат

Imagick::medianFilterImage(float $radius): bool

Медианный фильтр обрабатывает одно текущее изображение: вместо компоненты пикселя берётся среднее по порядку значение в соседстве. Это медиана, не арифметическое среднее. Входной объект изменяется, при успехе возвращается bool true. Сохраните исходный кадр и фильтруйте clone. Одноцветные точки могут исчезнуть, но настоящая тонкая линия и маленькие буквы тоже могут исчезнуть: алгоритм не знает, какая деталь была ошибкой.

ПараметрСмысл
$radiusОбязательный float. Официальный текст называет его радиусом соседства. В точной IM6-реализации deprecated Core передаёт (size_t)radius непосредственно как ширину и высоту StatisticImage: 3 означает 3 × 3, а не 7 × 7. Значение 1 в нашем наблюдении оставило вход прежним. При 0 размер подбирается автоматически. Для прикладной политики выбирайте понятные положительные целые размеры; не выдавайте приведение отрицательных или дробных чисел в size_t за полезный способ настройки.

Официальный пример сохраняется целиком: функция читает realpath($imagePath), применяет @ к вызову и отдаёт blob с заголовком image/jpg. В нашем самостоятельном примере @ заменён ограниченным журналом предупреждений, вход объявлен, а PNG явно закодирован. Заголовок HTTP сам по себе не преобразует формат файла; realpath может вернуть false для отсутствующего входа.

Официальная доступность: PECL imagick 2, PECL imagick 3. Все три XML помечены deprecated с PECL Imagick 3.4.4. Однако фактические bindings различаются: medianFilterImage/reduceNoiseImage ограничены IM6 и дали по два E_DEPRECATED в проверенной среде; averageImages имеет современную IM7-ветку в исследованных 3.7/3.8 исходниках и не дал такого предупреждения в IM6. Не переносите один общий статус доступности на всю группу. Для нового явного кода рассмотрены statisticImage и evaluateImages.

Официальный раздел ошибок указывает ImagickException. На пустом объекте каждый из трёх методов действительно дал «Can not process empty Imagick object». Это отличается от успешного вызова без изменения при размере 1 или успешного, но неподходящего по качеству Nonpeak. Предупреждения об устаревании сохраняются отдельно от ошибок; ввод и формат результата проверяются явно.

Полный официальный XML с описанием, параметрами, возвратом и оригинальным примером, если он есть
<?xml version="1.0" encoding="utf-8"?>
<!-- $Revision$ -->
<refentry xmlns="http://docbook.org/ns/docbook" xml:id="imagick.medianfilterimage">
 <refnamediv>
  <refname>Imagick::medianFilterImage</refname>
  <refpurpose>Applies a digital filter</refpurpose>
 </refnamediv>

 <refsynopsisdiv>
   &imagick.deprecated.function-3-4-4;
 </refsynopsisdiv>

 <refsect1 role="description">
  &reftitle.description;
  <methodsynopsis>
   <modifier>public</modifier> <type>bool</type><methodname>Imagick::medianFilterImage</methodname>
   <methodparam><type>float</type><parameter>radius</parameter></methodparam>
  </methodsynopsis>
  <para>
   Applies a digital filter that improves the quality of a
   noisy image.  Each pixel is replaced by the median in a
   set of neighboring pixels as defined by radius.
  </para>
 </refsect1>

 <refsect1 role="parameters">
  &reftitle.parameters;
  <para>
   <variablelist>
    <varlistentry>
     <term><parameter>radius</parameter></term>
     <listitem>
      <para>
      The radius of the pixel neighborhood.
      </para>
     </listitem>
    </varlistentry>
   </variablelist>
  </para>
 </refsect1>

 <refsect1 role="returnvalues">
  &reftitle.returnvalues;
  <para>
   &imagick.return.success;
  </para>
 </refsect1>

 <refsect1 role="errors">
  &reftitle.errors;
  <para>
   &imagick.imagick.throws;
  </para>
 </refsect1>



 <refsect1 role="examples">
  &reftitle.examples;
  <para>
    <example>
      <title> <function>Imagick::medianFilterImage</function></title>
      <programlisting role="php">
      <![CDATA[
<?php
function medianFilterImage($radius, $imagePath) {
    $imagick = new \Imagick(realpath($imagePath));
    @$imagick->medianFilterImage($radius);
    header("Content-Type: image/jpg");
    echo $imagick->getImageBlob();
}

?>
]]>
      </programlisting>
    </example>
  </para>
 </refsect1>

</refentry>

<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:t
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
indent-tabs-mode:nil
sgml-parent-document:nil
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
vim600: syn=xml fen fdm=syntax fdl=2 si
vim: et tw=78 syn=sgml
vi: ts=1 sw=1
-->

Убрать отдельные точки медианой и увидеть цену для тонкой детали

В точке (27,45) чёрный дефект стал белым. MAE к известному учебному оригиналу уменьшилась с 1.9914 до 0.6366, но надпись MUG01 и тонкое подчёркивание повреждены. Очищенный результат не объявляется точным восстановлением.

Убрать отдельные точки медианой и увидеть цену для тонкой деталиПример для указанного окружения
<?php
declare(strict_types=1);
require __DIR__.'/legacy-noise-average-fixture.php';
naRestore();
$clean=naClean();$before=naHash($clean);
$frames=naFrames();$frameHashes=naFrameHashes($frames);
$image=clone $frames[0];
$call=naCall('median3',fn()=>$image->medianFilterImage(3));
$result=naImage($image,$clean,'legacy-noise-average-median.png');
$input=naImage($frames[0],$clean,'median-noisy8.png');naSave($clean,'source-preview8.png');
naDiagnostic('legacy-noise-median-minimal',['executed_api'=>'medianFilterImage','radius'=>3,'call'=>naRecord($call),'images'=>['noisy'=>$input,'median'=>$result],
    'source_unchanged'=>naHash($clean)===$before,'input_frames_unchanged'=>naFrameHashes($frames)===$frameHashes,
    'checks'=>['true_two_warnings'=>$call['value']===true&&$call['deprecations']===2,
        'actual_change'=>naHash($image)!==naHash($frames[0]),'impulse_removed'=>$result['samples']['impulse1']['r']==1.0,
        'fixture_MAE_lower'=>$result['error_to_clean_PIXEl_CHAR_before_PNG8']['MAE']<$input['error_to_clean_PIXEl_CHAR_before_PNG8']['MAE'],
        'source_preserved'=>naHash($clean)===$before&&naFrameHashes($frames)===$frameHashes]]);
echo "legacy-noise-average-median.png\nsource-preview8.png\nmedian-noisy8.png\nmetrics.json\nmedian-radius=3 deprecations=2 impulse-removed=1 input-preserved=1\n";

В точке (27,45) чёрный дефект стал белым. MAE к известному учебному оригиналу уменьшилась с 1.9914 до 0.6366, но надпись MUG01 и тонкое подчёркивание повреждены. Очищенный результат не объявляется точным восстановлением. Каждый ZIP самостоятельный: example.php, пять PNG в base64 и legacy-noise-average-fixture.php. Распакуйте рядом и выполните php example.php. naRestore проверяет SHA и восстанавливает точные входы; шум не генерируется заново. naFrames открывает три кадра, naFreshSequence добавляет их копии в новый Imagick и ставит первый итератор; изучаемый averageImages остаётся виден в основном коде. naCall временно сохраняет только E_DEPRECATED и восстанавливает handler через finally. naImage измеряет объект до отдельной записи PNG8; naCompare составляет нативную полосу без масштабирования. Полный helper открыт в последнем разделе. Проверенная среда: PHP 8.3.6 / Imagick 3.7.0 / IM6.9.12-98 Q16, Ubuntu WSL; исполнение устаревших median/reduce в Windows IM7 не заявлено.

Ожидаемый вывод проверенной программы
legacy-noise-average-median.png
source-preview8.png
median-noisy8.png
metrics.json
median-radius=3 deprecations=2 impulse-removed=1 input-preserved=1

Выбрать обработку товарной схемы по реальным результатам и ограничениям

Сравнены известный чистый рисунок, повреждённый кадр, медиана, Nonpeak и среднее трёх выровненных кадров. Ни один bool не выбирает лучший вариант: учитываем точки, читаемость MUG01, тонкую линию и допустимые изменения.

Выбрать обработку товарной схемы по реальным результатам и ограничениямПример для указанного окружения
<?php
declare(strict_types=1);
require __DIR__.'/legacy-noise-average-fixture.php';
naRestore();
$clean=naClean();$before=naHash($clean);
$frames=naFrames();$frameHashes=naFrameHashes($frames);
$median=clone $frames[0];$reduce=clone $frames[0];
$calls['median']=naCall('median',fn()=>$median->medianFilterImage(3));
$calls['reduce']=naCall('reduce',fn()=>$reduce->reduceNoiseImage(3));
$sequence=naFreshSequence($frames);$sequence->setFirstIterator();
$calls['average']=naCall('average',fn()=>$sequence->averageImages());$mean=$calls['average']['value'];
$images=['clean'=>naImage($clean,$clean,'workflow-clean8.png'),'noisy'=>naImage($frames[0],$clean,'workflow-noisy8.png'),
    'median'=>naImage($median,$clean,'workflow-median8.png'),'reduce'=>naImage($reduce,$clean,'workflow-reduce8.png'),'mean'=>naImage($mean,$clean,'workflow-mean8.png')];
$rects=naCompare([$clean,$frames[0],$median,$reduce,$mean],'legacy-noise-average-workflow.png');
naDiagnostic('legacy-noise-average-workflow',['executed_apis'=>['medianFilterImage','reduceNoiseImage','averageImages'],'radius'=>3,'frame_count'=>3,
    'calls'=>array_map('naRecord',$calls),'images'=>$images,'panel_keys'=>['clean','noisy','median','reduce','mean'],'panel_geometry'=>$rects,
    'source_unchanged'=>naHash($clean)===$before,'input_frames_unchanged'=>naFrameHashes($frames)===$frameHashes,
    'checks'=>['median_success'=>$calls['median']['value']===true&&$calls['median']['deprecations']===2,
        'reduce_success_not_quality'=>$calls['reduce']['value']===true&&$calls['reduce']['deprecations']===2,
        'mean_new_object'=>$mean instanceof Imagick&&$mean!==$sequence&&$calls['average']['deprecations']===0,
        'median_fixture_MAE_lower'=>$images['median']['error_to_clean_PIXEl_CHAR_before_PNG8']['MAE']<$images['noisy']['error_to_clean_PIXEl_CHAR_before_PNG8']['MAE'],
        'reduce_fixture_MAE_higher'=>$images['reduce']['error_to_clean_PIXEl_CHAR_before_PNG8']['MAE']>$images['noisy']['error_to_clean_PIXEl_CHAR_before_PNG8']['MAE'],
        'mean_impulse_attenuated'=>naClose($images['mean']['samples']['impulse1']['r'],2/3),
        'source_preserved'=>naHash($clean)===$before&&naFrameHashes($frames)===$frameHashes]]);
echo "legacy-noise-average-workflow.png\nworkflow-clean8.png\nworkflow-noisy8.png\nworkflow-median8.png\nworkflow-reduce8.png\nworkflow-mean8.png\nmetrics.json\nmedian-MAE-lower=1 reduce-MAE-higher=1 mean-impulse-attenuated=1 input-preserved=1\n";

Сравнены известный чистый рисунок, повреждённый кадр, медиана, Nonpeak и среднее трёх выровненных кадров. Ни один bool не выбирает лучший вариант: учитываем точки, читаемость MUG01, тонкую линию и допустимые изменения. Каждый ZIP самостоятельный: example.php, пять PNG в base64 и legacy-noise-average-fixture.php. Распакуйте рядом и выполните php example.php. naRestore проверяет SHA и восстанавливает точные входы; шум не генерируется заново. naFrames открывает три кадра, naFreshSequence добавляет их копии в новый Imagick и ставит первый итератор; изучаемый averageImages остаётся виден в основном коде. naCall временно сохраняет только E_DEPRECATED и восстанавливает handler через finally. naImage измеряет объект до отдельной записи PNG8; naCompare составляет нативную полосу без масштабирования. Полный helper открыт в последнем разделе. Проверенная среда: PHP 8.3.6 / Imagick 3.7.0 / IM6.9.12-98 Q16, Ubuntu WSL; исполнение устаревших median/reduce в Windows IM7 не заявлено.

Ожидаемый вывод проверенной программы
legacy-noise-average-workflow.png
workflow-clean8.png
workflow-noisy8.png
workflow-median8.png
workflow-reduce8.png
workflow-mean8.png
metrics.json
median-MAE-lower=1 reduce-MAE-higher=1 mean-impulse-attenuated=1 input-preserved=1
Imagick::reduceNoiseImageТочечный шум, сохранение мелких деталей и среднее выровненных кадров

PECL imagick 2, PECL imagick 3 · imagick

Imagick::reduceNoiseImage(float $radius): bool

Назначение, параметры и результат

Imagick::reduceNoiseImage(float $radius): bool

Официальное описание говорит о сглаживании контуров с сохранением информации о границах и замене пикселя близким по значению соседом. Точная исследованная IM6-реализация делегирует StatisticImage с NonpeakStatistic. Это отдельная покомпонентная ранговая операция, а не синоним медианы или обещание выбрать правильный RGB-пиксель. В нашем контролируемом примере она ухудшила результат: успешный true не является оценкой качества.

ПараметрСмысл
$radiusОбязательный float. Согласно полному описанию соседство задаётся radius, а 0 выбирает подходящий размер автоматически. Точный IM6 Core передаёт (size_t)radius как ширину и высоту Nonpeak-окна; здесь 3 = 3 × 3. Автоматический 0 не гарантирует лучший размер: на этом входе в наблюдении результат 0 совпал с 5 и дал ещё большую ошибку. Метод меняет текущее изображение и возвращает bool true при успехе.

Полный официальный пример с функцией reduceNoiseImage($imagePath,$reduceNoise), @, realpath и HTTP-выводом сохранён. Наш код не подавляет все предупреждения и не предполагает, что название метода само подтверждает очистку. Для новых вызовов используйте явно выбранную statisticImage-операцию; её подходящий тип и размер всё равно определяются задачей.

Официальная доступность: PECL imagick 2, PECL imagick 3. Все три XML помечены deprecated с PECL Imagick 3.4.4. Однако фактические bindings различаются: medianFilterImage/reduceNoiseImage ограничены IM6 и дали по два E_DEPRECATED в проверенной среде; averageImages имеет современную IM7-ветку в исследованных 3.7/3.8 исходниках и не дал такого предупреждения в IM6. Не переносите один общий статус доступности на всю группу. Для нового явного кода рассмотрены statisticImage и evaluateImages.

Официальный раздел ошибок указывает ImagickException. На пустом объекте каждый из трёх методов действительно дал «Can not process empty Imagick object». Это отличается от успешного вызова без изменения при размере 1 или успешного, но неподходящего по качеству Nonpeak. Предупреждения об устаревании сохраняются отдельно от ошибок; ввод и формат результата проверяются явно.

Полный официальный XML с описанием, параметрами, возвратом и оригинальным примером, если он есть
<?xml version="1.0" encoding="utf-8"?>
<!-- $Revision$ -->
<refentry xmlns="http://docbook.org/ns/docbook" xml:id="imagick.reducenoiseimage">
 <refnamediv>
  <refname>Imagick::reduceNoiseImage</refname>
  <refpurpose>Smooths the contours of an image</refpurpose>
 </refnamediv>

 <refsynopsisdiv>
   &imagick.deprecated.function-3-4-4;
 </refsynopsisdiv>

 <refsect1 role="description">
  &reftitle.description;
  <methodsynopsis>
   <modifier>public</modifier> <type>bool</type><methodname>Imagick::reduceNoiseImage</methodname>
   <methodparam><type>float</type><parameter>radius</parameter></methodparam>
  </methodsynopsis>
  <para>
   Smooths the contours of an image while still preserving edge
   information. The algorithm works by replacing each pixel with
   its neighbor closest in value. A neighbor is defined by radius.
   Use a radius of 0 and Imagick::reduceNoiseImage() selects a
   suitable radius for you.
  </para>
 </refsect1>

 <refsect1 role="parameters">
  &reftitle.parameters;
  <para>
   <variablelist>
    <varlistentry>
     <term><parameter>radius</parameter></term>
     <listitem>
      <para>
      </para>
     </listitem>
    </varlistentry>
   </variablelist>
  </para>
 </refsect1>

 <refsect1 role="returnvalues">
  &reftitle.returnvalues;
  <para>
   &imagick.return.success;
  </para>
 </refsect1>

 <refsect1 role="errors">
  &reftitle.errors;
  <para>
   &imagick.imagick.throws;
  </para>
 </refsect1>



 <refsect1 role="examples">
  &reftitle.examples;
  <para>
    <example>
      <title> <function>Imagick::reduceNoiseImage</function></title>
      <programlisting role="php">
      <![CDATA[
<?php
function reduceNoiseImage($imagePath, $reduceNoise) {
    $imagick = new \Imagick(realpath($imagePath));
    @$imagick->reduceNoiseImage($reduceNoise);
    header("Content-Type: image/jpg");
    echo $imagick->getImageBlob();
}

?>
]]>
      </programlisting>
    </example>
  </para>
 </refsect1>

</refentry>

<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:t
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
indent-tabs-mode:nil
sgml-parent-document:nil
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
vim600: syn=xml fen fdm=syntax fdl=2 si
vim: et tw=78 syn=sgml
vi: ts=1 sw=1
-->

Увидеть реальный результат Nonpeak, который не подошёл этому рисунку

Вызов вернул true и изменил картинку, однако точка (27,45) осталась чёрной, а MAE выросла примерно до 15.9989. Здесь reduceNoiseImage не улучшил исходник. Это полезный отрицательный результат, а не успешная очистка по одному имени метода.

Увидеть реальный результат Nonpeak, который не подошёл этому рисункуПример для указанного окружения
<?php
declare(strict_types=1);
require __DIR__.'/legacy-noise-average-fixture.php';
naRestore();
$clean=naClean();$before=naHash($clean);
$frames=naFrames();$frameHashes=naFrameHashes($frames);
$image=clone $frames[0];
$call=naCall('reduce3',fn()=>$image->reduceNoiseImage(3));
$result=naImage($image,$clean,'legacy-noise-average-reduce.png');
$input=naImage($frames[0],$clean,'reduce-noisy8.png');
naDiagnostic('legacy-noise-reduce-minimal',['executed_api'=>'reduceNoiseImage','radius'=>3,'call'=>naRecord($call),'images'=>['noisy'=>$input,'reduce'=>$result],
    'source_unchanged'=>naHash($clean)===$before,'input_frames_unchanged'=>naFrameHashes($frames)===$frameHashes,
    'checks'=>['true_two_warnings'=>$call['value']===true&&$call['deprecations']===2,
        'actual_change'=>naHash($image)!==naHash($frames[0]),'not_claimed_improvement'=>$result['error_to_clean_PIXEl_CHAR_before_PNG8']['MAE']>$input['error_to_clean_PIXEl_CHAR_before_PNG8']['MAE'],
        'impulse_can_remain'=>$result['samples']['impulse1']['r']==0.0,
        'source_preserved'=>naHash($clean)===$before&&naFrameHashes($frames)===$frameHashes]]);
echo "legacy-noise-average-reduce.png\nreduce-noisy8.png\nmetrics.json\nreduce-radius=3 returned=1 deprecations=2 fixture-error-increased=1 input-preserved=1\n";

Вызов вернул true и изменил картинку, однако точка (27,45) осталась чёрной, а MAE выросла примерно до 15.9989. Здесь reduceNoiseImage не улучшил исходник. Это полезный отрицательный результат, а не успешная очистка по одному имени метода. Каждый ZIP самостоятельный: example.php, пять PNG в base64 и legacy-noise-average-fixture.php. Распакуйте рядом и выполните php example.php. naRestore проверяет SHA и восстанавливает точные входы; шум не генерируется заново. naFrames открывает три кадра, naFreshSequence добавляет их копии в новый Imagick и ставит первый итератор; изучаемый averageImages остаётся виден в основном коде. naCall временно сохраняет только E_DEPRECATED и восстанавливает handler через finally. naImage измеряет объект до отдельной записи PNG8; naCompare составляет нативную полосу без масштабирования. Полный helper открыт в последнем разделе. Проверенная среда: PHP 8.3.6 / Imagick 3.7.0 / IM6.9.12-98 Q16, Ubuntu WSL; исполнение устаревших median/reduce в Windows IM7 не заявлено.

Ожидаемый вывод проверенной программы
legacy-noise-average-reduce.png
reduce-noisy8.png
metrics.json
reduce-radius=3 returned=1 deprecations=2 fixture-error-increased=1 input-preserved=1

Выбрать обработку товарной схемы по реальным результатам и ограничениям

Сравнены известный чистый рисунок, повреждённый кадр, медиана, Nonpeak и среднее трёх выровненных кадров. Ни один bool не выбирает лучший вариант: учитываем точки, читаемость MUG01, тонкую линию и допустимые изменения.

Выбрать обработку товарной схемы по реальным результатам и ограничениямПример для указанного окружения
<?php
declare(strict_types=1);
require __DIR__.'/legacy-noise-average-fixture.php';
naRestore();
$clean=naClean();$before=naHash($clean);
$frames=naFrames();$frameHashes=naFrameHashes($frames);
$median=clone $frames[0];$reduce=clone $frames[0];
$calls['median']=naCall('median',fn()=>$median->medianFilterImage(3));
$calls['reduce']=naCall('reduce',fn()=>$reduce->reduceNoiseImage(3));
$sequence=naFreshSequence($frames);$sequence->setFirstIterator();
$calls['average']=naCall('average',fn()=>$sequence->averageImages());$mean=$calls['average']['value'];
$images=['clean'=>naImage($clean,$clean,'workflow-clean8.png'),'noisy'=>naImage($frames[0],$clean,'workflow-noisy8.png'),
    'median'=>naImage($median,$clean,'workflow-median8.png'),'reduce'=>naImage($reduce,$clean,'workflow-reduce8.png'),'mean'=>naImage($mean,$clean,'workflow-mean8.png')];
$rects=naCompare([$clean,$frames[0],$median,$reduce,$mean],'legacy-noise-average-workflow.png');
naDiagnostic('legacy-noise-average-workflow',['executed_apis'=>['medianFilterImage','reduceNoiseImage','averageImages'],'radius'=>3,'frame_count'=>3,
    'calls'=>array_map('naRecord',$calls),'images'=>$images,'panel_keys'=>['clean','noisy','median','reduce','mean'],'panel_geometry'=>$rects,
    'source_unchanged'=>naHash($clean)===$before,'input_frames_unchanged'=>naFrameHashes($frames)===$frameHashes,
    'checks'=>['median_success'=>$calls['median']['value']===true&&$calls['median']['deprecations']===2,
        'reduce_success_not_quality'=>$calls['reduce']['value']===true&&$calls['reduce']['deprecations']===2,
        'mean_new_object'=>$mean instanceof Imagick&&$mean!==$sequence&&$calls['average']['deprecations']===0,
        'median_fixture_MAE_lower'=>$images['median']['error_to_clean_PIXEl_CHAR_before_PNG8']['MAE']<$images['noisy']['error_to_clean_PIXEl_CHAR_before_PNG8']['MAE'],
        'reduce_fixture_MAE_higher'=>$images['reduce']['error_to_clean_PIXEl_CHAR_before_PNG8']['MAE']>$images['noisy']['error_to_clean_PIXEl_CHAR_before_PNG8']['MAE'],
        'mean_impulse_attenuated'=>naClose($images['mean']['samples']['impulse1']['r'],2/3),
        'source_preserved'=>naHash($clean)===$before&&naFrameHashes($frames)===$frameHashes]]);
echo "legacy-noise-average-workflow.png\nworkflow-clean8.png\nworkflow-noisy8.png\nworkflow-median8.png\nworkflow-reduce8.png\nworkflow-mean8.png\nmetrics.json\nmedian-MAE-lower=1 reduce-MAE-higher=1 mean-impulse-attenuated=1 input-preserved=1\n";

Сравнены известный чистый рисунок, повреждённый кадр, медиана, Nonpeak и среднее трёх выровненных кадров. Ни один bool не выбирает лучший вариант: учитываем точки, читаемость MUG01, тонкую линию и допустимые изменения. Каждый ZIP самостоятельный: example.php, пять PNG в base64 и legacy-noise-average-fixture.php. Распакуйте рядом и выполните php example.php. naRestore проверяет SHA и восстанавливает точные входы; шум не генерируется заново. naFrames открывает три кадра, naFreshSequence добавляет их копии в новый Imagick и ставит первый итератор; изучаемый averageImages остаётся виден в основном коде. naCall временно сохраняет только E_DEPRECATED и восстанавливает handler через finally. naImage измеряет объект до отдельной записи PNG8; naCompare составляет нативную полосу без масштабирования. Полный helper открыт в последнем разделе. Проверенная среда: PHP 8.3.6 / Imagick 3.7.0 / IM6.9.12-98 Q16, Ubuntu WSL; исполнение устаревших median/reduce в Windows IM7 не заявлено.

Ожидаемый вывод проверенной программы
legacy-noise-average-workflow.png
workflow-clean8.png
workflow-noisy8.png
workflow-median8.png
workflow-reduce8.png
workflow-mean8.png
metrics.json
median-MAE-lower=1 reduce-MAE-higher=1 mean-impulse-attenuated=1 input-preserved=1
Imagick::averageImagesТочечный шум, сохранение мелких деталей и среднее выровненных кадров

PECL imagick 2, PECL imagick 3 · imagick

Imagick::averageImages(): Imagick

Назначение, параметры и результат

Imagick::averageImages(): Imagick

Аргументов нет. AverageImages читает последовательность кадров из самого объекта Imagick и возвращает новый Imagick с усреднённым изображением. Массив объектов не передаётся в скобки: кадры предварительно добавляют через addImage. В показанном сценарии один контейнер содержит три одинаково выровненных кадра; результат — другой контейнер с одним кадром. Исходные изображения не заменяются результатом автоматически.

Среднее считается по соответствующим координатам и компонентам кадров, а не по соседству одного кадра. Проверяйте одинаковую геометрию, смысловое выравнивание и согласованное цветовое представление заранее. Метод не совмещает объекты, не распознаёт движение и не исправляет разные экспозиции/профили. Смещённый третий кадр создаёт полупрозрачный призрак. Наша проверка 400 × 320 — политика примера, а не утверждение, что native API обязательно отвергнет любой другой размер.

Перед усреднением используем свежую последовательность и явный setFirstIterator. При первичном исследовании native-библиотека аварийно остановилась с C assertion после сохранения первого результата, до второго/nonzero-index результата и JSON. Точная подстадия state/call/output не установлена; мы не утверждаем, что index 2 всегда падает. Опасный путь не повторяется и не включён в архивы. Такая авария не является обычным PHP-исключением, которое обещано поймать через catch. Исправленное наблюдение и все учебные вызовы используют свежий контейнер с первым итератором.

Официальная доступность: PECL imagick 2, PECL imagick 3. Все три XML помечены deprecated с PECL Imagick 3.4.4. Однако фактические bindings различаются: medianFilterImage/reduceNoiseImage ограничены IM6 и дали по два E_DEPRECATED в проверенной среде; averageImages имеет современную IM7-ветку в исследованных 3.7/3.8 исходниках и не дал такого предупреждения в IM6. Не переносите один общий статус доступности на всю группу. Для нового явного кода рассмотрены statisticImage и evaluateImages.

Официальный раздел ошибок указывает ImagickException. На пустом объекте каждый из трёх методов действительно дал «Can not process empty Imagick object». Это отличается от успешного вызова без изменения при размере 1 или успешного, но неподходящего по качеству Nonpeak. Предупреждения об устаревании сохраняются отдельно от ошибок; ввод и формат результата проверяются явно.

Полный официальный XML с описанием, параметрами, возвратом и оригинальным примером, если он есть
<?xml version="1.0" encoding="utf-8"?>
<!-- $Revision$ -->
<refentry xmlns="http://docbook.org/ns/docbook" xml:id="imagick.averageimages">
 <refnamediv>
  <refname>Imagick::averageImages</refname>
  <refpurpose>Average a set of images</refpurpose>
 </refnamediv>

 <refsynopsisdiv>
   &imagick.deprecated.function-3-4-4;
 </refsynopsisdiv>

 <refsect1 role="description">
  &reftitle.description;
  <methodsynopsis>
   <modifier>public</modifier> <type>Imagick</type><methodname>Imagick::averageImages</methodname>
   <void/>
  </methodsynopsis>
  <para>
   Average a set of images.
  </para>
 </refsect1>

 <refsect1 role="parameters">
  &reftitle.parameters;
  &no.function.parameters;
 </refsect1>

 <refsect1 role="returnvalues">
  &reftitle.returnvalues;
  <para>
   Returns a new Imagick object on success.
  </para>
 </refsect1>

 <refsect1 role="errors">
  &reftitle.errors;
  <para>
   &imagick.imagick.throws;
  </para>
 </refsect1>

</refentry>

<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:t
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
indent-tabs-mode:nil
sgml-parent-document:nil
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
vim600: syn=xml fen fdm=syntax fdl=2 si
vim: et tw=78 syn=sgml
vi: ts=1 sw=1
-->

Усреднить три выровненных кадра и сохранить новый результат

Один Imagick содержит три кадра; averageImages без параметров вернул отдельный объект с одним кадром 400 × 320. В точке (27,45) среднее black/white/white равно 2/3. Точки стали менее контрастными, но не исчезли; подпись и подчёркивание сохраняются лучше, чем после медианы.

Усреднить три выровненных кадра и сохранить новый результатПример для указанного окружения
<?php
declare(strict_types=1);
require __DIR__.'/legacy-noise-average-fixture.php';
naRestore();
$clean=naClean();$before=naHash($clean);
$frames=naFrames();$frameHashes=naFrameHashes($frames);
$sequence=new Imagick();
$sequence->addImage(clone $frames[0]);$sequence->addImage(clone $frames[1]);$sequence->addImage(clone $frames[2]);
$sequence->setFirstIterator();$iteratorBefore=$sequence->getIteratorIndex();
$call=naCall('average',fn()=>$sequence->averageImages());
$mean=$call['value'];
$result=naImage($mean,$clean,'legacy-noise-average-average.png');
foreach($frames as $index=>$frame){naSave($frame,'average-frame'.($index+1).'-8.png');}
naDiagnostic('legacy-noise-average-minimal',['executed_api'=>'averageImages','call'=>naRecord($call),'images'=>['mean'=>$result],
    'sequence'=>['count'=>$sequence->getNumberImages(),'iterator_before'=>$iteratorBefore,'iterator_after'=>$sequence->getIteratorIndex()],
    'returned_new_object'=>$mean!==$sequence,'input_frames_unchanged'=>naFrameHashes($frames)===$frameHashes,'source_unchanged'=>naHash($clean)===$before,
    'checks'=>['new_single_image'=>$mean instanceof Imagick&&$mean!==$sequence&&$mean->getNumberImages()===1,
        'three_frames_first_iterator'=>$sequence->getNumberImages()===3&&$iteratorBefore===0&&$sequence->getIteratorIndex()===0,
        'no_runtime_deprecation'=>$call['deprecations']===0,'same_coordinate_mean'=>naClose($result['samples']['impulse1']['r'],2/3),
        'fixture_max_error_85'=>$result['error_to_clean_PIXEl_CHAR_before_PNG8']['max']===85,
        'source_preserved'=>naHash($clean)===$before&&naFrameHashes($frames)===$frameHashes]]);
echo "legacy-noise-average-average.png\naverage-frame1-8.png\naverage-frame2-8.png\naverage-frame3-8.png\nmetrics.json\nframes=3 result-images=1 returned-new=1 iterator=0 input-preserved=1\n";

Один Imagick содержит три кадра; averageImages без параметров вернул отдельный объект с одним кадром 400 × 320. В точке (27,45) среднее black/white/white равно 2/3. Точки стали менее контрастными, но не исчезли; подпись и подчёркивание сохраняются лучше, чем после медианы. Каждый ZIP самостоятельный: example.php, пять PNG в base64 и legacy-noise-average-fixture.php. Распакуйте рядом и выполните php example.php. naRestore проверяет SHA и восстанавливает точные входы; шум не генерируется заново. naFrames открывает три кадра, naFreshSequence добавляет их копии в новый Imagick и ставит первый итератор; изучаемый averageImages остаётся виден в основном коде. naCall временно сохраняет только E_DEPRECATED и восстанавливает handler через finally. naImage измеряет объект до отдельной записи PNG8; naCompare составляет нативную полосу без масштабирования. Полный helper открыт в последнем разделе. Проверенная среда: PHP 8.3.6 / Imagick 3.7.0 / IM6.9.12-98 Q16, Ubuntu WSL; исполнение устаревших median/reduce в Windows IM7 не заявлено.

Ожидаемый вывод проверенной программы
legacy-noise-average-average.png
average-frame1-8.png
average-frame2-8.png
average-frame3-8.png
metrics.json
frames=3 result-images=1 returned-new=1 iterator=0 input-preserved=1

Выбрать обработку товарной схемы по реальным результатам и ограничениям

Сравнены известный чистый рисунок, повреждённый кадр, медиана, Nonpeak и среднее трёх выровненных кадров. Ни один bool не выбирает лучший вариант: учитываем точки, читаемость MUG01, тонкую линию и допустимые изменения.

Выбрать обработку товарной схемы по реальным результатам и ограничениямПример для указанного окружения
<?php
declare(strict_types=1);
require __DIR__.'/legacy-noise-average-fixture.php';
naRestore();
$clean=naClean();$before=naHash($clean);
$frames=naFrames();$frameHashes=naFrameHashes($frames);
$median=clone $frames[0];$reduce=clone $frames[0];
$calls['median']=naCall('median',fn()=>$median->medianFilterImage(3));
$calls['reduce']=naCall('reduce',fn()=>$reduce->reduceNoiseImage(3));
$sequence=naFreshSequence($frames);$sequence->setFirstIterator();
$calls['average']=naCall('average',fn()=>$sequence->averageImages());$mean=$calls['average']['value'];
$images=['clean'=>naImage($clean,$clean,'workflow-clean8.png'),'noisy'=>naImage($frames[0],$clean,'workflow-noisy8.png'),
    'median'=>naImage($median,$clean,'workflow-median8.png'),'reduce'=>naImage($reduce,$clean,'workflow-reduce8.png'),'mean'=>naImage($mean,$clean,'workflow-mean8.png')];
$rects=naCompare([$clean,$frames[0],$median,$reduce,$mean],'legacy-noise-average-workflow.png');
naDiagnostic('legacy-noise-average-workflow',['executed_apis'=>['medianFilterImage','reduceNoiseImage','averageImages'],'radius'=>3,'frame_count'=>3,
    'calls'=>array_map('naRecord',$calls),'images'=>$images,'panel_keys'=>['clean','noisy','median','reduce','mean'],'panel_geometry'=>$rects,
    'source_unchanged'=>naHash($clean)===$before,'input_frames_unchanged'=>naFrameHashes($frames)===$frameHashes,
    'checks'=>['median_success'=>$calls['median']['value']===true&&$calls['median']['deprecations']===2,
        'reduce_success_not_quality'=>$calls['reduce']['value']===true&&$calls['reduce']['deprecations']===2,
        'mean_new_object'=>$mean instanceof Imagick&&$mean!==$sequence&&$calls['average']['deprecations']===0,
        'median_fixture_MAE_lower'=>$images['median']['error_to_clean_PIXEl_CHAR_before_PNG8']['MAE']<$images['noisy']['error_to_clean_PIXEl_CHAR_before_PNG8']['MAE'],
        'reduce_fixture_MAE_higher'=>$images['reduce']['error_to_clean_PIXEl_CHAR_before_PNG8']['MAE']>$images['noisy']['error_to_clean_PIXEl_CHAR_before_PNG8']['MAE'],
        'mean_impulse_attenuated'=>naClose($images['mean']['samples']['impulse1']['r'],2/3),
        'source_preserved'=>naHash($clean)===$before&&naFrameHashes($frames)===$frameHashes]]);
echo "legacy-noise-average-workflow.png\nworkflow-clean8.png\nworkflow-noisy8.png\nworkflow-median8.png\nworkflow-reduce8.png\nworkflow-mean8.png\nmetrics.json\nmedian-MAE-lower=1 reduce-MAE-higher=1 mean-impulse-attenuated=1 input-preserved=1\n";

Сравнены известный чистый рисунок, повреждённый кадр, медиана, Nonpeak и среднее трёх выровненных кадров. Ни один bool не выбирает лучший вариант: учитываем точки, читаемость MUG01, тонкую линию и допустимые изменения. Каждый ZIP самостоятельный: example.php, пять PNG в base64 и legacy-noise-average-fixture.php. Распакуйте рядом и выполните php example.php. naRestore проверяет SHA и восстанавливает точные входы; шум не генерируется заново. naFrames открывает три кадра, naFreshSequence добавляет их копии в новый Imagick и ставит первый итератор; изучаемый averageImages остаётся виден в основном коде. naCall временно сохраняет только E_DEPRECATED и восстанавливает handler через finally. naImage измеряет объект до отдельной записи PNG8; naCompare составляет нативную полосу без масштабирования. Полный helper открыт в последнем разделе. Проверенная среда: PHP 8.3.6 / Imagick 3.7.0 / IM6.9.12-98 Q16, Ubuntu WSL; исполнение устаревших median/reduce в Windows IM7 не заявлено.

Ожидаемый вывод проверенной программы
legacy-noise-average-workflow.png
workflow-clean8.png
workflow-noisy8.png
workflow-median8.png
workflow-reduce8.png
workflow-mean8.png
metrics.json
median-MAE-lower=1 reduce-MAE-higher=1 mean-impulse-attenuated=1 input-preserved=1
Источники и обсуждения

Код и руководство с собой

Скачайте самостоятельные примеры с исходными данными, инструкциями и ожидаемыми результатами. Примеры HTTP и фрагменты для проекта помечены отдельно: им нужно указанное окружение.

Код не исполняется на сайте. Скачайте нужный пример и запускайте его в своём локальном окружении.

Материалы сверены 2026-10-12. Примеры и объяснения написаны для этого руководства; источники и обсуждения доступны в каждой главе.