Задание №1. Анализатор изображений

Нужно написать программу, которая должна открывать изображение и показывать его каналы (в выбранной цветовой модели). Также в изображение некоторым способом (например, фильтрацией) могут вноситься изменения, поэтому одновременно с исходной картинкой нужно видеть ее измененный вариант. Для исходного и измененного изображений нужно вывести ряд числовых параметров.

Все изображения должны выводиться без искажений — пиксель изображения соответствует пикселю на экране. Желательно показывать скролбары, если изображение целиком не помещается на экран.

Ключевые возможности:

Фильтры реализуются самостоятельно любым удобным способом. При каждом запуске фильтр применяется относительно исходного изображения.

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

Не нужно выводить каналы R,G,B в оттенках красного, зеленого или синего – только в оттенках серого.

Энтропия

Пусть вектор \(c\) — канал изображения, \(n_i\) — сколько раз значение \(i\) встречается в векторе \(c\) и \(p_i = n_i/\vert c \vert\) — вероятность. Энтропия \(c\) вычисляется по следующей формуле:

\[H(c) = -\sum {p_i}\log_2{p_i}\]

Энтропия всего изображения — сумма энтропий каждого канала.

Метрики

Чтобы определить, насколько измененное изображение отличается от исходного, используются различные метрики. Пусть \(с_1\) и \(с_2\) – каналы изображения в виде векторов длины \(n = width \cdot height\):

Значения метрик нужно вычислять только для каналов. Если выбрано все изображение, то нужно показывать значения метрик всех каналов.

Преобразование RGB в YUV и обратно

Без потерь

RGB → YUV YUV → RGB
\(u = r - g\) \(g = y - \displaystyle\frac{u + v}{4}\)
\(v = b - g\) \(r = u + g\)
\(y = \displaystyle\frac{u + v}{4} + g\) \(b = v + g\)

С потерями

RGB → YUV YUV → RGB
y’ = 0.299*r + 0.587*g + 0.114*b  
y = (int)y’ b = clip(y + 1.770*u)
u = (int)(0.565*(b - y’)) g = clip(y - 0.344*u - 0.714*v)
v = (int)(0.713*(r - y’)) r = clip(y + 1.403*v)
public static int clip(double value) {
    final int v = (int) Math.round(value);

    if (v < 0) {
        return 0;
    }

    if (v > 255) {
        return 255;
    }

    return v;
}

Интерфейс

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

Main Window

Возможные пункты меню.

Menus