Pythonでいろいろやってみる

Pythonを使った画像処理や機械学習などの簡単なプログラムを載せています。

画像に集中線を引く

集中線はマンガで用いられる技法で、画面のある点から外側に放射状に線を引き、動きなどを表現するものです。
画像の内側と外側に円を仮定して、内側の円と外側の円の間で三角形を描画することで、画像に集中線を作成しています。
f:id:T_A_T:20190409195241p:plain
また、集中線の太さ(三角形の鋭角の大きさ)、集中線の頂点の位置にばらつきを与えて自然な感じにしています。

使った関数・メソッド
  • cv2.imread() : 画像ファイルの読み出し
  • img.shape : 画像の高さ、幅、チャンネル数を取得する
  • math.sqrt() : 平方根を求める
  • math.pi : 円周率
  • math.cos() : cosを求める
  • math.sin() : sinを求める
  • random.random() : 0.0~1.0の範囲のランダムな浮動小数点を生成
  • cv2.fillPoly() : 塗りつぶされた多角形を描画
  • cv2.imwrite() : 画像を保存する
環境
  • windows10 home
  • Anaconda 3/ jupyter notebook 5.6.0
  • Python 3.7.0
  • OpenCV 4.0.0
準備

画像ファイルはフリー写真素材ぱくたそからダウンロードさせていただき、ファイル名'cat_boss.jpg'で、jupyter notebookファイル(***.ipynb)と同じディレクトリに保存しました。 f:id:T_A_T:20190409202642p:plain
cat_boss.jpg

コード
import cv2  # OpenCVのインポート
import math  # Mathのインポート
import numpy as np  # numpyのインポート
import random  # randomのインポート

fname = 'cat_boss.jpg'  # 画像ファイル名
img = cv2.imread(fname)  # 画像を読み出しオブジェクトimgに代入
height, width = img.shape[:2]  # 画像の高さ、幅を取得

diagonal = math.sqrt(height**2+width**2) # 画像の対角線を計算(外側の円の半径に使用)
center_y = int(height/2)  # 集中線の中心座標y 
center_x = int(width/2)  # 集中線の中心座標x 
circle_r_1 = 230  # 内側の円の半径
circle_r_2 = int(diagonal)  # 外側の円の半径
line_number = 100  # 集中線の個数
angle_div = 2*math.pi/line_number  # 1周をline_numberで分割した際の角度(rad) 
angle_thickness = 2*math.pi/360*7  # 三角形の鋭角(rad)

# 集中線の本数分の三角形を描画する処理
for i in range(line_number):  # line_numberだけ繰り返す 
    r_1_variation = (random.random()-1)*30  # 内側の円の半径ばらつき
    angle_variation = (random.random()-1)/2  # 線の太さのばらつき
    angle = angle_div * i 
    cos_theta = math.cos(angle)  
    sin_theta = math.sin(angle)   
    cos_theta_2 = math.cos(angle+angle_thickness*angle_variation)
    sin_theta_2  = math.sin(angle+angle_thickness*angle_variation)
    x_1 =  int(center_x + (circle_r_1+r_1_variation) * cos_theta) 
    y_1 =  int(center_y + (circle_r_1+r_1_variation) * sin_theta)
    x_2 =  int(center_x + circle_r_2 * cos_theta)
    y_2 =  int(center_y + circle_r_2 * sin_theta)
    x_3 =  int(center_x + circle_r_2 * cos_theta_2)
    y_3 =  int(center_y + circle_r_2 * sin_theta_2)
    pts = np.array(((x_1, y_1), (x_2, y_2), (x_3, y_3)))
    cv2.fillPoly(img, [pts], (0, 0, 0))  # 塗りつぶされた三角形を描画  
    
cv2.imwrite('cat_boss_concentration.png',img)  # ファイル名 cat_boss_concentration.png でimgを保存
実行結果

集中線が引かれます。

f:id:T_A_T:20190409202720p:plain


集中線の中心位置を少し上に、中心円の大きさを大きく、集中線の色を白に変えてみます。

コード
import cv2  # OpenCVのインポート
import math  # Mathのインポート
import numpy as np  # numpyのインポート
import random  # randomのインポート

fname = 'cat_boss.jpg'  # 画像ファイル名
img = cv2.imread(fname)  # 画像を読み出しオブジェクトimgに代入
height, width = img.shape[:2]  # 画像の高さ、幅を取得

diagonal = math.sqrt(height**2+width**2) # 画像の対角線を計算(外側の円の半径に使用)
center_y = int(height/2-100)  # 集中線の中心座標y 
center_x = int(width/2)  # 集中線の中心座標x 
circle_r_1 = 280  # 内側の円の半径
circle_r_2 = int(diagonal)  # 外側の円の半径
line_number = 100  # 集中線の個数
angle_div = 2*math.pi/line_number  # 1周をline_numberで分割した際の角度(rad) 
angle_thickness = 2*math.pi/360*7  # 三角形の鋭角(rad)

# 集中線の本数分の三角形を描画する処理
for i in range(line_number):  # line_numberだけ繰り返す 
    r_1_variation = (random.random()-1)*30  # 内側の円の半径ばらつき
    angle_variation = (random.random()-1)/2  # 線の太さのばらつき
    angle = angle_div * i 
    cos_theta = math.cos(angle)  
    sin_theta = math.sin(angle)   
    cos_theta_2 = math.cos(angle+angle_thickness*angle_variation)
    sin_theta_2  = math.sin(angle+angle_thickness*angle_variation)
    x_1 =  int(center_x + (circle_r_1+r_1_variation) * cos_theta) 
    y_1 =  int(center_y + (circle_r_1+r_1_variation) * sin_theta)
    x_2 =  int(center_x + circle_r_2 * cos_theta)
    y_2 =  int(center_y + circle_r_2 * sin_theta)
    x_3 =  int(center_x + circle_r_2 * cos_theta_2)
    y_3 =  int(center_y + circle_r_2 * sin_theta_2)
    pts = np.array(((x_1, y_1), (x_2, y_2), (x_3, y_3)))
    cv2.fillPoly(img, [pts], (255, 255, 255))  # 塗りつぶされた三角形を描画
    
cv2.imwrite('cat_boss_concentration.png',img)  # ファイル名 cat_boss_concentration.png でimgを保存

実行結果

f:id:T_A_T:20190409202749p:plain

以下のサイトを参考にさせていただきました

Python公式 >> random.random()
note.nkmk.me >> Python, OpenCVで図形描画(線、長方形、円、矢印、文字など)

ブログランキングに参加しています

にほんブログ村 IT技術ブログへ
にほんブログ村