Pull to refresh
131
0
Александр Карпинский @homm

Например: Программист

Send message

Наша математическая Вселенная

Reading time9 min
Views3.7K

Я решил назвать эту статью так же как называется книга Макса Тегмарка, потому что речь в статье пойдёт о том же, о чем и в книге. Но дело в том, что я не читал эту книгу. Я, думаю, как и многие тут, смотрел научно-популярные видео, интересовался устройством вселенной, копил знания, замечал закономерности и в какой-то момент у меня сложилась картина. Я держал эту картину при себе т.к. уж очень простой и понятной она была, я был уверен, что я не первый и не десятый человек, увидевший эту картину.

Читать далее
Total votes 15: ↑15 and ↓0+15
Comments5

Борьба с цветными полосами в JPEG

Reading time7 min
Views9.1K

Если вы хоть раз сохраняли фото в формате JPEG, вы возможно знаете, насколько ужасно могут выглядеть джипеги. Десятилетия доминирования этого формата привели к тому, что у многих интернет-пользователей сформировалась стойкая аллергия к тому, что называется «артефакты JPEG».



Лувр. 480×245 пикселей, сильно сжатый JPEG


Без сомнения, никто бы не хотел делиться таким месивом пикселей с кем-то. Если бы вы спросили меня, что конкретно не так с этим изображением, я бы сказал, что в целом оно выглядит довольно близко к оригиналу: нет существенных искажений цветов, объекты узнаваемы. Однако я бы сказал, что тут есть две огромные проблемы:

Читать дальше →
Total votes 26: ↑24 and ↓2+35
Comments15

Главный секрет операторов match/case в пайтоне

Reading time2 min
Views14K

Не так давно увидела свет версия языка пайтон 3.10. В ней был добавлен pattern matching statement (оператор сопоставления с шаблонами). Как гласит официальное описание этого оператора в PEP622, разработчики в большей мере вдохновлялись наработками таких языков как: Scala, Erlang, Rust.

Многие, в том числе и я, встретили оператор с критикой. Можно для примера почитать комментарии к недавнему посту. В основном люди жалуются на синтаксис, который похож на синтаксис питона, однако означает совершенно другое. Вот несколько примеров:

Читать далее
Total votes 27: ↑23 and ↓4+26
Comments24

Перегон картинок из Pillow в NumPy/OpenCV всего за два копирования памяти

Reading time7 min
Views11K

Стоп, что? В смысле «всего»? Разве преобразование из одного формата в другой нельзя сделать за одно копирование, а лучше вообще без копирования?

Да, это кажется безумием, но более привычные методы преобразования картинок работают в 1,5-2,5 раза медленнее (если нужен не read-only объект). Сегодня я покопаюсь в кишках обеих библиотек, расскажу почему так получилось и кто виноват. А также покажу финальный результат, который работает так же, только быстрее. Никаких репозиториев или пакетов не будет, только рассказ и рабочий код в конце. Но давайте обо всём по порядку.

Читать далее
Total votes 39: ↑39 and ↓0+39
Comments13

Эпл испортила мне ноутбук почти сразу после покупки и до сих пор не собирается чинить

Reading time4 min
Views76K

Как вы понимаете, это крик души. Уже больше года я «счастливый» обладатель 13-дюймового Macbook Pro 2019 года за 170 тысяч рублей.


Когда я его покупал, я естественно знал, что у этих ноутбуков было полно проблем с клавиатурой и обрывами шлейфа экрана, но это была уже третья реинкарнация и все обзоры говорили в пользу того, что большинство проблем уже решено. В принципе так и есть: за вычетом пару раз западавшего пробела, клавиатура не сильно парит. Беда пришла с другой стороны.

Читать дальше →
Total votes 98: ↑54 and ↓44+34
Comments566

Главный секрет блока else в циклах пайтона

Reading time1 min
Views49K

Это короткая статья для новичков. Наверняка вы знаете, что в пайтоне для циклов for и while предусмотрен блок else. И с этим блоком возникает много путаницы, потому что его действие на первый взгляд неинтуитивно. Приходится тратить немного времени или заглядывать в документацию каждый раз, когда он встречается:


