За последние 24 часа нас посетили 22399 программистов и 1150 роботов. Сейчас ищут 676 программистов ...

[РЕШЕНО] Куплю скрипт

Тема в разделе "PHP для профи", создана пользователем artoodetoo, 9 дек 2017.

  1. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.072
    Симпатии:
    1.237
    Адрес:
    там-сям
    @TeslaFeo молодец, я посмотрю.
    @voral конечно фон учитывается ровно так же как всё остальное. если фона много, его цвет будет доминировать.
     
  2. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.072
    Симпатии:
    1.237
    Адрес:
    там-сям
    У меня самого есть кой-какие идеи насчёт оптимизации. Не хочу сейчас озвучивать, чтобы не повлиять на чей-то выбор. Позже раскажу.
     
  3. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.553
    Симпатии:
    631
    Осталось подготовить для гитхаба
     

    Вложения:

    • topPalette.PNG
      topPalette.PNG
      Размер файла:
      172,1 КБ
      Просмотров:
      8
    TeslaFeo нравится это.
  4. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.553
    Симпатии:
    631
    Нарештi сподобился.

    Спасибо @artoodetoo за интересную задачу, хоть появился повод что-то нормально на гитхабе оформить. Ты уж извини насчет прав, публикую под MIT =)

    Paletter.
    https://github.com/VasyaSh/Paletter

    Я обратил внимание на то, что в примере из первого сообщения всегда используется одна и та же палитра. Это означает, что не обязательно нужно выбирать цвета из картинки. Можно взять сравнительно небольшую палитру и притягивать цвета изображения к её цветам, начисляя очки каждому цвету за каждый пиксель.
    Поэтому я решил генерировать свою палитру из 210 цветов и 46 градаций серого

    [​IMG]

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

    [​IMG]

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

    [​IMG]

    Это всё оформлено в виде наглядного (в ущерб быстродействию, конечно) ООП. Хотя кое-какие оптимизации есть.
    Paletter.php - класс, с которым можно полноценно работать.
    Classes/Base.php - класс палитры с функцией построения 256-цветного спектра.
    Classes/RealImage.php - класс представляет анализируемую картинку. Создает для себя уменьшенную до 200 пикс. по стороне картинку и разбирает попиксельно.
    Classes/PseudoImage.php - класс для подмены (на анализ) реальной картинки на фейк с заданным количеством пикселей заданных цветов. То есть, как было сказано, не нужно второй раз гонять картинку по уменьшенной палитре. Достаточно передать вот такой объект с информацией, каких пикселей какого цвета сколько в нём (ведь это как раз результат первого анализа).
    Classes/Color.php - класс цвета. Умеет разбирать целочисленный индекс на составляющие по RGB, а так же пересчитывать целое число при изменении значений каналов.

    В папке примеров готовые скрипты для просмотра палитры, разбора картинки на 256 цветов, разбор на топ-10 цветов.

    Анализ картинки на моем сервере занимает около 30 секунд. Любая картинка (кроме маленькой) будет анализироваться одинаково долго, потому что все приводятся к примерно одинаковому размеру.

    А что меня осенило в понедельник, это способ нахождения ближайшего цвета. Как сравнивать? Есть элементарный прием. Будем считать значения R, G, B как координаты в трехмерном пространстве x, y, z. Тогда длина отрезка между двумя цветами рассчитывается по формуле
    [​IMG]
    Здравствуй, школа. Хотя, это только предположение, что ближайшие цвета будут похожими. Но результаты, вроде бы. приемлемы. И есть мысль, что можно в одну функцию уместить редукцию количества цветов с самой картинки, "притягивая" ближайшие друг к другу, до сокращения к нужному числу.
     
    TeslaFeo нравится это.
  5. voral

    voral Активный пользователь

    С нами с:
    30 ноя 2017
    Сообщения:
    646
    Симпатии:
    104
    @[vs], а если берем цвет (0,0,100). И есть два цвета (0,100,100) и (0,0,300). (утрировано развел).Точно не окажемся в ближнем, но визуально другом цвете?
    --- Добавлено ---
    Даже лучше с одним расстоянием (0,100,100) и (0,0,200)
     
  6. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.072
    Симпатии:
    1.237
    Адрес:
    там-сям
    ну видимо ты так отказался от премии. ещё не факт, что ты бы её заслужил ;) народ, TeslaFeo у нас вне конкурса. челендж продолжается.

    никак не соберусь посмотреть код. в любом случае поздравляю! жди от меня issues на гитхабе.
     
  7. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.553
    Симпатии:
    631
    @voral как бы да, темный синий (0, 0, 100) запросто окажется ближе к темному сине-зеленому (0, 99, 100) чем к яркому синему (0, 0, 200), однако тут можно спорить, что лучше. Вспоминается эта иллюзия с оранжевой ячейкой на темной стороне.

    @artoodetoo я открыт для пожертвований :D
     
  8. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.072
    Симпатии:
    1.237
    Адрес:
    там-сям
    моя идея оптимизации в том, чтобы доверить тяжелые процедуры сишным библиотекам. то есть делегировать GD или ImageMagic.
    думаю сначала надо их попросить ужать картинку до какого-то скромного размера. суть в том, что маленькая превьюшка содержит те же цвета в среднем. пикселы могут потеряться, но вариант масштабирования imagecopyresampled() бережно относится к цвету, вычисляя средние значения. в чём-то картинка станет даже достовернее с точки зрения зрения :D .
    кто когда-нибудь смешивал краски на палитре, поймёт о чём я. затем я думаю поиграть с imagetruecolortopalette() чтобы упростить палитру. ну а со скромным остатком пикселей и цветов уже можно на PHP работать за ограниченное время ;)
     
  9. voral

    voral Активный пользователь

    С нами с:
    30 ноя 2017
    Сообщения:
    646
    Симпатии:
    104
    Мысли в слух (пока не проверял):для метода с расстоянием в 3D. Корень,квадрат,сложение и вычитание. Заменить на слеующее. Например принимаем параметр погрешности 8. И каждый цвет приводим следующим образом:
    PHP:
    1. function convert(array $rgb,$koeff = 8) {
    2.    return [
    3.       'r' => intdiv($rfb['r']/$koef)  * $koef  + $koef  / 2,
    4.       'g' => intdiv($rfb['g']/$koef)  * $koef  + $koef  / 2,    
    5.        'b' => intdiv($rfb['b']/$koef)  * $koef  + $koef  / 2,
    6.    ];
    7. }
    --- Добавлено ---
    Точнее правильнее будет с математическим округлением
     
  10. Maputo

    Maputo Активный пользователь

    С нами с:
    30 июл 2015
    Сообщения:
    1.136
    Симпатии:
    173
    @artoodetoo, может пора ТЗ актуализировать?
    Например, может ли использоваться imagemagik? Если требуется 1 оттенок вывести на 100% - это будет преобладающий оттенок или усредненный оттенок всей картинки? В примере @[vs] два красных оттенка считать одинаковыми или разными? Ну и почему @TeslaFeo вне конкурса? Он выполнил все пункты ТЗ.
     
  11. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.072
    Симпатии:
    1.237
    Адрес:
    там-сям
    @Maputo я не думаю, что такие детали надо конкретизировать.

    по мне так выводы можно делать только попробовав код на нескольких разных картинках, взять результат и зарядить в поиск, на который я дал ссылку. если результат будет на глаз близок к исходной палитре, значит получилось. лично мне по барабану что там за цифры #100100100 или #0f8100104, мне интересно похоже или не похоже.
     
  12. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.553
    Симпатии:
    631
    @artoodetoo я поигрался с resized и resampled, и выяснил, проблема с маленькими фрагментами практически не решаема. К примеру, какой-то цвет может суммарно занимать прилично места, но быть раздроблен на мелкие фрагменты по всему изображению. Уменьшение без сглаживания его просто съест, но сохранит соседние цвета. Со сглаживанием - смешает в какую-то кашу непонятного цвета, которая в итоге будет в результате.

    @voral можно в математической формуле, к примеру после возведения в квадрат, делить на коэффициент лидирующий канал, тем самым сокращая расстояние между цветами с одинаковым лидирующим каналом.
     
  13. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.072
    Симпатии:
    1.237
    Адрес:
    там-сям
    зайду издалека:
    эксперимент. сделай в фотошопе картинку где вертикальные полоски в 1 пиксель толщиной чередуются. например каждая вторая синяя, а каждая первая жёлтая. размножь это до, например, 300 пикселей в ширину. теперь отодвинься от экрана и посмотри какого цвета картинка.
    она зелёная! так какой цвет нам надо искать в итоге?
     
    [vs] нравится это.
  14. voral

    voral Активный пользователь

    С нами с:
    30 ноя 2017
    Сообщения:
    646
    Симпатии:
    104
    @[vs], тут даже не лидирующий, вероятно, а все надо на их весовые коэффициенты. Ведь при одинаковом лидирующем важен будет уже второй канал.
     
  15. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.553
    Симпатии:
    631
  16. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.072
    Симпатии:
    1.237
    Адрес:
    там-сям
    как-то так: [​IMG]
     
  17. Maputo

    Maputo Активный пользователь

    С нами с:
    30 июл 2015
    Сообщения:
    1.136
    Симпатии:
    173
  18. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.072
    Симпатии:
    1.237
    Адрес:
    там-сям
    мне не удалось расставить пиксели равномерно. видна текстура ))) но думаю суть понятна. глаз "замыливает" мелкие детали, вычисляет усреднённый цвет. поэтому я считаю, что потеря мелких фрагментов не критична, когда наша цель выделить преимущественные цвета. по человечески это зеленый цвет, а по машинному синий + желтый.

    но в итоге, повторюсь: только реальный прогон на нескольких сильно разных картинках может выявить лучший вариант.
    --- Добавлено ---
    грязно зеленый. другие оттенки исходных цветов дали бы более чистый результат
     
  19. TeslaFeo

    TeslaFeo Старожил

    С нами с:
    9 мар 2016
    Сообщения:
    2.989
    Симпатии:
    759
    ИМХО уменьшать картинки не надо. Надо выбрать ширину диапазонов по вкусу.
    40 сек - это не много. Можно в цикл пачку картинок засунуть, запустить через консоль и оставить на ночь.
    Результаты сохранить в БД и потом пользоваться.
    Или для добавления картинок можно реализовать что-то типа очереди и кроном запуливать по ночам.
     
    voral нравится это.
  20. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.072
    Симпатии:
    1.237
    Адрес:
    там-сям
  21. Maputo

    Maputo Активный пользователь

    С нами с:
    30 июл 2015
    Сообщения:
    1.136
    Симпатии:
    173
    Вообще для выбора диапазонов есть определенный метод, но он, так сказать "на скорую руку":
     
    #71 Maputo, 19 дек 2017
    Последнее редактирование: 19 дек 2017
  22. TeslaFeo

    TeslaFeo Старожил

    С нами с:
    9 мар 2016
    Сообщения:
    2.989
    Симпатии:
    759
    и как с этим бороться? есть мысли?

    как из FFFF00 и 0000FF получить 00FF00 ? )
     
    #72 TeslaFeo, 20 дек 2017
    Последнее редактирование: 20 дек 2017
  23. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.553
    Симпатии:
    631
    Компьютеры складывают цвета так
    PHP:
    1. $color1 = 0xFFFF00;
    2. $color2 = 0x0000FF;
    3. echo dechex(($color1 ^ $color2) / 1.875);
    из синего + желтый получится серый 888888.
    --- Добавлено ---
    А не, это фигня какая-то. Но не фигня, что ресайзинг сводит к серому (по крайней мере в Paint).
     
  24. TeslaFeo

    TeslaFeo Старожил

    С нами с:
    9 мар 2016
    Сообщения:
    2.989
    Симпатии:
    759
    ресайзить не надо. Надо как-то пиксели объединить в группы и вычислить какой цвет летит в глаз пользователю)
    при этом четкие границы в группах пикселей быть не может.
    Шизофрения короче какая-то)
    мне пока-что задача кажется нерешаемой.
    Можно на выходных побаловаться.
    Если научиться вычислять зеленый из синего и желтого, то можно брать группы пикселей,
    распределять равномерно по площади и вычислять выходной цвет.
    Но тут упрешься в разную плотность пикселей на разных устройствах.
    Короче хз...
     
  25. voral

    voral Активный пользователь

    С нами с:
    30 ноя 2017
    Сообщения:
    646
    Симпатии:
    104
    Этот пример как раз и показывает что уменьшать изображения перед анализом нельзя. Т.к. исходное избражение может состоять, например, четких синих и желтых элементов, и именно так и выглядеть (предположим у нас картинка 5000 х 5000 квадраты размером 50х50) а она у нас сведется к грязно зеленому. Более того если уменьшать правильно то надо не за один подход 5000x5000 -> 100x100. А в несколько этапов (сейчас конкретики не помню, подчерпнул из статей по работе с фотографиями). Т.е. это дополнительные затраты времени и ресурсов.

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

    Ну и несколько заметок на полях:
    1. Стоит учитывать прозрачность. Т.е. пикселы у которых прозрачность 0 вообще убирать. С полупрозрачными надо подумать,. Т.е. alpha возвращаемый imagecolorat то же стоит учитывать
    2. Для ускорения анализа - написать модуль для php. (с, c++, freepascal и т.п.)....