[Назад] [Вся нить] [Первые 100 сообщений] [Последние 50 сообщений]
Ответ в нить [Последние 50 сообщений]
Имя
Captcha image [Д]
Animapcha image [@] [?] [Т]
Тема    ( ответ в 1000686)
Сообщение
flower
Предпросмотр
Файл 
Пароль  (для удаления файлов и сообщений)
Параметры   
140368429_p0.jpg - (2.48MB, 4000×4000)
1000686
No. 1000686  
Замечания и предложения по нему, а также их обсуждение.
Предыдущий тред тонет тут >>1000357.
163 сообщений пропущено. Показаны 50 последних сообщений
No. 1000975  
>>1000965
>stretched_aoba.png
Чем и как такое забавное сгенерировано?
No. 1000978  
>>1000975
gimp, Filters → Distorts → Lens Distortion. Подбирать параметры.
No. 1001000  
Автор форматтера приглашается для ревью https://codeberg.org/yakui-lover/fbe-410/pulls/19
No. 1001001  
Пока посмотрел код на телефоне. Я не автор rec_node_format.
> // Currently there's a bug here: it produces 15 lines instead of 16 (compare with <br> above).
Разве в контексте предложенного алгоритма !20:<li>x</li>: не корректнее сравнивать с !20:<br>x:, чем с !20:x<br>?

Всегда ли ли <ul><li> означает новую строку? Или если в самом начале сообщения или сразу после <br>, то переноса строки не будет? I wonder.
No. 1001002  
>>1001001
Э… там какой-то майндфак вообще. Требует изучения. А я подозревал, что вырезание <body> и </body> по индексам это нехорошо.
No. 1001005  
Ну, видимо, дело в моей версии PHP или чём-то ещё. Здесь не воспроизводится.
По существу заданных мне вопросов могу пояснить следующее:

// This is correct (there is a line break after "Begin", even two of them):
testcase(my_expand('Begin<ul>!20:<li>x</li>:</ul>End'), my_expand('Begin<ul>!15:<li>x</li>:</ul>'));
// This is incorrect (15 lines total, not 16):
testcase(my_expand('<ul>!20:<li>x</li>:</ul>'), my_expand('<ul>!15:<li>x</li>:</ul>'));
No. 1001006  
Поскольку автор форматтера не объявился, давайте рассмотрим PR в его отсутствие.

И это, так а чего, будем прикручивать поиск картинок? Для этого постгрес не нужен: вот это отрабатывает в MySQL за 40 мс:

SELECT filename, hash0, hash1, hash2
FROM images
WHERE id BETWEEN 3 AND 199997
ORDER BY BIT_COUNT(hash0 ^ %s) + BIT_COUNT(hash1 ^ %s) + BIT_COUNT(hash2 ^ %s) ASC
LIMIT 30

