Вопрос по image, python – Полутоновые изображения в Python

7

Я работаю над проектом, который требует от меня отделить каждый цвет в изображении CYMK и создать полутоновое изображение, которое будет напечатано на специальном полутоновом принтере. Используемый метод является аналогом шелкографии в том, что процесс практически идентичен. Сфотографируйте и вырежьте каждый цветной канал. Затем создайте экран для полутона. Каждый цветной экран должен иметь угол наклона экрана на 15-45 (регулируемый) градусов. Размер точки и LPI должны быть рассчитаны из настраиваемых пользователем значений для достижения различных эффектов. Мне сказали, что этот процесс используется в шелкографии, но мне не удалось найти какую-либо информацию, объясняющую полутонирование CYMK. Я нашел много для того, чтобы свести к одному цвету и создать новый стиль печати черно-белого полутонового изображения.

Я бы предположил, что мне нужно: 1. разделить файл на его цветные каналы. 2. создать монохромное полутоновое изображение для этого канала. 3. Наклоните результирующее полутоновое изображение на количество градусов * номер канала. Кто-нибудь знает, если это правильный подход?

Кто-нибудь знает какой-либо существующий код Python для этого? Или каких-либо хороших объяснений этого процесса или алгоритмов?

Теперь связаны:How to halftone a black and white picture? martineau
обновил мой код, надеюсь, это полезно;) fraxel

Ваш Ответ

2   ответа
4

но использует внутренний метод дизеринга (Floyd-Steinberg), поддерживаемый внутри. Однако создает артефакты, поэтому я подумываю переписать его C-код.

    from PIL import Image

    im  = Image.open('tree.jpg')             # open RGB image
    cmyk= im.convert('CMYK').split()         # RGB contone RGB to CMYK contone
    c = cmyk[0].convert('1').convert('L')    # and then halftone ('1') each plane
    m = cmyk[1].convert('1').convert('L')    # ...and back to ('L') mode
    y = cmyk[2].convert('1').convert('L')
    k = cmyk[3].convert('1').convert('L')

    new_cmyk = Image.merge('CMYK',[c,m,y,k]) # put together all 4 planes
    new_cmyk.save('tree-cmyk.jpg')           # and save to file

Неявное применение GCR PIL также может быть расширено более общим, но я попытался описать простое решение, в котором также игнорируются разрешение и выборка.

24

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

Split the image into C, M, Y, K. Rotate each separated image by 0, 15, 30, and 45 degrees respectively. Take the half-tone of each image (dot size will be proportional to the intensity). Rotate back each half-toned image.

Теперь у вас есть разделенные изображения цвета. Как вы упомянули, шаг поворота уменьшает проблемы с выравниванием точек (которые могут все испортить), и такие вещи, какМойр & # xE9; шаблонные эффекты будет разумно сведено к минимуму.

Это должно быть довольно легко с помощью кодаPIL.

Update 2:

Я написал небольшой код, который сделает это за вас, он также включает в себяGCA функция (описано ниже):

import Image, ImageDraw, ImageStat

def gcr(im, percentage):
    '''basic "Gray Component Replacement" function. Returns a CMYK image with 
       percentage gray component removed from the CMY channels and put in the
       K channel, ie. for percentage=100, (41, 100, 255, 0) >> (0, 59, 214, 41)'''
    cmyk_im = im.convert('CMYK')
    if not percentage:
        return cmyk_im
    cmyk_im = cmyk_im.split()
    cmyk = []
    for i in xrange(4):
        cmyk.append(cmyk_im[i].load())
    for x in xrange(im.size[0]):
        for y in xrange(im.size[1]):
            gray = min(cmyk[0][x,y], cmyk[1][x,y], cmyk[2][x,y]) * percentage / 100
            for i in xrange(3):
                cmyk[i][x,y] = cmyk[i][x,y] - gray
            cmyk[3][x,y] = gray
    return Image.merge('CMYK', cmyk_im)

