Python・Pygameで画像処理まとめ
文章:syun
日付:2005/8/11

目次
1.はじめに
2.グレースケール変換
3.セピア変換
4.2値変換
5.RGB抽出
6.RGB成分入れ替え
7.ネガ変換
8.輪郭抽出
9.グレースケールの改良版
10.モザイク化
11.ぼかし
12.モーションブラー
13.鮮鋭化






1.はじめに
今回はPython・Pygameを使った画像処理のソースコードをのせます。
(解説はなしです…)




2.グレースケール変換
超基本のグレースケールから、、。
import pygame

_gSrc = None

pygame.init()
pygame.display.set_mode((150, 150), 0, 32)
pygame.display.set_caption("グレースケール")
_gScr = pygame.display.get_surface()
tBuf = pygame.image.load("kenmo.jpg").convert()

# グレースケール変換
w, h = tBuf.get_size()
for j in range(h):
	for i in range(w):
		colorA = tBuf.get_at((i, j))
		gray = (colorA[0] + colorA[1] + colorA[2]) / 3
		tBuf.set_at((i, j), (gray, gray, gray, 255))

while True:
	_gScr.blit(tBuf, (0, 0), tBuf.get_rect())
	pygame.display.update()
	pygame.time.wait(10)





3.セピア変換
次にセピア変換を。
import pygame

_gSrc = None

pygame.init()
pygame.display.set_mode((150, 150), 0, 32)
pygame.display.set_caption("セピア変換")
_gScr = pygame.display.get_surface()
tBuf = pygame.image.load("kenmo.jpg").convert()

# セピア変換
w, h = tBuf.get_size()
for j in range(h):
	for i in range(w):
		colorA = tBuf.get_at((i, j))
		gray = (colorA[0] + colorA[1] + colorA[2]) / 3
		tBuf.set_at((i, j), (gray * 1, gray * 0.8, gray * 0.6, 255))

while True:
	_gScr.blit(tBuf, (0, 0), tBuf.get_rect())
	pygame.display.update()
	pygame.time.wait(10)




4.2値変換
続いて、2値変換を。
import pygame

_gSrc = None

pygame.init()
pygame.display.set_mode((150, 150), 0, 32)
pygame.display.set_caption("2値変換")
_gScr = pygame.display.get_surface()
tBuf = pygame.image.load("kenmo.jpg").convert()

threshold = 127 # 閾値
# 2値変換
w, h = tBuf.get_size()
for j in range(h):
	for i in range(w):
		colorA = tBuf.get_at((i, j))
		gray = (colorA[0] + colorA[1] + colorA[2]) / 3
		if(threshold > gray):
			colorA = (255, 255, 255, 255)
		else:
			colorA = (0, 0, 0, 255)
		tBuf.set_at((i, j), colorA)

while True:
	_gScr.blit(tBuf, (0, 0), tBuf.get_rect())
	pygame.display.update()
	pygame.time.wait(10)




5.RGB抽出
RGB抽出を。
import pygame

_gSrc = None

pygame.init()
pygame.display.set_mode((150, 150), 0, 32)
pygame.display.set_caption("RGB抽出")
_gScr = pygame.display.get_surface()
tBuf = pygame.image.load("kenmo.jpg").convert()

# RGB抽出
w, h = tBuf.get_size()
for j in range(h):
	for i in range(w):
		colorA = tBuf.get_at((i, j))
		# R成分抽出
		tBuf.set_at((i, j), (colorA[0], 0, 0, 255))

while True:
	_gScr.blit(tBuf, (0, 0), tBuf.get_rect())
	pygame.display.update()
	pygame.time.wait(10)




6.RGB成分入れ替え
RGB成分入れ替えです。
import pygame

_gSrc = None

pygame.init()
pygame.display.set_mode((150, 150), 0, 32)
pygame.display.set_caption("RGB成分入れ替え")
_gScr = pygame.display.get_surface()
tBuf = pygame.image.load("kenmo.jpg").convert()

# RGB成分入れ替え
w, h = tBuf.get_size()
for j in range(h):
	for i in range(w):
		colorA = tBuf.get_at((i, j))
		# RGBをGRBに
		tBuf.set_at((i, j), (colorA[1], colorA[0], colorA[2], 255))

while True:
	_gScr.blit(tBuf, (0, 0), tBuf.get_rect())
	pygame.display.update()
	pygame.time.wait(10)




7.ネガ変換
ネガ変換です。
import pygame

_gSrc = None

pygame.init()
pygame.display.set_mode((150, 150), 0, 32)
pygame.display.set_caption("ネガ変換")
_gScr = pygame.display.get_surface()
tBuf = pygame.image.load("kenmo.jpg").convert()

# ネガ変換
w, h = tBuf.get_size()
for j in range(h):
	for i in range(w):
		colorA = tBuf.get_at((i, j))
		r = 255 - colorA[0]
		g = 255 - colorA[1]
		b = 255 - colorA[2]
		# 色の反転
		tBuf.set_at((i, j), (r, g, b, 255))