for f in files:
    if f.uuid == match_uuid:
        break
else:
    raise FileNotFound()

Когда будет исключение: когда файл не найден? Когда найден? Когда список пуст? На этот вопрос сложно ответить, потому что блок else находится на одном уровне с блоком for и кажется, что это какое-то условие, относящиеся к самому списку; например, когда for не нашел ни одной записи. Но достаточно знать главный секрет блока else для циклов, чтобы больше никогда не терять на это время:

Читать дальше →
Total votes 66: ↑59 and ↓7+76
Comments161

Трансформация цвета: поиски в прореженном столе

Reading time9 min
Views8.8K

Это обзор функциональности, появившейся в Pillow 5.2: применение трехмерных таблиц поиска (3D lookup tables, 3D LUT) для трансформации цвета. Эта техника широко распространена в обработке видео и 3D-играх, однако мало графических библиотек могли похвастаться 3D LUT трансформациями до этого.


Трехмерные таблицы поиска дают большую гибкость в описании цветовых трансформаций, но самое главное трансформации выполняются за одинаковое время, какими бы сложными они не были.


from PIL import Image, ImageFilter

def washout(r, g, b):
    h, s, v = _rgb_to_hsv(r, g, b)
    if 0.3 < h < 0.7:
        s = 0
    return _hsv_to_rgb(h, s, v)

im = Image.open('./Puffins.jpg')
im = im.filter(ImageFilter.Color3DLUT.generate(17, washout))

Функция, полностью написанная на Пайтоне, применяется к 16,6-мегапиксельной картинке за 75ms.



Работа с изображениями и так ресурсоемка, поэтому я обожаю алгоритмы, которые позволяют убрать сложность от входных параметров. Пять лет назад я реализовал в Pillow гауссово размытие, работающее за одинаковое время для любого радиуса. Не так давно я рассказал как можно уменьшить изображение за константное время с минимальной потерей качества. Сегодня я покажу для каких задач можно применять 3D LUT, какие у нее ограничения и похвастаюсь достигнутой производительностью в Pillow-SIMD.

Читать дальше →
Total votes 23: ↑23 and ↓0+23
Comments6

Правдоподобная реконструкция Инстаграм-подобных фильтров

Reading time4 min
Views11K

Существует куча софта, который позволяет пользователям применять различные цветовые фильтры к своим фотография. Пионером в этом деле был Инстаграм и иногда хочется сделать в своем приложении уже знакомые пользователям фильтры. И я хочу представить набор утилит, который позволит в полу-автоматическом режиме очень точно воспроизводить цветовые фильтры из других приложений в своём приложении.


https://github.com/homm/color-filters-reconstruction


Людям нравятся фильтры из Инстаграма. Они пытаются воспроизвести их снова и снова. И снова и снова. И снова и снова. Проблема с этими попытками в том, что люди пытаются вручную подобрать цветовую коррекцию, которая будет хоть как-то похожа на то, что делают оригинальные фильтры. Для меня же было намного более интересно попробовать воспроизвести фильтры основываясь на более надежных методах и математике. И похоже, что это единственная попытка действительно точного воссоздания цветовых фильтров.


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



Для сравнения, это результат применения того же фильтра из коммерческого набора «Инстаграм-подобных фильтров», который вы без труда сможете нагуглить:


Читать дальше →
Total votes 23: ↑23 and ↓0+23
Comments32

Фундаментальная уязвимость HTML при встраивании скриптов

Reading time9 min
Views51K

Чтобы описать суть проблемы, мне нужно рассказать, как вообще устроен HTML. Вы наверняка в общих чертах представляли себе, но я все равно коротко пробегусь по основным моментам, которые понадобятся для понимания. Если кому-то не терпится, сразу переходите к сути.


HTML — это язык гипертекстовой разметки. Чтобы говорить на этом языке, нужно соблюдать его формат, иначе тот, кто читает написанное, не сможет вас понять. Например, в HTML у тегов есть атрибуты:


<p name="value">

