8

私は、CYMK 画像の各色を分離し、特別なハーフトーン プリンターで印刷されるハーフトーン画像を生成する必要があるプロジェクトに取り組んでいます。使用される方法は、プロセスがほとんど同じであるという点で、シルク スクリーニングに類似しています。写真を撮り、各カラー チャネルを分析します。次に、ハーフトーン用のスクリーンを作成します。各カラー スクリーンは、15 ~ 45 度 (調整可能) 傾斜したスクリーンを持っている必要があります。ドット サイズと LPI は、さまざまな効果を実現するために、ユーザーが構成可能な値から計算する必要があります。このプロセスはシルク スクリーニングで使用されていると言われていますが、CYMK ハーフトーンを説明する情報を見つけることができませんでした。単色に縮小し、新しい印刷スタイルの白黒ハーフトーン画像を生成する方法はたくさんあります。

私はする必要があると思います:

  1. ファイルをカラーチャンネルに分割します。
  2. そのチャネルのモノクロ ハーフトーン イメージを生成します。
  3. 結果のハーフトーン イメージを度数 * チャネル数だけ傾けます。

これが正しいアプローチであり、これに対する既存のpythonコードであるかどうかは誰にも分かりますか? または、このプロセスまたはアルゴリズムの適切な説明はありますか?

4

2 に答える 2

29

私は以前、スクリーン印刷スタジオ (かなり小さなスタジオでした) を経営していました。実際に色分解印刷を行ったことはありませんが、原則についてはかなり精通しています。これは私がそれにアプローチする方法です:

  1. イメージを C、M、Y、K に分割します。
  2. 分離された各イメージをそれぞれ 0、15、30、および 45 度回転します。
  3. 各画像のハーフトーンを取得します (ドット サイズは強度に比例します)。
  4. 各ハーフトーン イメージを元に戻します。

これで、色分けされた画像ができました。あなたが言及したように、回転ステップはドットの配置の問題(すべてを台無しにする)を減らし、モアレパターンの影響などは合理的に最小限に抑えられます.

これは、 PILを使用して非常に簡単にコーディングできるはずです。

更新 2:

これを行う簡単なコードをいくつか書きました。これにはGCR関数も含まれています (以下で説明します)。

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()

これにより、次のようになります。

ここに画像の説明を入力

これに(目をぼかし、モニターから離れてください):

ここに画像の説明を入力

画像のサンプリングはピクセルごとに行うことができることに注意してください (したがって、最終的な画像で元の画像の解像度が維持されます)。を設定してこれを行いますsample=1。この場合scale、多数の可能なドット サイズが存在するように、より大きな数値を設定する必要があります。これにより、出力画像のサイズも大きくなります (元の画像サイズ * スケール ** 2 なので注意してください!)。

デフォルトでは、からチャンネルRGB(黒いチャンネル) に変換すると空になります。チャネルが必要かどうかは、印刷プロセスによって異なります。必要な理由はさまざまです。 のオーバーラップよりも優れた黒を取得する、インクを節約する、乾燥時間を改善する、インクのにじみを減らすなどです。オーバーラップを置き換えたいチャンネルのパーセンテージ(これについては、コード コメントでもう少し詳しく説明します)。CMYKKKCMYGCRKCMY

例をいくつか示します。letter F画像から と を処理するsample=1scale=8、かなり高解像度になります。

の 4 つのCMYKチャネル、percentage=0空のKチャネル:

ここに画像の説明を入力ここに画像の説明を入力ここに画像の説明を入力ここに画像の説明を入力

組み合わせて生成します:

ここに画像の説明を入力

CMYKchannels, with percentage=100, したがってKchannel が使用されます. シアン チャネルが完全に抑制され、マゼンタとイエロー チャネルが使用するインクがかなり少ないことが、画像の下部にある黒い帯でわかります。

ここに画像の説明を入力ここに画像の説明を入力ここに画像の説明を入力ここに画像の説明を入力ここに画像の説明を入力

于 2012-05-13T23:11:26.953 に答える
4

私のソリューションも PIL を使用していますが、内部でサポートされている内部ディザリング手法 (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 適用は、より一般的なもので拡張することもできますが、解像度とサンプリングも無視される単純なソリューションを説明しようとしました。

于 2014-03-16T13:50:13.713 に答える