(После

CREATE TABLE images (
  id       INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
  filename VARCHAR(32) NOT NULL,
  hash0    BIGINT UNSIGNED NOT NULL,
  hash1    BIGINT UNSIGNED NOT NULL,
  hash2    BIGINT UNSIGNED NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4

и вставки 200k записей со случайными хешами).
Вроде бы даже «на холодную» столько же времени требуется.

А хэшер скомпилировать в WASM и запускать на сервере и на клиенте — оказывается, синусы-косинусы-корни зависят от платформы, IEEE 754 не определяет результат до последнего бита. А WASM определяет. Да и сишкой тыкать в живой интерпретатор PHP как-то небезопасно.
No. 1001007  
148054363_p0.jpg - (608.36KB, 2000×3038)
1001007
>>1001006
> И это, так а чего, будем прикручивать поиск картинок?
Всё не могу пока включиться в работу. Так что прошу, если можете, взять дело в свои руки.

> BIT_COUNT(hash0 ^ %s) + BIT_COUNT(hash1 ^ %s) + BIT_COUNT(hash2 ^ %s)
С Постгресом, как минимум, можно обойтись одним bit(192) столбцом вместо трёх. Но если есть желание вскорости увидеть рабочий вариант... Решайтесь.
No. 1001008  
>>1001007
Хорошо.

Из последних упражнений:
  1. Можно заставить выделять памяти максимум 6 байт на пиксель. Это вместе с преобразованием прозрачности в чёрное или белое в зависимости от weighted luma, как у вас. imagemagick, вроде, максимум 4 байта на пиксель может потреблять, ffmpeg — 12.
  2. Center crop на 87.5% хорошо работает, результаты лучше.
  3. Выглядит интересным https://github.com/manjunath5496/ML-Papers/blob/main/Saliency Detection A Spectral Residual Approach.pdf,но у авторов большие проблемы с выражением своих мыслей формализмами — большинство формул и формулировок означают не то, что можно подумать)
Но #2 и #3 это на потом.

> С Постгресом, как минимум, можно обойтись одним bit(192) столбцом вместо трёх.
Ну, в MySQL тоже есть BINARY(192). Только BIT_COUNT с ним не работает (он обрезает входное значение до 64 бит). И, почему-то, даже с BIT_COUNT(whole_hash), что неправильно, оно работает медленнее.

Да и какая разница, если 40 мс?
No. 1001009  
> BIT_COUNT(whole_hash)
BIT_COUNT(whole_hash ^ UNHEX(%s)), конечно же.
No. 1001014  
Будет ли принята фича с поиском похожих картинок, если таковая будет реализована? Там на сервере нужно будет запускать только ffmpeg и мою штуку через что-то типа wasmtime с максимальными ограничениями (без доступа к сети, ФС, etc, с лимитами на память и время работы — настраивается в wasmtime), чтобы было безопасно.
No. 1001015  
>>1001014
>wasmtime
Нет. Пишите на языке кодобазы.
No. 1001016  
kaga.gif - (290.38KB, 320×240)
1001016
>>1001015
На языке кодобазы это будет непрактично, поскольку подход требует обработки изображений, которую у меня не получается выразить в терминах libvips или чего-либо ещё.
Ну и мы планировали это дело на клиенте ещё запускать — там-то точно нужен будет васм, лол.

В общем, weird. Ну может кто-то, не я, сделает версию без блюра на PHP. Но зачем дублировать то, что на клиенте будет.

Васмтайм, оказывается, нет в репозиториях дебиана. Но есть wasmedge и wazero. Чем они-то не угодили?
No. 1001017  
>>1001016
На языке отличным от кодобазы это будет непрактично, потому что сопровождающему тогда придётся знать 2-2.5 языка вместо 1.5.
Пишите отдельный продукт в отдельной репе. А дальше если это можно вызывать через exec, то и славно.
No. 1001019  
eva_com.jpg - (397.03KB, 2048×1902)
1001019
>>1001017
OK. Этот отдельный продукт может требовать для запуска на сервере какой-либо рантайм WASI (wasmtime/wasmedge/whatever)? Без этого можно, но нужно будет заморачиваться с изоляцией (ну и детерминизм потеряется, хотя, опять же, nobody cares).
Запускать какой-то сишный код без изоляции на сервере кажется плохой идеей даже мне, автору кода.
No. 1001022  
139443861_p0.webp - (11.48MB, 4961×7016)
1001022
>>1001019
> детерминизм потеряется
Проблему с синусами-косинусами-корнями разве нельзя решить, захардкодив матрицы преобразования?
> спойлер
Кто он, safe и blazing fast? Верно, дети. Это Rust!

>>1001016
> подход требует обработки изображений, которую у меня не получается выразить в терминах libvips
Какие конкретно моменты не получется? Попробую в субботу посмотреть-таки.
No. 1001023  
>>1001019
У нас там magic и ffmpeg уже запускаются от апача, какая ещё изоляция? Я-то могу что-нибудь настроить, но в случае Соуса, думаю будет проще какой-нибудь просто Докер обернуть.
No. 1001024  
тыктыктык.gif - (486.87KB, 720×720)
1001024
>>1001022
> Проблему с синусами-косинусами-корнями разве нельзя решить, захардкодив матрицы преобразования?
Нет, потому что там ещё exp в blur_gauss_dyn. А вообще, если мы не компилируемся в WASM и не включаем в себя всю лабуду для декодирования изображений, то не имеет смысла заботиться о каком-то детерминизме: всё равно RGBA, которые надекодирует библиотека, может отличаться от платформы к платформе (минимальные пары есть), и уж точно от того, что надекодирует браузер, если мы на клиенте собираемся использовать его возможности для декодирования, а не полагаться на WASM, в котором всё нужное для декодирования уже есть.

> Кто он, safe и blazing fast? Верно, дети. Это Rust!
Ну вот тут не вполне понятно, какой от него прок. Быстрее, чем текущее под bwrap, точно не будет.

> Какие конкретно моменты не получется?
Момент blur_gauss_dyn & scale_nn. Там нужно считать свёртку. Не во всех пикселях, а только в тех, которые нужны scale_nn. Свёртка прямоугольная.

>>1001023
> У нас там magic и ffmpeg уже запускаются от апача
magic и ffmpeg написаны понятно кем, их код всегда под пристальным присмотром, они есть в репозиториях всех крупных дистрибутивов, etc. Поэтому их не должно быть страшно запускать.
Вот эту мою хреновину — должно быть.

> , какая ещё изоляция?
bwrap. Или firejail. Или Podman/Docker/что-то там в systemd завезли.

$ ffmpeg -hide_banner -loglevel error -i картинка.jpg -vf format=rgba -f image2pipe -vcodec pam - | bwrap --ro-bind /usr/bin/busybox /usr/bin/busybox --unshare-all /usr/bin/busybox sha1sum
eb3609abf7df96a19edf40c059bb2f15f2bf5911  -
$

(Для повторения нужен busybox-static, наш хэшер будет тоже статически слинкован, если будет просто читать PAM из stdin.)
Это изоляция вообще всего, включая сеть, ФС, user namespace, etc.

Ну или не через пайп, а использовать ту же SDL2_Image, и прокидывать всё нужное-слинкованное тоже через bwrap.

> Я-то могу что-нибудь настроить, но в случае Соуса, думаю будет проще какой-нибудь просто Докер обернуть.

Можно. Но не знаю, зачем заморачиваться с чем-то ещё, если bwrap умеет всё, что нужно, и есть в репозиториях.
No. 1001026  
> bwrap
Я тут обнаружил, что systemd-run --scope ещё лучше: даже не нужно устанавливать отдельный пакет, и оно работает везде, где есть системд, а bwrap в таком виде не работает на каких-то хентайных hardened-версиях дистрибутивов.

«Если у вас не systemd, делайте bwrap. Если у вас не bwrap, сделайте chmod u+s /usr/bin/bwrap или обращайтесь к нам за помощью, если мы ещё живы.»
No. 1001028  
126222408_p0.jpg - (12.47MB, 5300×3600)
1001028
>>1001024
> Момент blur_gauss_dyn & scale_nn
И правда, крайне неудобно, если возможно.

Судя по всему, в libvips нету условного reduce. Поэтому в терминах php-vips для подсчёта значения в заблюреном пикселе надо будет делать extract_area вокруг него и multiply'ить её на ядро, потом брать у результата avg (sum нету) и умножать среднее на количество элементов в матрице. extract_area не копирует память, а вот multiply, как я понимаю, будет. Что не есть эффективно. И ещё проблема с clamp.

В чём-то побыстрее и понизкоуровнее PHP вроде есть воспользоваться более низкоуровневым Vips.Region и обращаться к пикселям по указателю.

> uint32_t rgba = f(f_userdata, x, y);
На всякий случай. Grayscale, как Соусная "Неправда", и 16-битные цвета, как в некоторых PNG аниме-скриншотах, обрабатываются корректно?
No. 1001029  
RGB565 ещё.
No. 1001031  
phash_haha.png - (130.74KB, 728×755)
1001031
>>1001028
> На всякий случай. Grayscale, как Соусная "Неправда", и 16-битные цвета, как в некоторых PNG аниме-скриншотах, обрабатываются корректно?
Sure thing. Это же SDL2 этим занимается, а нам просто предоставляет SDL_GetRGBA() и количество байт на пиксель (bpp). Мы читаем bpp байт по нужному смещению, передаём результат и SDL_PixelFormat *format в SDL_GetRGBA(), она декодирует в rgba.
format->format может принимать одно из большого списка значений SDL_PIXELFORMAT_*.

У меня готов образец, который читает PAM из ffmpeg’а. И даже прозрачность выставляет в чёрное или белое в зависимости от средней люмы (в основной ветке это пока не реализовано). Ветка prod. Сделать ./build_main_pam.sh и запускать так

ffmpeg -hide_banner -loglevel error -i PICTURE.jpg -vf format=rgba -f image2pipe -vcodec pam - | ./main_pam
No. 1001032  
kosozu_at_computer.png - (1.06MB, 800×800)
1001032
(На картинке была демонстрация корректность обработки grayscale старым хэшером с SDL2_Image.)

Статическая сборка (CC="gcc -static -s" ./build_main_pam.sh) даёт бинарник в 747 кб, что вполне. Его нужно будет потом просто запускать под systemd-run --scope (...какие-то_опции...).

Осталось код на PHP и фронтенд написать.
No. 1001033  
639874d21003300f29ad786214873413.jpg - (130.34KB, 1123×1576)
1001033
>>1001031
>>1001032
Замечательно.

> ffmpeg
Хм. Там такая проблема вроде, что он отказывается картинки, превосходящие где-то 20000 (?) пикселей по одной стороне. С одной стороны, релевантно для сшивок манги. С другой, вряд ли есть польза от phashing'а таких сшивок.
No. 1001037  
c1.png - (85.16KB, 1000×1000)
1001037
>>1001033
> Там такая проблема вроде, что он отказывается картинки, превосходящие где-то 20000 (?) пикселей по одной стороне.
Всё гораздо интересней. Ограничения такие:
  • (8×W + 1024)×(H + 128) < 2147483647;
  • W < 65536;
  • H < 65536.
На практике это означает W×H < ≈260'000'000 (на самом деле верхний предел 259M〜264M в зависимости от aspect ratio).

При этом приведённая мной команда ffmpeg выделяет 8 байт на один пиксель. А наша программа ещё допольнительно 2 байта на пиксель.
Если мы хотим, чтобы всё вместе это потребляло не больше, скажем, 1G (лимит по умолчанию у imagemagick), то площадь (W×H) должна быть < ≈107'000'000. То есть ffmpeg’у нужно передавать именно те самые -max_pixels 100M, про которые мной говорилось в >>1000949.

А ≈107M (ограничение по памяти, которую дозволительно скушать) это меньше, чем ≈260M (техническое ограничение ffmpeg’а).

Мне кажется, получилось неплохо: для компиляции, кроме build-essential, ничего не нужно; собранный бинарник не может сломаться после обновлений, ибо статический; systemd-run даже не нужно устанавливать.
No. 1001038  
1. Должна ли функциональность «похожие картинки» находиться за [кф]апчей?
2. Название пуродакуто®©? Изначально не хотелось название.
No. 1001039  
>>1001038
  1. Под похожие, может быть, а под почти идентичные, думаю, нет.

    Я как это себе представлял: пользователь выбирает картинку для прикрепления, её хэш тут же отправляется серверу, а сервер возвращает, есть ли likely идентичные картинки. Если есть, показывается в status bar'е о том уведомление и reflink на одну из.

    Но это про почти идентичные. А под похожие, наверное, окно вроде «Избранные нити» или отдельную страницу? На которую в уведомлении давать ссылку, если почти идентичные или похожие были обнаружены.

  2. You decide. Я бы на чём-то совсем утилитарном остановился вроде round_phash.
No. 1001040  
>>1001039
Вы понимаете, что такое захочется трогать даже не только для того чтоб постить - а чтоб найти что-то милое?
No. 1001041  
146735452_p0.jpg - (853.25KB, 1240×1754)
1001041
>>1001040
Ну, я из соображений отказоустойчивости и хотел HNSW индекс.

Но будут ли желающие? Ведь iqdb вроде не трогают для целей поиска милоты, и вряд ли iqdb для таких целей сколь-нибудь удовлетворительно. И надолго ли желания у желающих хватит? Скажем, если похожие картинки бывают редко: сделать поиск без капчи вплоть до расстояния, где false positive rate < 0.001). Более глубокий пока отключить вовсе, а потом спрятать за капчу. Сейчас, мне кажется, менять-возиться с капчесистемой будет нецелесообразно муторно в рамках MVP.

