OpenCVで用意した画像のPyGameによる表示
画像の回転をOpenCVを利用して行い、回転した画像をPyGameで連続的に提示すると、画像が回転しているように見える。例えば、図1の画像を横方向に回転することを考える。
図1
リスト1のスクリプトを実行すると、図2に示すように横方向に回転しているように見える動画が表示される。ファイルは、圧縮ファイルusingopencvfiles.zipにまとめた。
−
図2
リスト1のスクリプトで用いているOpenCVのライブラリは、コマンド
pip install opencv-python
でインストールできる。インストールしたライブラリは、次のコードでimportできる。
import cv2
リスト1のスクリプトを実行すると、次のスクリプトで画像ファイルsample.pngが読み込まれて表示される。
img1 = cv2.imread('sample.png')
img2 = cv2.cvtColor(img1,
cv2.COLOR_BGR2RGB) # RGBに変換
plt.imshow(img2)
plt.show()
表示する前に、画像の色をRGBに並べ替えていることに注意。
表示画像(図1)のWindowを閉じると(右上角のX印をクリック)、画像の回転(横方向)に合わせた横方向収縮画像の作成とPyGameのsurfaceのリストへの格納が、次のスクリプトで行われる。
surfaces = []
for i in range(38):
ck_time =
time.perf_counter()
t_angl = i * 2 *
np.pi/38
# 回転角
s_ps = np.array([[img_w//2,
0], [img_w//2, img_h], [0, 0]], dtype=np.float32)
d_ps = np.array([[img_w//2,
0], [img_w//2, img_h],
[int((img_w//2)*(1 - np.cos(t_angl))), 0]],
dtype=np.float32)
t_mat =
cv2.getAffineTransform(s_ps, d_ps)
# 変換行列
t_img = cv2.warpAffine(img1,
t_mat, (img_w, img_h)) # 画像の変換
cv2.imwrite('temp.png',
t_img)
# 変換画像をファイルに保存
surfaces.append(pg.image.load('temp.png')) # 保存画像ファイルをPyGame用画像として
# スクリーンのリストに格納
画像の縦方向の中心、[img_w//2, 0]を[img_w//2, img_h]結ぶ線、を固定して、左上の点[0, 0]を回転角t_anglの回転に対応する点[int((img_w//2)*(1 - np.cos(t_angl))), 0]に変換する行列t_matを求めて、変換画像t_imgを算出している。
回転画像のsurfaceのリストの作成後、次のスクリプトで1枚ずつ順番に提示している。
ck = True
# while文のコントロール用
img_id = 0
# 表示画像のid
size_L = len(surfaces)
ck_time = time.perf_counter() # 画面の更新間隔のコントロール用
while ck:
screen.blit(surfaces[img_id], (100, 100))
img_id += 1
if img_id >= size_L:
img_id = 0
提示の時間間隔は次のコードで行っている。
while time.perf_counter()
< ck_time + 0.1: # 画面の更新間隔を0.1秒とする
pass
pg.display.flip()
ck_time =
time.perf_counter()
スクリプトの実行終了は、次のコードでWindowのクローズボタンがクリックされたかどうかのチェックにより行っている。
for e in pg.event.get():
if
e.type == pg.QUIT: # Close Windowボタンがクリックされたか
ck = False
# while文の終了
クリックされていたらckをFalseに設定してwhile文を終了している。
他の画像で試みる場合は、次のコードにおけるファイル名'sample.png'を該当の画像ファイル名に置き換えればよい。
img1 = cv2.imread('sample.png')
import pygame as pg
import cv2 #
pip install opencv-python
import numpy as np
import matplotlib.pyplot as plt
import time
pg.init() # PyGameの初期化
img1 = cv2.imread('sample.png')
img2 = cv2.cvtColor(img1,
cv2.COLOR_BGR2RGB) # RGBに変換
plt.imshow(img2)
plt.show()
(img_h, img_w, _) = img1.shape
# 画像配列のサイズ
print(img_h, img_w)
surfaces = []
for i in range(38):
ck_time =
time.perf_counter()
t_angl = i * 2 *
np.pi/38
# 回転角
s_ps = np.array([[img_w//2,
0], [img_w//2, img_h], [0, 0]], dtype=np.float32)
d_ps = np.array([[img_w//2,
0], [img_w//2, img_h],
[int((img_w//2)*(1 - np.cos(t_angl))), 0]],
dtype=np.float32)
t_mat =
cv2.getAffineTransform(s_ps, d_ps)
# 変換行列
t_img = cv2.warpAffine(img1,
t_mat, (img_w, img_h)) # 画像の変換
cv2.imwrite('temp.png',
t_img)
# 変換画像をファイルに保存
surfaces.append(pg.image.load('temp.png')) # 保存画像ファイルをPyGame用画像として
# スクリーンのリストに格納
print(f'{i+1}/38')
print(len(surfaces))
screen = pg.display.set_mode((img_w+200,
img_h+200)) # 表示画面のサイズ
pg.display.set_caption('Using OpenCV')
screen.fill((0, 0, 0))
ck = True
# while文のコントロール用
img_id = 0
# 表示画像のid
size_L = len(surfaces)
ck_time = time.perf_counter() # 画面の更新間隔のコントロール用
while ck:
screen.blit(surfaces[img_id], (100, 100))
img_id += 1
if img_id >= size_L:
img_id = 0
while time.perf_counter()
< ck_time + 0.1: # 画面の更新間隔を0.1秒とする
pass
pg.display.flip()
ck_time =
time.perf_counter()
for e in pg.event.get():
if
e.type == pg.QUIT: # Close Windowボタンがクリックされたか
ck = False
# while文の終了
pg.quit() # PyGameの終了