def halftone(im, cmyk, sample, scale):
    '''Returns list of half-tone images for cmyk image. sample (pixels), 
       determines the sample box size from the original image. The maximum 
       output dot diameter is given by sample * scale (which is also the number 
       of possible dot sizes). So sample=1 will presevere the original image 
       resolution, but scale must be >1 to allow variation in dot size.'''
    cmyk = cmyk.split()
    dots = []
    angle = 0
    for channel in cmyk:
        channel = channel.rotate(angle, expand=1)
        size = channel.size[0]*scale, channel.size[1]*scale
        half_tone = Image.new('L', size)
        draw = ImageDraw.Draw(half_tone)
        for x in xrange(0, channel.size[0], sample):
            for y in xrange(0, channel.size[1], sample):
                box = channel.crop((x, y, x + sample, y + sample))
                stat = ImageStat.Stat(box)
                diameter = (stat.mean[0] / 255)**0.5
                edge = 0.5*(1-diameter)
                x_pos, y_pos = (x+edge)*scale, (y+edge)*scale
                box_edge = sample*diameter*scale
                draw.ellipse((x_pos, y_pos, x_pos + box_edge, y_pos + box_edge), fill=255)
        half_tone = half_tone.rotate(-angle, expand=1)
        width_half, height_half = half_tone.size
        xx=(width_half-im.size[0]*scale) / 2
        yy=(height_half-im.size[1]*scale) / 2
        half_tone = half_tone.crop((xx, yy, xx + im.size[0]*scale, yy + im.size[1]*scale))
        dots.append(half_tone)
        angle += 15
    return dots

im = Image.open("1_tree.jpg")

cmyk = gcr(im, 0)
dots = halftone(im, cmyk, 10, 1)
im.show()
new = Image.merge('CMYK', dots)
new.show()

Это превратит это:

enter image description here

в это (размыть глаза и отойти от монитора):

enter image description here

Обратите внимание, что выборка изображения может быть попиксельной (таким образом, сохраняя разрешение исходного изображения, в конечном изображении). Сделайте это, установивsample=1, в этом случае вам нужно установитьscale к большему числу, так что есть ряд возможных размеров точек. Это также приведет к увеличению размера выходного изображения (размер исходного изображения * масштаб ** 2, так что следите!).

По умолчанию при конвертации изRGB вCMYK K канал (черный канал) пуст. Нужно ли вамK канал или нет, зависит от вашего процесса печати. Существуют различные возможные причины, по которым вы можете этого захотеть: получить черный цвет лучше, чем наложениеCMYэкономия чернил, сокращение времени сушки, уменьшение вытекания чернил и т. д. Во всяком случае, я также написал немногоЗамена серого компонента функцияGCA, так что вы можете установить процентK канал, который вы хотите заменитьCMY перекрываются с (я объясняю это немного дальше в комментариях к коду).

Вот пара примеров для иллюстрации. Обработкаletter F с картинки, сsample=1 а такжеscale=8, так что довольно высокое разрешение.

4CMYK каналы, сpercentage=0так пустоK канал:

enter image description hereenter image description hereenter image description hereenter image description here

объединяет в производство:

enter image description here

CMYK каналы, сpercentage=100, такK канал используется. Вы можете видеть, что голубой канал полностью подавлен, а пурпурный и желтый каналы используют намного меньше чернил в черной полосе внизу изображения:

enter image description hereenter image description hereenter image description hereenter image description hereenter image description here

+1 Отлично.
аккуратное решение!
@ user69333 - Круто, удачи в этом! Кстати, я Фраксель (отличается от Андрея, который тоже ответил ..). Я был бы признателен, если бы вы могли «принять мой ответ», щелкнув по галочке, это работает так, как работает stackoverflow (мы оба получаем очки ... упс), ура.
Еще раз спасибо, Андрей. Ваш компонент серой шкалы может пригодиться. Большая часть того, что я узнал здесь, пришла с сайтов, посвященных футболкам. Теперь это заставило меня задуматься об использовании OSS для печати на футболках. Однако я заметил, что коммерческое программное обеспечение, похоже, использует RGB, а также каналы CMYK и другие экраны. Я читал статью об использовании Photoshop для футболок с трафаретной печатью, и мне кажется, что это очень важно. Что касается моего проекта печати, ты дал мне хорошее начало. Я собираюсь добавить ваш код в оттенках серого и сделать еще несколько модов. user693336
Я поиграл с некоторыми углами, которые я нашел в сети в диапазоне от 10 до 60 градусов на канал, и обнаружил, что некоторые комбинации приводят к очень плохим эффектам муарового паттерна, в то время как другие уменьшают эти эффекты. Мой код позволяет мне устанавливать определенные углы для каждого канала, чтобы я мог использовать углы, которые не являются инкрементными. Это, кажется, помогает уменьшить эффекты, но также может изменить воспринимаемый цвет. Это круто возиться с ;-) user693336

Похожие вопросы