写真をグレースケールにしよう
今回は写真をグレースケールにしてみましょう。
グレースケールにするにはRGBの各要素をすべて同じ値にします。
どのように値を決定するかは、色々な考え方がありますが代表的なものをあげています。
ピクセル内のRGBの平均
一番単純な方法として、ピクセルを構成する各RGBの値の平均を設定します。
例えば、RGBが(230,50,200)の場合は、(160,160,160)となります。
前回のプログラムを元に、ピクセルにグレーを設定しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
### インポート import pygame from pygame.locals import * ### 定数 WIDTH = 640 # 幅 HEIGHT = 400 # 高さ ### モジュール初期化 pygame.init() ### 画面設定 surface = pygame.display.set_mode((WIDTH,HEIGHT)) ### 写真読み込み img = pygame.transform.rotozoom(pygame.image.load("photo.jpg").convert(), 0, 0.2) ### 写真のピクセルを直接編集 pixel = pygame.PixelArray(img) ### Y座標、X座標の色を取得 for y in range(img.get_height()): for x in range(img.get_width()): ### カラー定数をRGBA形式に変換 rgba = surface.unmap_rgb(pixel[x][y]) ### グレースケールに変換 gray = int((rgba[0] + rgba[1] + rgba[2]) / 3) ### 色を書き換え pixel[x][y] = (gray,gray,gray) ### オブジェクト削除 del pixel ### 写真表示 surface.blit(img, (int((WIDTH-img.get_width())/2),int((HEIGHT-img.get_height())/2))) ### 画面更新 pygame.display.update() ### 無限ループ while True: ### イベント処理 for event in pygame.event.get(): if event.type == KEYDOWN and event.key == K_ESCAPE: break else: continue ### whileループ終了 break ### 終了処理 pygame.quit() |
プログラムを実行すると、以下の画像が表示されます。
自然なグレースケール
人間の目は、赤や青より緑の方が濃淡を区別しやすいという性質があるため、緑を強めるとより自然なグレースケールが表示できます。
カラーテレビなどの映像システムでは、以下のように色に重みをつけます。
赤 ✕ 0.298912 + 緑 ✕ 0.586611 + 青 ✕ 0.114478
プログラムでは色の重みはあまり細かくしても仕方がないので、小数点第3位までにしています。
上記のプログラムの29行目を、以下のように書き換えます。
1 |
gray = int(rgba[0] * 0.299 + rgba[1] * 0.587 + rgba[2] * 0.114) |
プログラムを実行すると、以下の画像が表示されます。
セピア調のグレースケール
一般的にセピア色の値は(107,74,43)くらいです。
セピア色にするために、赤(107)を基準に緑と青をその割合でグレースケールに掛けます。
掛ける値は、赤は1.0、緑は0.7、青は0.4にします。
上記のプログラムの32行目を、以下のように書き換えます。
1 |
pixel[x][y] = (gray,int(gray * 0.7),int(gray * 0.4)) |
プログラムを実行すると、以下の画像が表示されます。