plzombie / depress

Program to create djvu from multiple files (using djvulibre)
https://depress.tech/
BSD 2-Clause "Simplified" License
4 stars 1 forks source link

Version 1.8 #13

Closed plzombie closed 2 days ago

plzombie commented 7 months ago

Таски на версию 1.8

Опционально

plzombie commented 2 months ago

Добавить автодетект папки, куда установлен djvulibre - done

zvezdochiot commented 2 months ago

Для определения цветного/серого пользуй S из HSL:

Si = max(RGBi)-min(RGBi)
S = (max(Si)+mean(Si))/2
S < T ? gray: color

Для определения ЧБ пользуй гистограмму серого:

G=gray(RGB)
H=histogram(G)
up=upper(H != 0)
low=lower(H != 0)
t = k*(up-low)
Sup = sum(H(up...up-t))
Slow = sum(H(low...low+t))
S = sum(H)
(Sup + Slow) > k*S ? BW : gray

PS: можешь испльзовать два отдельных коэффициента: klow (для чёрного) и kup (для белого). Или вообще только чёрный.

plzombie commented 2 months ago

Опция -auto добавлена и работает для простейшего случая, требует доработки. Поддержку tiff я делать, скорее всего, не буду, так как libtiff сама по себе огромная библиотека (или надо брать libtiff от djvulibre)

plzombie commented 2 months ago

По поводу количества потоков - проблема была в максимальном количестве waitable objects, равном MAXIMUM_WAIT_OBJECTS. Исправил.

zvezdochiot commented 2 months ago

Отслеживай показатели насыщенности(S) и светлости(L) своих изображений:

                        int v_min = buf[i*(size_t)channels];
                        int v_max = v_min;
                        size_t ch = (channels < 3) ? channels : 3;
                        for(j = 1; j < ch; j++) {
                                int origin = buf[i*(size_t)channels+j];
                                v_min = (v_min < origin) ? v_min : origin;
                                v_max = (v_max < origin) ? origin : v_max;
                        }
                        int HSL_S = v_max - v_min;
                        int HSL_L = (v_max + v_min) / 2;

HSL_L позволит тебе отсечь "белое" (допустим < 192 - "небелое"), и учитывать цветность HSL_S только "небелых" пикселей.

PS: Порог (128) также рекомендую производить по HSL_L.

Для анализа используй гистограммы:

                        uint64_t hist_L[256] = {0}, hist_S[256] = {0}, hist_SL[256] = {0};
                        int thres_L = 192;
                        hist_L[HSL_L]++;
                        hist_S[HSL_S]++;
                        hist_SL[HSL_S] += (HSL_L < thres_L) ? 1 : 0;

Для получения точечтой оценки используй "доминанту" гистограммы:

    for (unsigned int i = 1; i < 256; i++)
    {
        histogram[i] += histogram[i - 1];
    }

    unsigned int ilow  = 0;
    for (unsigned int i = (256 >> 1); i > 0; i >>= 1)
    {
        uint64_t sum_max = 0;
        unsigned int inew = ilow;
        for (unsigned int j = ilow; j < (ilow + i); j++)
        {
            uint64_t const sum_low = (j > 0) ? histogram[j] : 0;
            uint64_t const sum_high = histogram[j + i];
            uint64_t const sum = sum_high - sum_low;
            if (sum > sum_max)
            {
                inew = j;
                sum_max = sum;
            }
        }
        ilow = inew;
    }

    return ilow;
zvezdochiot commented 2 months ago

Помимо указанных манипуляций с HSL, можно также делать вспомогательное обесцвеченное изображение:

maxRGBi = max(Ri, Gi, Bi);
Ri = Gi = Bi = maxRGBi;

и применять различные метрики к двум изображениям. Ежели метрики простые (MSE, PSNR или корреляция), то можно обойтись без хранения вспомогательного изображения, вычисляя метрику "на лету".

По значению же метрики и производить классификацию серый/цветной. Желательно предусмотреть подавление фонового оттенка с помощью чего то, вроде фильтра GrayWorld.

plzombie commented 2 months ago

Мне для первой итерации достаточно будет, чтобы он ч/б сканы, сохранённые в jpeg, корректно обрабатывал. То есть (берём модель HSV), условно, V близко к границам, а по S построим гистограмму, и чтобы большинство значений было в районе 0 (вычисляем порог от размера исходного изображения). А дальше уже можно делать адаптивный порог и прочее. Пока просто нет времени и настроения это доделывать. А потом уже можно для постеризованных изображений сделать детектор