@ledsun blog

無味の味は佳境に入らざればすなわち知れず

透過pngを作る

ChatGPTで画像が作れるようになりました。 楽しく画像をつくりました。

ChatGPTで作った画像

作った画像でトレーナーが作りたくなりました。 背景色の白が印刷されてしまいます。 絵だけを残して背景を透過したいです。

Windowsの3Dペイントには良い感じに塗りつぶしてくれる機能があります。 グリーンバックの容量で #00FF00 で塗りつぶします。

背景を #00FF00 で塗りぶした画像

#00FF00 の単色のはずなので、素朴に透過色で塗りつぶします。 これをRubyでやりました。

require 'chunky_png'

image = ChunkyPNG::Image.from_file('path/to/your/image.png')

# 透明にしたい色を指定(例えば白の場合)
target_color = ChunkyPNG::Color.from_hex('#FFFFFF')

# 透明色を定義(透明度が0の場合)
transparent_color = ChunkyPNG::Color.rgba(0, 0, 0, 0)

image.height.times do |y|
  image.width.times do |x|
    # ターゲットの色が見つかった場合は透明に置き換える
    if image[x, y] == target_color
      image[x, y] = transparent_color
    end
  end
end

# 修正した画像を保存
image.save('path/to/your/output_image.png')

ChatGPTの提示したスクリプトです。 ファイルパスを修正して使用しました。

#00FF00 を透過した画像

よく見ると縁に緑が残っています。 3Dペイントはアンチエイリアシングが効くみたいです。 今回の画風では不要です。が、OFFにできません。

完全一致では緑が残るので、ある程度遊びを持つようにRubyスクリプトを変更します。

require 'chunky_png'

transparent_color = ChunkyPNG::Color.rgba(0, 0, 0, 0)

# 比較対象の色
target_color = ChunkyPNG::Color.from_hex('#00ff00')

# 色の類似度を判定する閾値
threshold = 100

image = ChunkyPNG::Image.from_file '/mnt/c/Users/led_l/OneDrive/デスクトップ/背景の緑化.png'
image.height.times do |y|
  image.row(y).each_with_index do |pixel, x|
    # 現在のピクセルの色
    r, g, b = ChunkyPNG::Color.r(pixel), ChunkyPNG::Color.g(pixel), ChunkyPNG::Color.b(pixel)

    # 目標の色との差分を計算
    r_diff = (r - ChunkyPNG::Color.r(target_color)).abs
    g_diff = (g - ChunkyPNG::Color.g(target_color)).abs
    b_diff = (b - ChunkyPNG::Color.b(target_color)).abs

    # 差分が閾値内ならば似ている色として配列に追加
    if r_diff <= threshold && g_diff <= 70 && b_diff <= threshold
      image[x, y] = transparent_color
    end
  end
end

image.save '/mnt/c/Users/led_l/OneDrive/デスクトップ/背景のtrasparent化2.png'

緑っぽい色を透過した画像

結構綺麗になりました。 ただ、拡大すると緑色が残っています。

少し戻って、塗りつぶしの手順を改善するのが良さそうです。