Как альтернативу капче можно потом rate limiter.
No. 1001042  
govoryaschaya_ryba.jpg - (78.29KB, 625×500)
1001042
О чём вы?

MySQL пробегается по 200k записям за 40 мс (мой эксперимент из >>1001006). У нас сейчас ≈20k картинок. ffmpeg [...] largest_image.webp | ./main_pam отрабатывает, on the other hand, за 3.7 сек.

Т.е. bottleneck в вычислении хэша, а не в поиске.

Даже если у нас накопится >200k картинок, можно брать 200k последних (для этого я замерял вместе с WHERE clause).

Мы ещё не перешли на постгрес. Даже если перейдём, непонятно, будет ли от HNSW вообще какая-либо польза.
No. 1001044  
В общем предлагаю сделать что-то типа такого.
Не знаю, нужно ли syncWithReality().
Можно вместо этого написать скрипт.
Для работы с load balancer’ом нужно будет расширить протокол Load_Balancer, добавив хотя бы Get_Available_Files.
Само изображение можно запрашивать по URL (это KU_FILESERVER?).
Потом интегрировать в кодобазу.

class SimilarPicture {
    public string $board;
    public int $postid;
    public int $distance;
}

class SimilarPicturesService {
    __construct(
        MySQL $tc_db,
        string $hasherExecutablePath,
        int $maxRowsToQuery = 200_000,
        int $maxSimilarToFind = 30,
        string $isolationMethod = 'via_systemd_run'
    )