Тут [name] — это имя атрибута, а [value] — это его значение. В статье я буду использовать квадратные скобки вокруг кода, чтобы было понятно, где он начинается и заканчивается. После имени стои́т знак равенства, а после него — значение, заключенное в кавычки. Значение атрибута начинается сразу после первого символа кавычки и заканчивается сразу перед следующим символом кавычки, где бы он не находился. Это значит, что если вместо [value] вы запишете [OOO "Рога и копыта".], то значение атрибута name будет [OOO ], а еще у вашего элемента будет три других атрибута с именами: [рога], [и] и [копыта"."], но без значений.


<p name="OOO "Рога и копыта"."></p>

Если это не то, чего вы ожидали, вам нужно как-то изменить значение атрибута, чтобы в нем не встречалась кавычка. Самое простое, что можно придумать — просто вырезать кавычки.


<p name="OOO Рога и копыта."></p>
Читать дальше →
Total votes 98: ↑65 and ↓33+32
Comments67

Качественное уменьшение изображений за константное время

Reading time8 min
Views28K

Хочу поделиться очень простым и эффективным методом ресайза изображении, который работает за константное время относительно размера исходного изображения и дает неожиданно качественный результат. Метод применим для любых языков и приложений.


Для начала давайте порассуждаем логически. Если вы делаете ресайз изображения, наверное вы хотите чтобы результат хотя бы отдаленно напоминал оригинал. Для этого нужно учесть как можно больше информации из исходного изображения. Вы слышали о методе «ближайшего соседа»? В этом методе для каждой точки конечного изображения просто берется какая-то одна точка из исходного изображения в неизменном виде.



Уменьшение изображения 4928×3280 до 256×170 ближайшим соседом.


Рекомендую смотреть примеры из статьи в браузере в масштабе 100% и без ретины. То есть по максимуму исключить ресайз при просмотре.

Результат не представляет ничего хорошего. Изображение дерганое, зернистое, даже трудно понять что на нем изображено. Особенно если на исходном изображении было много мелких деталей или оно само было зернистым. Почему так получается? Потому что в конечном изображении было учтено очень мало информации из исходного. Если условно отметить на исходном изображении те точки, которые попадают в конечное, получится вот такая сеточка:



Точки, которые попадут в конечное изображение размером 20×13.
Читать дальше →
Total votes 80: ↑78 and ↓2+76
Comments46

Root хуже Михалкова

Reading time2 min
Views42K

Рут – это мифическое существо в экосистеме Linux. Он может всё: зайти в любой каталог, удалить любой файл, завершить любой процесс, открыть любой порт. В общем это суперчеловек, чрезвычайно могущественный и очень полезный. Но задумывались ли вы когда-нибудь, какую цену мы платим руту? Не думали же вы, что он работает за просто так.


Вы знаете команду df? Она показывает все подключенные сейчас диски и статистику по ним: сколько место занято, сколько свободно. Например:


$ df -m
Filesystem     1M-blocks   Used Available Use% Mounted on
udev                 224      1       224   1% /dev
tmpfs                 48      1        47   2% /run
/dev/dm-0           9204   7421      1294  86% /

Вы когда-нибудь замечали, что для локальных дисков сумма Used и Available чаще всего меньше общего размера диска? Ненамного, но меньше.

Читать дальше →
Total votes 103: ↑80 and ↓23+57
Comments140

Как я сделал самый быстрый ресайз изображений. Часть 3, числа с фиксированной точкой

Reading time14 min
Views10K

Я продолжаю подробно рассказывать о приемах оптимизации, позволивших мне написать самый быстрый ресайз изображений на современных x86 процессорах. На этот раз речь пойдет о преобразовании вычислений с плавающей точкой в вычисления с целыми числами. Сперва я расскажу немного теории, как это работает. Затем вернусь к реальному коду, в том числе SIMD-версии.


В предыдущих частях:


Часть 0
Часть 1, общие оптимизации
Часть 2, SIMD

Читать дальше →
Total votes 37: ↑37 and ↓0+37
Comments15

