В предыдущей части мы невольно погрузились в само устройство такой высокоуровневой абстракции,
как изображение и познакомились с понятием битовых плоскостей или битовых планов. Также, мы научились выделять произвольный битовый план из некоторого базового канала изображения, что в последствии можно использовать в алгоритмах обработки изображений или компьютерного зрения как некоторый вид бинаризации или даже своего рода качественной оценки произвольного изображения. Но сегодня мы продвинемся немного дальше…
Познакомившись с понятием битового плана мы пришли к довольно интересному выводу: оказывается изображение состоит из нескольких каналов, каждый из которых состоит из битовых плоскостей, количество которых ограничено битовым представлением числовых характеристик цвета. Данное ограничение вытекает из количества битов на цвет канала, но мы сейчас, конечно, не будем вдаваться в подробности, а обратим внимание лишь на то, что битовая плоскость является своеобразным атомарным примитивом, над которым можно также производить некоторые операции и с одной из таких операций мы и будем сегодня работать.
Выделение некоторой битовой плоскости основано на побитовых операциях, которые позволяют извлечь интересующий нас бит и представить его как самостоятельный цвет (либо черный, либо белый).
Но, что если используемая нами операция выделения может быть применена и в обратную сторону: можно вместо извлечения значения бита, попытаться его изменить ?
Я задался этим вопросом и узнал, что есть одна известная операция над битовой плоскостью, которая довольно известна и проста. Дело в том, что я практически нигде не встретил упоминания об установке бита в произвольное значение (либо 0, либо 1), однако, я нашел операцию, которая “устанавливает” некоторый бит в значение 0.
Для битовых плоскостей это фактически обозначает уничтожение (стирание) некоторой битовой плоскости в изображении, но в литературе данное действие называется вырезанием битовой плоскости.
Именно вырезание битовой плоскости мы и реализуем в этой статье.
Для реализации задуманного будем использовать материал из предыдущей части и нам опять потребуется dlib вместе с функцией выделения нужного канала (взять можно из части I).
Принцип очищения битовой плоскости выгялдит следующим образом: считываем цвет пикселя, переводим его из числового формата dlib в более удобный диапазон чисел (от 0 до 255), далее с помощью битовой операции устанавливаем в 0 бит числового представления цвета (номер этого бита соответствует номеру битовой плоскости). Полученное число с очищенным битом мы делим на 255 и записываем в нужный канал, остальные же значения цветовых каналов оставляем точно такими же, какими они и были.
А выглядит это так:
auto clearBitPlane(SuperImage superImage, CHANNEL channel, int numberOfBit) { ubyte clearNthBit(float value, int numberOfBit) { ubyte mask = 0b00000001; ubyte nvalue = cast(ubyte) (value * 255); return (nvalue & ~(mask << numberOfBit)) >> numberOfBit; } SuperImage newImage = superImage.getChannel(channel); foreach (x; 0..newImage.width) { foreach (y; 0..newImage.height) { ubyte bp; Color4f color = newImage[x,y]; final switch (channel) with (CHANNEL) { case RED: bp = clearNthBit(newImage[x, y].r, numberOfBit); newImage[x,y] = Color4f(bp / 255.0f, color.b, color.g); break; case GREEN: bp = clearNthBit(newImage[x, y].g, numberOfBit); newImage[x,y] = Color4f(color.r, bp / 255.0f, color.g); break; case BLUE: bp = clearNthBit(newImage[x, y].b, numberOfBit); newImage[x,y] = Color4f(color.r, color.b, bp / 255.0f); break; } } } return newImage; }
Результат операции (вырезана битовая плоскость под номером 0, удаление которой не дает потери информации):
На этом мы заканчиваем вторую часть экспериментов, хоть и небольшую, но все равно занятную: описанная процедура может быть использована только на одном канале, но в перспективе ее можно усовершенствовать, применив ко всему изображению, а также можно попробовать осуществить сборку изображения из разных битовых плоскостей разных изображений, что даст причудливый вариант наложения изображений, однако эту задачу я оставляю для тебя, искушенный читатель…