    // Returns false if image cannot be hashed.
    addRecord(
        string $board,
        int $postid,
        string $imagePath
    ) : bool

    // Returns null if image cannot be hashed, otherwise an array of 'SimilarPicture' objects.
    findSimilar(
        string $imagePath,
        int $maxDistance = -1
    ): array|null

    // Delete everything except the latest 'maxRowsToQuery' rows.
    deleteOld() : void

    // Delete rows for all images not physically present on disk anymore.
    // If $onlyDelete === false, also hash, and add rows for, all images that are physically present on disk.
    // This may take some time.
    syncWithReality(bool $onlyDelete) : bool
}
No. 1001045  
Алсо, ping regarding PRs.
No. 1001047  
board_php.webp - (52.63KB, 2173×235)
1001047
>>1001044
В рамках текущей архитектуры, не проще ли получать phash файла в upload.class.php, обращаясь, также как и в случае с генерацией preview, к файлу по $_FILES['imagefile']?

И либо передавать получаемый в $upload_class пхэш методу $post_class, либо insert'ить в image_phashes таблицу прямо в board.php, если есть что.

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

Если отказаться от кроссбородового поиска, можно без особых неудобств хранить пхэши в тех же posts_ таблицах: тогда и функции удаления обновлять не надо, правда, поиск может стать куда дольше.
No. 1001048  
>>1001047
> В рамках текущей архитектуры, не проще ли получать phash файла в upload.class.php, обращаясь, также как и в случае с генерацией preview, к файлу по $_FILES['imagefile']?
> И либо передавать получаемый в $upload_class пхэш методу $post_class, либо insert'ить в image_phashes таблицу прямо в board.php, если есть что.
> А удалять запись из image_phashes при удалении поста или только его файла; пусть у нас и несколько разных функций связанных с удалением в кодобазе, каждую из которых надо обновить.
Оно и будет так, только функции, связанные с хэшами, будут в отдельном модуле.
Я не вижу недостатков в этом.
Из преимуществ: separation of concerns (у нас и так manage.class.php весит 212 Kb); легче будет выпилить это всё, если будет надобность.

