Python: Как реализовать двоичный фильтр на RGB-изображении?(алгоритм) - PullRequest
0 голосов
/ 17 декабря 2018

Я пытаюсь реализовать фильтр двоичных изображений (чтобы получить монохромное двоичное изображение), используя python & PyQT5, и для получения новых цветов пикселей я использую следующий метод:

def _new_pixel_colors(self, x, y):
    color = QColor(self.pixmap.pixel(x, y))

    result = qRgb(0, 0, 0) if all(c < 127 for c in color.getRgb()[:3]) else qRgb(255, 255, 255)

    return result

Может ли это бытьправильный образец двоичного фильтра для изображения RGB ?Я имею в виду, это достаточное условие, чтобы проверить, является ли пиксель ярче или темнее, чем (127,127,127) Серый цвет?И пожалуйста, не предоставляйте никаких решений с opencv, подушками и т. Д. .Я спрашиваю только о самом алгоритме.

Ответы [ 2 ]

0 голосов
/ 17 декабря 2018

Я бы, по крайней мере, сравнил с интенсивностью i=R+G+B ...

Для ROI подобных масок вы можете использовать любые методы пороговых значений (адаптивный порог является лучшим) но если ваше результирующее изображение не является маской ROI и должно напоминать визуальные особенности исходного изображения, то лучшее из известных мне преобразований - использовать дизеринг .

Идея, лежащая в основе сглаживания черно-белого изображения, заключается в преобразовании серых шкал в черно-белые изображения, сохраняющие затенение.Результат часто шумный, но сохраняет гораздо больше визуальных деталей.Здесь простой наивный C ++ дизеринг (извините, не кодер Python):

picture pic0,pic1;
    // pic0 - source img
    // pic1 - output img
int x,y,i;
color c;
// resize output to source image size clear with black
pic1=pic0; pic1.clear(0);
// dithering
i=0;
for (y=0;y<pic0.ys;y++)
 for (x=0;x<pic0.xs;x++)
    {
    // get source pixel color (AARRGGBB)
    c=pic0.p[y][x];
    // add to leftovers
    i+=WORD(c.db[picture::_r]); // _r,_g,_b are just constants 0,1,2
    i+=WORD(c.db[picture::_g]);
    i+=WORD(c.db[picture::_b]);
    // threshold white intensity is 255+255+255=765
    if (i>=384){ i-=765; c.dd=0x00FFFFFF; } else c.dd=0;
    // copy to destination image
    pic1.p[y][x]=c;
    }

То же самое, что и в приведенной выше ссылке, но с использованием только черного и белого.i - это накопленная интенсивность, которая будет размещена на изображении.xs,ys - это разрешение, а c.db[] - это доступ к цветному каналу.

Если применить это к цветному изображению следующим образом:

input

Результат выглядит следующим образом:

output

Как вы можете видеть все детали, где сохранились, но появляются шумные узоры ... Для печати былоиногда разрешение изображения умножается для повышения качества.Если вы поменяете наивные 2, вложенные в петли, с лучшим рисунком (например, квадраты 16x16 и т. Д.), То шум будет сохраняться вблизи артефактов ограничения источника.Существуют также подходы, использующие псевдослучайные паттерны (поместите остаток i рядом с исходным пикселем в случайном месте), который даже лучше ...

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

PS только для сравнениядругие выходы порогового значения ответа - это то же самое изображение, сглаженное:

input output

0 голосов
/ 17 декабря 2018

пороговое значение изображения - это класс алгоритмов, который вы ищете - двоичный порог устанавливает пиксели на 0 или 1, да.

В зависимости от желаемого результата, рассмотрите возможность преобразованияИзображение сначала в другие цветовые пространства, в частности HSL, с каналом яркости.Использование (127, 127, 127) в качестве порога не всегда учитывает яркость, потому что каждый канал RGB является насыщенностью R, G или B;рассмотрите это изображение:

Original Image

127, 127, 127 RGB Threshold

50% Luminance HSL Threshold

from PIL import Image
import colorsys


def threshold_pixel(r, g, b):
    h, l, s = colorsys.rgb_to_hls(r / 255., g / 255., b / 255.)
    return 1 if l > .36 else 0
    # return 1 if r > 127 and g > 127 and b > 127 else 0


def hlsify(img):
    pixels = img.load()
    width, height = img.size

    # Create a new blank monochrome image.
    output_img = Image.new('1', (width, height), 0)
    output_pixels = output_img.load()

    for i in range(width):
        for j in range(height):
            output_pixels[i, j] = threshold_pixel(*pixels[i, j])

    return output_img


binarified_img = hlsify(Image.open('./sample_img.jpg'))
binarified_img.show()
binarified_img.save('./out.jpg')

На других сайтах StackExchange существует множество дискуссий на эту тему, например,

Бинаризация данных изображения

Как выполнить бинаризациюцветное изображение?

как получить хорошее двоичное изображение, используя метод Оцу для этого изображения?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...