Как я сделал самый быстрый ресайз изображений. Часть 2, SIMD

Reading time15 min
Views27K

Это продолжение цикла статей о том, как я занимался оптимизацией и получил самый быстрый ресайз на современных x86 процессорах. В каждой статье я рассказываю часть истории, и надеюсь подтолкнуть еще кого-то заняться оптимизацией своего или чужого кода. В предыдущих сериях:


Часть 0
Часть 1, общие оптимизации


В прошлый раз мы получили ускорение в среднем в 2,5 раза без изменения подхода. В этот раз я покажу, как применять SIMD-подход и получить ускорение еще в 3,5 раза. Конечно, применение SIMD для обработки графики не является ноу-хау, можно даже сказать, что SIMD был придуман для этого. Но на практике очень мало разработчиков используют его даже в задачах обработки изображений. Например, довольно известные и распространенные библиотеки ImageMagick и LibGD написаны без использования SIMD. Отчасти так происходит потому, что SIMD-подход объективно сложнее и не кроссплатформенный, а отчасти потому, что по нему мало информации. Довольно просто найти азы, но мало детальных материалов и разбора реальных задач. От этого на Stack Overflow очень много вопросов буквально о каждой мелочи: как загрузить данные, как распаковать, запаковать. Видно, что всем приходится набивать шишки самостоятельно.

Читать дальше →
Total votes 70: ↑67 and ↓3+64
Comments26

Как я сделал самый быстрый ресайз изображений. Часть 1, общие оптимизации

Reading time15 min
Views20K

В пилотной части я рассказал о задаче как можно подробнее. Рассказ получился долгим и беспредметным — в нем не было ни одной строчки кода. Но без понимания задачи очень сложно заниматься оптимизацией. Конечно, некоторые техники можно применять, имея на руках только код. Например, кешировать вычисления, сокращать ветвления. Но мне кажется, что некоторые вещи без понимания задачи просто никогда не сделать. Это и отличает человека от оптимизирующего компилятора. Поэтому ручная оптимизация все еще играет огромную роль: у компилятора есть только код, а у человека есть понимание задачи. Компилятор не может принять решение, что значение "4" достаточно случайно, а человек может.



Напомню, что речь пойдет об оптимизации операции ресайза изображения методом сверток в реально существующей библиотеке Pillow. Я буду рассказывать о тех изменениях, что я делал несколько лет назад. Но это не будет повторение слово-в-слово: оптимизации будут описаны в порядке, удобном для повествования. Для этих статей я сделал в репозитории отдельную ветку от версии 2.6.2 — именно с этого момента и будет идти повествование.

Читать дальше →
Total votes 48: ↑47 and ↓1+46
Comments65

Как я сделал самый быстрый ресайз изображений. Часть 0

Reading time7 min
Views34K

Здравствуйте, меня зовут Саша, я написал самый быстрый ресайз изображений для современных х86 процессоров. Я так утверждаю, поскольку все остальные библиотеки, которые я сумел найти и протестировать, оказались медленнее. Я занялся этой задачей, когда работал над оптимизацией ресайза картинок на лету в Uploadcare. Мы решили открыть код и в результате появился проект Pillow-SIMD. Любой желающий с легкостью может использовать его в приложении на языке Python.


Любой код выполняется на конкретном железе и хорошей оптимизации можно добиться, только понимая его архитектуру. Всего я планирую выпустить 4 или 5 статей, в которых расскажу как применять знание архитектуры железа для оптимизации реальной задачи. Своим примером я хочу побудить вас оптимизировать другие прикладные задачи. Первые две статьи выйдут в течение недели, остальные — по мере готовности.

Читать дальше →
Total votes 80: ↑79 and ↓1+78
Comments67

Ресайз картинок в браузере. Все может стать еще хуже

Reading time3 min
Views51K

 


Знакомьтесь, это Маня. Маню поразил страшный недуг и теперь она нуждается в вашей помощи. Маня росла обычной девочкой, жизнерадостным счастливым ребенком. Но чуть больше года назад врачи поставили ей страшный диагноз — алиазинг. И она стала выглядеть вот так.