> только его файла
Администратор может удалить файлы через rm -rf, если через модерку по какой-то причине не работает. syncWithReality() нужно для этого. Ну ещё и для хэширования всего, что есть, при первом деплое этой фичи.

> Если отказаться от кроссбородового поиска, можно без особых неудобств хранить пхэши в тех же posts_ таблицах: тогда и функции удаления обновлять не надо, правда, поиск может стать куда дольше.
Не понял про «функции удаления обновлять не надо». А таблицы с неконстантными именами это плохо, уже натерпелись с posts_$board (это единственное, что сейчас держится на дисциплине, всё остальное сделано/можно сделать с ? placeholders).
No. 1001049  
Я, наверное, несколько непонятно выразился в >>1001044.

Следует читать так:

В общем предлагаю сделать что-то типа такого. Потом интегрировать в кодобазу.
<отступление>
Не знаю, нужно ли syncWithReality().
Можно вместо него (метода syncWithReality()) написать скрипт.
Если этот метод всё-таки будет иметь место, и он должен будет работать с load balancer’ом, то нужно будет расширить протокол Load_Balancer, добавив хотя бы Get_Available_Files.
В таком случае изображение можно запрашивать по URL (это KU_FILESERVER?), не добавляя ничего дополнительного в протокол Load_Balancer.
No. 1001050  
>>1001045
Я в малой доступности ещё джве недели.
No. 1001051  
>>1001050
ОК.
>>1001047
> Если отказаться от кроссбородового поиска, можно без особых неудобств хранить пхэши в тех же posts_ таблицах: тогда и функции удаления обновлять не надо, правда, поиск может стать куда дольше.
Вашу эту мысль я теперь понял. Я не хочу так делать. Не только из-за скорости поиска (не измерял, но думаю, что таки да, куда), а ещё и из-за количества действий, необходимых для того, чтобы эту фичу потом выпилить. Orthogonality.
No. 1001053  
>>1001045
Последнее с изменением ДБ солью чуть позднее.
No. 1001054  
Тред тонет. Пожалуйста, перекатите.

>>1001053
Спасибо. >>1001044 более-менее принято? Вместо syncWithReality() будет скрипт, иначе слишком хрупко это всё будет (у апача и PHP в нескольких разных местах стоят таймауты на время исполнения кода на пхп для страницы).
No. 1001055  
ЪЭЯГОУ
No. 1001056  
ВНАКЛЫ
No. 1001057  
ЖЭУГЧБ
No. 1001058  
ЧЁЪЦЖУ
No. 1001059  
ЧВФПДЪ
No. 1001060  
ИАКХНС
No. 1001061  
ДПЕБЯЭ
No. 1001062  
МНЦБЙЭ
No. 1001063  
ШЩНСЭМ
No. 1001064  
ЫЗТФЖУ
No. 1001065  
Можете удолить, это я тестировал [Pr. 109]. По паролю (DELETE_ME) не удаляется почему-то.
Удалить сообщение []
Пароль  
[Mod]