while True:
	_gScr.blit(tBuf, (0, 0), tBuf.get_rect())
	pygame.display.update()
	pygame.time.wait(10)




8.輪郭抽出
輪郭抽出です。 大きめの画像でやると、そこそこキレイに抽出できますね。
import pygame
import math

_gSrc = None

pygame.init()
pygame.display.set_mode((150, 150), 0, 32)
pygame.display.set_caption("輪郭抽出")
_gScr = pygame.display.get_surface()
tBuf = pygame.image.load("kenmo.jpg").convert()

tblGray = []
# グレースケールテーブル作成
for j in range(tBuf.get_height()):
	w = []
	for i in range(tBuf.get_width()):
		colorA = tBuf.get_at((i, j))
		gray = (colorA[0] + colorA[1] + colorA[2]) / 3
		w.append(gray)
	tblGray.append(w)
# 輪郭抽出(グラディエント法)
for j in range(tBuf.get_height() - 1):
	for i in range(tBuf.get_width() - 1):
		# 微分、というか差分
		dx = tblGray[j][i+1] - tblGray[j][i]
		dy = tblGray[j+1][i] - tblGray[j][i]
		#tblGray[j][i] = math.sqrt(dx ** 2 + dy ** 2)
		tblGray[j][i] = abs(dx) + abs(dy) # 高速化

# 2値化
AMP = 5 # 出力レベル
BLACK = (0, 0, 0, 255)
WHITE = (255, 255, 255, 255)
for j in range(tBuf.get_height() - 1):
	for i in range(tBuf.get_width() - 1):
		if(tblGray[j][i] > AMP):
			tBuf.set_at((i, j), WHITE)
		else:
			tBuf.set_at((i, j), BLACK)

while True:
	_gScr.blit(tBuf, (0, 0), tBuf.get_rect())
	pygame.display.update()
	pygame.time.wait(10)
ノイズが多い場合は出力レベルを上げるとキレイになりますよー。



9.グレースケールの改良版
グレースケールの改良版です。 人の目は緑に最も良く反応し、続いて赤、青という反応をします。 よって、このように重みをかけると、自然なグレースケールになるわけです。
import pygame
import math

_gSrc = None

def main():
	pygame.init()
	pygame.display.set_mode((250, 250), 0, 32)
	pygame.display.set_caption("グレースケール2")
	_gScr = pygame.display.get_surface()
	tBuf = pygame.image.load("nyan.bmp").convert()

	for j in range(tBuf.get_height()):
		for i in range(tBuf.get_width()):
			rgba = tBuf.get_at((i, j))
			gray = (
				rgba[0] * 0.299   # r
				+ rgba[1] * 0.587 # g
				+ rgba[2] * 0.114 # b
				) / 3
			tBuf.set_at((i, j), (gray, gray, gray, 255))
	while True:
		_gScr.blit(tBuf, (0, 0), tBuf.get_rect())
		pygame.display.update()
		for e in pygame.event.get():
			if e.type == pygame.QUIT: return
		pygame.time.wait(10)

if __name__ == '__main__':
	main()




10.モザイク化
モザイク化です。 画面遷移時に使えますね。(ただ、重いから使えないかな…)
import pygame
import math

# Mosaic
# @param tBuf サーフェス
# @param RECT モザイクをかける範囲
# @param SIZE モザイクの大きさ
def transMosaic(tBuf, RECT, SIZE):
	if(SIZE < 1): return None
	retBuf = pygame.transform.scale(tBuf, tBuf.get_size())
	for j in range(RECT.top, RECT.bottom, SIZE):
		for i in range(RECT.left, RECT.right, SIZE):
			colorSum = 0, 0, 0
			for b in range(SIZE):
				for a in range(SIZE):
					rgba = tBuf.get_at((i+a, j+b))
					colorSum = (
						colorSum[0] + rgba[0],
						colorSum[1] + rgba[1],
						colorSum[2] + rgba[2])
			colorSum = (
				colorSum[0] / ((SIZE)**2),
				colorSum[1] / ((SIZE)**2),
				colorSum[2] / ((SIZE)**2),
				255)
			for b in range(SIZE):
				for a in range(SIZE):
					retBuf.set_at((i+a, j+b), colorSum)
	return retBuf
# Main
def main():
	pygame.init()
	pygame.display.set_mode((250, 250), 0, 32)
	pygame.display.set_caption("モザイク")
	_gScr = pygame.display.get_surface()
	tBuf = pygame.image.load("nyan.bmp").convert()

	i = 1
	while True:
		dstBuf = transMosaic(tBuf, pygame.Rect(50, 50, 100, 100), i)
		i += 1
		if(i > 50): i = 1
		_gScr.blit(dstBuf, (0, 0), dstBuf.get_rect())
		pygame.display.update()
		for e in pygame.event.get():
			if e.type == pygame.QUIT: return
		pygame.time.wait(10)