Как выяснилось, виной тому стала жадность и алчность производителей браузеров, которые решили сэкономить на алгоритмах ресайза изображений и применить самые низкокачественные фильтры. Тогда Маню удалось спасти — она прошла курс последовательных не кратных двум уменьшений, что снизило алиазинг и вернуло её былую резкость. Но теперь ей снова угрожает опасность.

Читать дальше →
Total votes 102: ↑87 and ↓15+72
Comments88

Pillow-SIMD

Reading time5 min
Views14K

Ускорение операций в 2.5 раза по сравнению с Pillow и в 10 по сравнению с ImageMagick



Pillow-SIMD — это «форк-последователь» библиотеки работы с изображениями Pillow (которая сама является форком библиотеки PIL, ныне покойной). «Последователь» означает, что проект не становится самостоятельным, а будет обновляться вместе с Pillow и иметь ту же нумерацию версий, только с суффиксом. Я надеюсь более-менее оперативно выпускать версии Pillow-SIMD сразу после выхода версий Pillow.


Почему SIMD


Есть несколько способов улучшения производительности обработки изображений (да и всех остальных вещей, наверное, тоже).


  1. Можно использовать более хорошие алгоритмы, которые дают такой же результат.
  2. Можно сделать более быструю реализацию существующего алгоритма.
  3. Можно подключить больше вычислительных ресурсов для решения той же задачи: дополнительные ядра CPU, GPU.
Читать дальше →
Total votes 23: ↑23 and ↓0+23
Comments5

Ресайз картинок в браузере. Все очень плохо

Reading time10 min
Views104K
Если вы когда-нибудь сталкивались с задачей ресайза картинок в браузере, то вы наверное знаете, что это очень просто. В любом современном браузере есть такой элемент, как холст (<canvas>). На него можно нанести изображение нужных размеров. Пять строчек кода и картинка готова:

function resize(img, w, h) {
  var canvas = document.createElement('canvas');
  canvas.width = w;
  canvas.height = h;
  canvas.getContext('2d').drawImage(img, 0, 0, w, h);
  return canvas;
}

Из холста картинку можно сохранить в JPEG и, например, отправить на сервер. Можно было на этом закончить статью, но сперва давайте взглянем на результат. Если вы поставите рядом такой холст и обычный элемент <img>, в который загружена та же картинка (исходник, 4 Мб), то вы увидите разницу.

img
Читать дальше →
Total votes 156: ↑152 and ↓4+148
Comments90

Pillow 2.7 — Существенное улучшение качества и производительности

Reading time6 min
Views42K
Первого января 2015 года по расписанию вышла новая версия библиотеки для работы с изображениями Pillow 2.7. Так как многие изменения в ней были сделаны командой Uploadcare, мы рады представить вам расширенную версию заметок о релизе этой версии.

Для начала вспомним, с чего все началось. Pillow — дружественный форк (как называют его авторы) популярной библиотеки PIL, Python Imaging Library. Последняя версия PIL 1.1.7 вышла в 2009 году и в основном содержала исправления ошибок. Изначально Pillow задумывался как проект только по приведению в порядок сборки PIL, и разработчики рекомендовали отправлять все баги, не связанные со сборкой, в оригинальный PIL. Но время шло, PIL стремительно устаревала, багов не уменьшалось, тут еще Python 3 маячил на горизонте. Поэтому с версией Pillow 2.0 все изменилось. «Pillow 2.0.0 добавляет поддержку Python 3 и включает много багфиксов со всего интернета» гласит описание проекта на PyPI. И с тех пор понеслось. Каждые три месяца выходили версии с огромным количеством багфиксов и другими улучшениями от различных разработчиков. Самым значительным нововведением за это время было, пожалуй, поддержка форматов WebP и JPEG2000. Теперь пришло время следующего большого шага.
Читать дальше →
Total votes 55: ↑55 and ↓0+55
Comments2

Information

Rating
5,427-th
Location
Санкт-Петербург, Санкт-Петербург и область, Россия
Date of birth
Registered
Activity