Попробовал снова поиграться с более продвинутыми методами поиска, но, опять не пришел к положительным результатам. SIFT/SURF слишком громоздки. ORB ведет себя тоже неплохо, но полегче, и исполняет поставленные задачи, но, встает более серьезная проблема - поиск. Для снижения количества ложно-положительных результатов поиска нужно увеличивать количество точек для изображения. Увеличение количества точек - больше данных для поиска. Больше данных для поиска - меньше скорость и требуется больше мощностей. На реакторе больше 7 миллионов изображений. При < 100 точек - результат ультра гавно. 200-300 - более менее, но не на таком объеме. Это неплохо работало бы, если бы было 1-2 миллиона изображений. +- допустимые результаты, для такого объема, это 450+ точек на изображение. Итого, 3 миллиарда точек. Это порядка 200+ гигов данных, которые нужно хранить в оперативе, для более быстрого поиска. И даже при таких условиях поиск одной картинки длиться порядка 20-25 секунд, что уже далеко за приделами комфортного уровня. Можно ли решить это? Да, конечно, но это уже нужно распределять все на штуки 4+ сервера, а цена аренды такого удовольствия выходит слишком большая(150$+). Согласно опросу недавнему, она вроде бы подъемная, но, я прекрасно понимаю что обстоятельства у людей меняются. Кто-то переоценил свои финансовые возможности, а кого то просто заебет донатить на это, а бегать постоянно делать посты на это тему... Ну такое себе удовольствие.
Потому сорян, я правда старался, но уперся в ограничения не связанные с программными аспектами. Или может вы подскажите метод поиска hamming, который работает быстро на огромном объеме данных, и при этом не требует существенных апаратних ресурсовp.s. это разве что собирать сразу на годик+ аренды, и тогда есть смысл дальше играться, но уже с несколькими серверами
И так въебал на это просто прорву времени и сил, и танцевать дальше уже с пачкой серверов не горю желанием сейчас
Парето был умным мужиком, 20% усилий/затрат дают 80% результата.. А больше не особо и надо..
Вы не особо представляете на сколько это громадный объем данных
Ну хотя бы гистограмму какую-то вместо картинки получить.
Обучить описательную сеть на небольшой выборке. Посмотреть как будет работать с изменёнными, шакальными и прочими изображениями из обучающей выборки.
Кстати, есть возможность для расширения функционала, вроде рекомендаций недостающих тегов.
1.5 Blur+downscale всю картинку.
2. Размер каждого квадрата 5% от ширины на 5% от высоты.
3.Координаты задаются в процентах от высоты и ширины картинки(X:10%,Y:5% и т.п.)
2. Квадрат представляешь как матрицу из чисел и получаешь хэш.
3. Держать все хэши в памяти не нужно.
Асинхронно читай с диска в режиме потока и скармливай проверятору.
4. Как только 3 квадрата нашлись в хэшах запускаешь попиксельную проверку с погрешностью.
5. Если всё ещё медленно - выводи спиннер "Ах если бы ты задонатил - спинера бы не было."
Квадратный метод - это префильтор. Основная работа идёт только когда ловится совпадение.
Если не нравятся квадраты - можешь группировать по цветовой маске. Например, создать кластера по цветовой маске, соотношению сторон.
Поиск будет проще и быстрее.
Соотношение сторон - кроп передает привет
Идею я понял, сократить количество возможных вариантов с миллионов до десятков тысяч - сотен тысяч, но оно не сильно помогает. Потому нужно сокращать количество до сотен. При среднем количестве точек в 500/картинку будет приемлемая скорость поиска. А как можно это сделать? Квадраты - хуйня. Сделать их маленькими - будет тьма данных. Сделать их большими - не будет ловить нужные. Цветовая маска не работает. Соотношение сторон тоже. Что еще можно использовать? Количество точек на изображении? При сжатии режутся градиенты, и на их месте появляються ложно положительные точки, потому даже для внешне одинаковых изображений, количество точек может отличаться в разы. Легкий blur, что бы убрать эти ступеньки, существенно увеличивает количество кожно положительных срабатываний
Здесь идёт речь о том, что пользователь пытается обмануть баянометр, изменяя размер картинки и цветокор картинки?
Ну понятно, что для поиска эта картинка уже не даст 100% точности сравнения. Это уже какой-то ИИ нужен, чтобы прогонять ещё несколько тысяч проходов, изменяя размеры картинки относительно эталона и то же самое делать с цветокором, хотя каким хером его подберёшь, там же фильтры ещё есть.
Превратить всё в монохром, так там выйдет какая-нибудь яркость-контрастность другая.
Ясно же, что будут какие-то отклонения от 100%.
Банально, новый текст на картинке запилят и это уже новый мем, новый демотиватор с другим текстом. Это тоже баян?
Выходит, нужно получать, к какой картинке по каким параметрам ближе всего, не со 100% совпадением.
Нельзя же определить точно, что "на этой картинке кот, цвет белый, глаза желтые" или "на этой картинке 3 светофора" или "на этой картинке мем JoJo". Вряд ли можно прогнать и такие параметры получить?
Хотя бы можно получить что-то наподобие "на этой картинке 3 объекта, 1 с площадью около 70%. 2 других с площадью 10%, преобладающий цвет синий (возможно небо или море), первый объект преобладающий цвет чёрный" ?
Просто получить хоть какие-то параметры с картинки, даже не вникая в то, какие они (чёрный ящик). И уже эти параметры сравнивать.
По форме, по площади, по относительному расположению.
На выходе просто набор цифр будет, коефициент a1:23 b3:48 и так далее.
И вряд ли оно на 100% совпадёт, если картинку подгоняли под обход баянометра.
как я и думал, нужно делать кучу операций для каждого изображения, а это пипец как затратно, нужно обладать хорошим железом, мощными видяхами, скорей всего.
По несколько сотен для каждой пикчи.
Короче, была бы крутая видюха, я бы повозился, а так смысла нет гадать.
Посчитать, на каком расстоянии расположены максимумы и минимумы и потом проверять, укладываются ли какие-либо несколько точек в указанные пропорции.
Можно попробовать на небольшой порции картинок и заранее известных паттернах или частях картинок.
Можно ли брать ограниченное количество точек (50 лучших) на целевом изображении и точек 100 на таргетах. Сохраняем хорошие таргеты, чтобы потом прогнать их с большим количеством точек. Можно попробовать сперва грубым ORBом пройти, потом SIFTом для сокращения ошибок.
Взять простую hash функцию которая при сравнении выдает хороший false negative близкий к 0, ну и конечно со средненькими остальными параметрами, но не с отвратительными.
Я не знаю какие варианты изменения картинок должны быть учтены, но как пример преобразовывать картинку до квадрата 2*2 и отсортировать цвета, можно в rgb, но можно и в hls. Можно и 1 доминирующий конечно взять, тут сильно зависит от входных данных.
Собрать hash со всех текущих картинок и кластеризовать с помощью к примеру c-means, прийдется с параметрами повозится, но надо решить по количеству кластеров дабы разбить на нормальное количество групп нормального размера.
При поиске выполнять hash для картинки и проверять к каким кластерам он относится с определенным порогом, далее уже можно использовать более традиционные методы, которые работают на меньших объемах данных.
Как вариант если hash не учитывает какие либо преобразования, то при поиске для картинки можно вычислять hash несколько раз до преобразования и после, далее сравнивать с теми кластерами с которыми похожи.
Это позволит уменьшить время для поиска. Так как вычисление hash не должно быть сложным, сравнение с центрами кластеров также простая операция. А далее пойдут более тяжелые операции на меньших объемах.
баянометр замолчал..
На работе коллега пилил статью на схожую тему, уже есть гораздо более приятные инструменты:
https://newtechaudit.ru/sopostavlenie-izobrazhenij-s-pomoshhyu-python-i-kornia/
Да, не вопрос, наверное она работает, и работает хорошо. Как быстро производить поиск по 7 лямов изображений. Вот главный вопрос
https://neon.tech/blog/pg-embedding-extension-for-vector-search
Как вариант - тот же Кликхаус:
https://clickhouse.com/docs/ru/sql-reference/functions/bit-functions?ysclid=lk5q6wailp474740462#bithammingdistance
Можно в лоб пробовать, но я бы заморочился с дополнительными признаками чтобы сократить выборку можно было, например - набор цветов.
Дополнительные признаки не работают. Работали б - уже давно сделал бы. Можешь почитать комментарии выше
Опенсурс же, э, хоть сам контрибьють.
Greenplum, Vertica, только я хз, есть ли там нужные функции или придётся руками реализовывать. В любом случае, мне кажется, нужна колоночная БД чтобы не таскать с диска гору ненужной инфы.
Отказываться от чуть ли не коробочного решения по идеологии - ну хз.
По какой причине там яндекс хз, может спонсоры. На работе используем для метрик, хорошая штука.
https://aws.amazon.com/ru/solutions/implementations/clickhouse-cluster/
Потому что изначально Кликхаус - разработка Яндекса. Как и Catboost, например.
можно попробовать поискать бд с реализациями индексов на таких деревьях, либо держать рядом микросервис для поиска на каком-нибудь расте, который за пару дней можно написать комбинируя примеры кода из документации даже не зная раст.
ищи реализации, которые поддерживают динамическое добавление элементов в дерево.
скорей всего любая реализация индекса для поиска расстояний между хешами это будет дерево. вопрос только какое и как реализовано.
"очень много ресурсов" - это сколько? в память не влазит? нужно смотреть реализации, которые умеют держать индекс на диске. разбивать деревья на деревья поменьше и каким-то образом индексировать их, чтоб знать к какому дереву идти.
но в целом поиск по миллиадру значений это в любом случае интересное удовольствие. вот простая математика:
предположим, что размер хеша 64бит. это 8 байт.
миллион хешей это 8мб. за 120мс 8мб на современном процессоре можно обойти просто фуллсканом. наверное, даже не раз.
7 миллионов хешей - 56мб. это не фантастический объем данных.
миллиард хешей это 8 гб. 8гб фуллсканом обойти за разумное время за адекватные деньги за 120мс невозможно. а значит мы возвращаемся к первому пункту - нужен индекс.
а индекс это будет дерево.
Гуглеж на скорую руку выдал вот это обсуждение на stackoverflow (как раз поиск картинок) один чувак в комментах расписывает и мощностя и упоминает примеры с 15М объектов..
https://stackoverflow.com/questions/32785803/similar-image-search-by-phash-distance-in-elasticsearch
Миллион секунд = 11.5 дней
Миллиард секунд = 32 года
Когда на вход баянометра подаётся картинка - тоже проганяется через классификатор и поиск производится через только через пространство тех картинок у которых совпадают теги (часть тегов). Это позволит отсеивать кууучу сорцов которые явно не совпадут.
1. классификатор(грубо говоря определили что это аниме арт - отбрасываем не аниме картинки)
2. преобладающие цвета(эту технику вообще недооценивают, т.к. любой туториал начинается с "переводим в грейскейл", бонусом тут идёт инвариантность относительно размеров, соотношения сторон).
3. попробовал-бы гистограммы цвета. Решение элеметарное, очень "в лоб", но кажется зайдёт для такого контента хорошо
возможно подойдет какой-то коэффициент соотношения сторон с допуском. маловероятно что картинка 16:9 будет баяном картинки 10:6
свети цветовое пятно с коэффициенту тоже хорошая идея. опять же сравнивать с возможностью некоторой погрешности
картинки по вертикали маловероятно что будут отражены, но могут быть отражены по горизонтали. возможно есть смысл делать центральный срез в пропорции, рубить его на шинглы и сводить к какому-нить цветовому пятну яркость которого использовать как коэффициент ( опять ) по которому отсеивать с некоторой границей допуска совпадения
Цвета - помойка. Я не знаю какой долбоеб это везде пропагандирует, но это буквально худший метод из возможных. Очень дорогой по ресурсам, не жрет шакальство, не жрет ватермарки, не жрет нихуя.
Доп разобрал по комментариям выше:
https://joyreactor.cc/post/5589139#comment28045163
у вас есть большой объем данных с которым в момент надо быстро сравнивать.
этот объем данных можно процессить и до запроса когда скорость важна
не весь объем данных на самом деле нужен, а только небольшая фракция. на сколько эта фракция большая зависит от того что считается баяном, а что нет. тобишь нужен список того что точно указывает на то что это баян
картинки могут отличаться друг от друга по ряду параметров которые уменьшат выборку. так как могут быть какие-то неточности в изображениях ( ватермарки, сжатие, отражение и т. д. ) то точное сравнение на большой выборке использовать нет смысла, но и неточные, скорее всего, позволят отсеять практически все что вот прям совсем не похоже
используя сравнение по точкам вы, возможно, каждый раз собираете точки с изображений. почему бы не хранить собранные данные чтобы каждый раз не обрабатывать весь массив данных?
вообще задача любопытная и явно 100500 раз решенная. надо лезть в гугл и искать что-нить на английском по этому поводу
Есть 100500 решений, которые не работают когда количество данных переваливает за 10 лямов
самый банальный вариант:
соберите себе в папочку десяток оригинальных картинок и баяны к ним. выделите что повторяется. потом найдите еще пару десятков разных изображений и выделите то что всегда отличается
но, мне кажется, про предварительную обработку изображений для получения по ним данных можно найти уже готовые решения которые помогут упростить отсев совсем неподходящих вариантов
тем более что всего 10 лямов вариантов. большая часть индексов бд будет весить несколько десятков метров
Мне кажеться ты просто не понимаешь всех подводных камней этой задачи
у вас проблема с выборкой данных. выборку можно сократить. чтобы сократить кол-во данных в выборке надо вывести правила отсева данных которые точно не нужны в выборке при этом чтобы этот отсев стоил минимальное кол-во ресурсов
Есть условный хэш 39e5bd14f7a80c62, и он считает побитное отклонение, так? Можно рассчитать сумму "по символам". И изначально брать в поисковую выборку диапазоном от сумма +- допустимое отклонение. Эта сумма хотя бы будет индексироваться, хоть и увеличим базу на ~12Гб.
Далее мне было лень эксперементировать но один мой знакомый(https://chat.openai.com/share/f3ae236e-42f5-4ffd-b1f0-bfbb21c6c0d6) подсказал как можно пожать фичи.
В конце нужно по ним будет искать и тут есть варианты https://stackoverflow.com/questions/48019842/get-minimum-euclidean-distance-between-a-given-vector-and-vectors-in-the-databas. faiss я поставилл но далльше не стал ковыряться.