if __name__ == '__main__':
	main()




11.ぼかし
ぼかしです。
import pygame
import math

# ぼかし
# @param tBuf サーフェス
# @return 変換後のサーフェス
def transBlur(tBuf):
	retBuf = pygame.transform.scale(tBuf, tBuf.get_size())
	
	for j in range(1, retBuf.get_height()-1):
		for i in range(1, retBuf.get_width()-1):
			color1 = tBuf.get_at((i,   j-1))
			color2 = tBuf.get_at((i-1, j))
			color3 = tBuf.get_at((i,   j+1))
			color4 = tBuf.get_at((i+1, j))
			color5 = tBuf.get_at((i,   j))
			color = (
				(color1[0]+color2[0]+color3[0]+color4[0]+color5[0])/5,
				(color1[1]+color2[1]+color3[1]+color4[1]+color5[1])/5,
				(color1[2]+color2[2]+color3[2]+color4[2]+color5[2])/5,
				255)
			retBuf.set_at((i, j), color)
	return retBuf
# Main
def main():
	pygame.init()
	pygame.display.set_mode((250, 250), 0, 32)
	pygame.display.set_caption("ぼかし")
	_gScr = pygame.display.get_surface()
	tBuf = pygame.image.load("nyan.bmp").convert()

	i = 32
	while True:
		tBuf = transBlur(tBuf)
		_gScr.blit(tBuf, (0, 0), tBuf.get_rect())
		pygame.display.update()
		for e in pygame.event.get():
			if e.type == pygame.QUIT: return
		pygame.time.wait(10)

if __name__ == '__main__':
	main()




12.モーションブラー
左上方向のモーションブラーです。
import pygame
import math

# モーションブラー(左上)
# @param tBuf サーフェス
# @return 変換後のサーフェス
def transBlur(tBuf):
	retBuf = pygame.transform.scale(tBuf, tBuf.get_size())
	
	for j in range(retBuf.get_height()-5):
		for i in range(retBuf.get_width()-5):
			color1 = tBuf.get_at((i,   j))
			color2 = tBuf.get_at((i+1, j+1))
			color3 = tBuf.get_at((i+2, j+2))
			color4 = tBuf.get_at((i+3, j+3))
			color5 = tBuf.get_at((i+4, j+4))
			color = (
				(color1[0]+color2[0]+color3[0]+color4[0]+color5[0])/5,
				(color1[1]+color2[1]+color3[1]+color4[1]+color5[1])/5,
				(color1[2]+color2[2]+color3[2]+color4[2]+color5[2])/5,
				255)
			retBuf.set_at((i, j), color)
	return retBuf
# Main
def main():
	pygame.init()
	pygame.display.set_mode((250, 250), 0, 32)
	pygame.display.set_caption("ぼかし")
	_gScr = pygame.display.get_surface()
	tBuf = pygame.image.load("nyan.bmp").convert()

	i = 32
	while True:
		tBuf = transBlur(tBuf)
		_gScr.blit(tBuf, (0, 0), tBuf.get_rect())
		pygame.display.update()
		for e in pygame.event.get():
			if e.type == pygame.QUIT: return
		pygame.time.wait(10)

if __name__ == '__main__':
	main()




13.鮮鋭化
鮮鋭化です。
import pygame
import math

def saturate(param):
	if(param < 0): ret = 0
	elif(param > 255): ret = 255
	else: ret = param
	return ret
# 鮮鋭化
# @param tBuf サーフェス
# @return 変換後のサーフェス
def transSharp(tBuf):
	retBuf = pygame.transform.scale(tBuf, tBuf.get_size())
	
	for j in range(1, retBuf.get_height()-1):
		for i in range(1, retBuf.get_width()-1):
			color1 = tBuf.get_at((i,   j))
			color2 = tBuf.get_at((i-1, j))
			color3 = tBuf.get_at((i+1, j))
			color4 = tBuf.get_at((i,   j-1))
			color5 = tBuf.get_at((i,   j+1))
			color = (
				saturate(color1[0]-((color2[0]+color3[0]+color4[0]+color5[0])-(color1[0]*4))),
				saturate(color1[1]-((color2[1]+color3[1]+color4[1]+color5[1])-(color1[1]*4))),
				saturate(color1[2]-((color2[2]+color3[2]+color4[2]+color5[2])-(color1[2]*4))),
				255)
			retBuf.set_at((i, j), color)
	return retBuf
# Main
def main():
	pygame.init()
	pygame.display.set_mode((250, 250), 0, 32)
	pygame.display.set_caption("鮮鋭化")
	_gScr = pygame.display.get_surface()
	tBuf = pygame.image.load("nyan.bmp").convert()

	tBuf = transSharp(tBuf)
	while True:
		_gScr.blit(tBuf, (0, 0), tBuf.get_rect())
		pygame.display.update()
		for e in pygame.event.get():
			if e.type == pygame.QUIT: return
		pygame.time.wait(10)

if __name__ == '__main__':
	main()