0. はじめに
※ この作品はピアプロ・キャラクター・ライセンスに基づいてクリプトン・フューチャー・メディア株式会社のキャラクター「初音ミク」を描いたものです
1. OpenCVの図形描画関数
- こちらのサイトを参考にさせていただいております.
共通引数
-
img
:図形を描画する画像 -
pt1
:始点 -
pt2
:終点 -
center
:円の中心 -
color
:色(今回はカラー画像で(Blue, Green, Red)で指定する) -
thickness
:線の太さ,長方形や円の場合は負の値を指定することで塗りつぶされる(デフォルト:1) -
lineType
:線のタイプ(デフォルト:8連結) -
shift
:座標と半径の値の小数点以下の桁を表すビット数(デフォルト:0)
図形を描画するための画像を用意する
# OpenCVのインポート
import cv2
# 画像をNumPyの配列ndarrayとして読み込んで操作するためにインポート
import numpy as np
# np.full((縦のサイズ, 横のサイズ, 3), (Blue, Green, Red),
# 符号なし8ビット整数型)で図形を描画するための画像を作成
img = np.full((100, 100, 3), (211, 211, 211), dtype=np.uint8)
# image.pngという名前で出力する
cv2.imwrite('image.png', img)
線分:cv2.line()
# cv2.line(img, pt1, pt2, color, thickness, lineType, shift)
cv2.line(img, (10, 10), (90, 90), (0, 0, 255))
cv2.line(img, (90, 10), (10, 90), (0, 255, 0), thickness=3, lineType=cv2.LINE_AA)
矢印:cv2.arrowedLine()
# cv2.arrowedLine(img, pt1, pt2, color, thickness, lineType, shift, tipLength)
# tipLength:矢の先の部分の長さ,全体の長さに対する比で表す(デフォルト:0.1)
cv2.arrowedLine(img, (10, 10), (90, 90), (255, 0, 0), thickness=5)
cv2.arrowedLine(img, (90, 10), (10, 90), (0, 255, 255), tipLength=0.5)
長方形:cv2.rectangle()
# cv2.rectangle(img, pt1, pt2, color, thickness, lineType, shift)
cv2.rectangle(img, (10, 10), (90, 40), (255, 255, 0), thickness=-1)
cv2.rectangle(img, (10, 60), (90, 90), (255, 0, 255))
円:cv2.circle()
# cv2.circle(img, center, radius, color, thickness, lineType, shift)
# radius:円の半径
cv2.circle(img, (25, 25), 15, (0, 0, 255), thickness=-1)
cv2.circle(img, (65, 65), 20, (0, 255, 0), thickness=5, lineType=cv2.LINE_4)
楕円:cv2.ellipse()
# cv2.ellipse(img, box, color, thickness, lineType)
# box(center, axes, angle):centerは(x, y),axesは(横方向直径, 縦方向直径),
# angleはx軸方向を0度として時計回りに回転角度を指定する
cv2.ellipse(img, ((20, 35), (20, 50), 0), (255, 0, 0), thickness=-1)
cv2.ellipse(img, ((65, 65), (30, 60), 45), (0, 255, 255), thickness=2, lineType=cv2.LINE_AA)
円弧:cv2.ellipse()
# cv2.ellipse(img, center, axes, angle, startAngle, endAngle, color, thickness, lineType, shift)
# axes:(横方向半径, 縦方向半径)
# startAngle:円弧の開始角度
# endAngle:終了角度
cv2.ellipse(img, (25, 50), (10, 25), 0, 0, 270, (255, 255, 0))
cv2.ellipse(img, (75, 50), (10, 25), 30, 0, 270, (255, 0, 255), thickness=-1)
2. 初音ミクを描く
背景
import cv2
import numpy as np
img = np.full((500, 500, 3), (211, 211, 211), dtype=np.uint8)
cv2.imwrite("miku.png", img)
顔と眉
# 顔
cv2.circle(img, (250, 280), 150, (230, 240, 255), thickness=-1)
# 左眉
cv2.ellipse(img, (180, 270), (30, 10), 0, 210, 330, (0, 0, 0))
# 右眉
cv2.ellipse(img, (320, 270), (30, 10), 0, 210, 330, (0, 0, 0))
髪
# 髪土台
cv2.ellipse(img, (250, 175), ( 90, 150), 90, 90, 270, (118, 123, 1), thickness=-1)
# 前髪中央左
cv2.ellipse(img, (170, 270), (110, 110), 260, 0, 40, (118, 123, 1), thickness=-1)
# 前髪中央右
cv2.ellipse(img, (260, 160), ( 60, 150), 170, 270, 360, (118, 123, 1), thickness=-1)
# 前髪中央右調整
cv2.ellipse(img, (290, 180), ( 30, 140), 180, 270, 360, (230, 240, 255), thickness=-1)
# 触覚左
cv2.ellipse(img, (130, 160), ( 60, 220), 180, 270, 360, (118, 123, 1), thickness=-1)
# 触覚左調整
cv2.ellipse(img, (135, 200), ( 20, 180), 180, 270, 360, (230, 240, 255), thickness=-1)
# 前髪左
cv2.ellipse(img, (170, 180), ( 60, 120), 200, 270, 360, (118, 123, 1), thickness=-1)
# 触覚右
cv2.ellipse(img, (370, 160), ( 60, 220), 0, 0, 90, (118, 123, 1), thickness=-1)
# 触覚右調整
cv2.ellipse(img, (365, 200), ( 20, 180), 0, 0, 90, (230, 240, 255), thickness=-1)
# 前髪右
cv2.ellipse(img, (240, 175), (100, 220), 310, 0, 90, (118, 123, 1), thickness=-1)
# ツインテール左根元
cv2.ellipse(img, (150, 200), (100, 100), 120, 0, 180, (118, 123, 1), thickness=-1)
# ツインテール左毛先
cv2.ellipse(img, ( 80, 340), (180, 80), 100, 0, 180, (118, 123, 1), thickness=-1)
# ツインテール右根元
cv2.ellipse(img, (350, 200), (100, 100), 120, 90, 270, (118, 123, 1), thickness=-1)
# ツインテール右毛先
cv2.ellipse(img, (420, 340), (180, 80), 260, 0, 180, (118, 123, 1), thickness=-1)
# 触覚左影
cv2.ellipse(img, (105, 260), ( 20, 90), 0, 90, 270, ( 53, 53, 23), thickness=-1)
# ツインテール左影
cv2.ellipse(img, ( 80, 340), (120, 20), 100, 0, 180, ( 53, 53, 23), thickness=-1)
# 触覚左影調整
cv2.ellipse(img, (110, 260), ( 20, 90), 0, 90, 270, (118, 123, 1), thickness=-1)
# 触覚右影
cv2.ellipse(img, (395, 260), ( 20, 90), 180, 90, 270, ( 53, 53, 23), thickness=-1)
# ツインテール右影
cv2.ellipse(img, (420, 340), (120, 20), 260, 0, 180, ( 53, 53, 23), thickness=-1)
# 触覚右影調整
cv2.ellipse(img, (390, 260), ( 20, 90), 180, 90, 270, (118, 123, 1), thickness=-1)
口と頬
# 口
cv2.ellipse(img, (250, 350), ( 15, 15), 0, 40, 140, ( 0, 0, 0))
# 左頬
cv2.ellipse(img, ((160, 350), ( 60, 80), -25), (225, 225, 250), thickness=-1)
# 右頬
cv2.ellipse(img, ((340, 350), ( 60, 80), 25), (225, 225, 250), thickness=-1)
目
# 左目白
cv2.ellipse(img, ((180, 320), ( 60, 80), 0), (255, 255, 255), thickness=-1)
# 左目緑大
cv2.ellipse(img, ((185, 315), ( 48, 70), 0), (118, 123, 1), thickness=-1)
# 左目緑中
cv2.ellipse(img, ((190, 326), ( 40, 50), 0), (176, 162, 101), thickness=-1)
# 左目緑小
cv2.ellipse(img, ((193, 330), ( 30, 40), 0), (168, 184, 103), thickness=-1)
# 左目緑中央
cv2.ellipse(img, ((190, 310), ( 15, 20), 0), (118, 118, 73), thickness=-1)
# 左目灰
cv2.ellipse(img, ((195, 340), ( 20, 20), 0), (169, 169, 169), thickness=-1)
# 左目光大
cv2.ellipse(img, ((190, 290), ( 10, 15), -20), (255, 255, 255), thickness=-1)
# 左目光小
cv2.ellipse(img, ((185, 290), ( 10, 5), 0), (255, 255, 255), thickness=-1)
# 左目線上
cv2.ellipse(img, (175, 300), ( 20, 40), 90, 120, 240, ( 0, 0, 0), thickness=5)
# 左目線下
cv2.ellipse(img, (175, 300), ( 20, 40), 60, 120, 190, ( 0, 0, 0), thickness=5)
# 右目白
cv2.ellipse(img, ((320, 320), ( 60, 80), 0), (255, 255, 255), thickness=-1)
# 右目緑大
cv2.ellipse(img, ((315, 315), ( 48, 70), 0), (118, 123, 1), thickness=-1)
# 右目緑中
cv2.ellipse(img, ((310, 326), ( 40, 50), 0), (176, 162, 101), thickness=-1)
# 右目緑小
cv2.ellipse(img, ((307, 330), ( 30, 40), 0), (168, 184, 103), thickness=-1)
# 右目緑中央
cv2.ellipse(img, ((310, 310), ( 15, 20), 0), (118, 118, 73), thickness=-1)
# 右目灰
cv2.ellipse(img, ((305, 340), ( 20, 20), 0), (169, 169, 169), thickness=-1)
# 右目光大
cv2.ellipse(img, ((320, 290), ( 10, 15), -20), (255, 255, 255), thickness=-1)
# 右目光小
cv2.ellipse(img, ((315, 290), ( 10, 5), 0), (255, 255, 255), thickness=-1)
# 右目線上
cv2.ellipse(img, (325, 300), ( 20, 40), 90, 120, 240, ( 0, 0, 0), thickness=5)
# 右目線下
cv2.ellipse(img, (325, 300), ( 20, 40), 120, 170, 250, ( 0, 0, 0), thickness=5)
髪飾り
# 左髪飾り左上黒
cv2.line(img, (150, 110), (110, 150), ( 0, 0, 0), thickness=30)
# 左髪飾り左下黒
cv2.line(img, (130, 170), (110, 150), ( 0, 0, 0), thickness=30)
# 左髪飾り左上赤
cv2.line(img, (150, 110), (110, 150), ( 0, 0, 255), thickness=10)
# 左髪飾り左下赤
cv2.line(img, (130, 170), (110, 150), ( 0, 0, 255), thickness=10)
# 右髪飾り左上黒
cv2.line(img, (370, 110), (330, 150), ( 0, 0, 0), thickness=30)
# 右髪飾り左下黒
cv2.line(img, (370, 190), (330, 150), ( 0, 0, 0), thickness=30)
# 右髪飾り右下黒
cv2.line(img, (370, 190), (390, 170), ( 0, 0, 0), thickness=30)
# 右髪飾り左上赤
cv2.line(img, (370, 110), (330, 150), ( 0, 0, 255), thickness=10)
# 右髪飾り左下赤
cv2.line(img, (370, 190), (330, 150), ( 0, 0, 255), thickness=10)
# 右髪飾り右下赤
cv2.line(img, (370, 190), (390, 170), ( 0, 0, 255), thickness=10)
3. 髪型と目の色を変えると
- 別のキャラクターになります
import cv2
import numpy as np
img = np.full((500, 500, 3), (211, 211, 211), dtype=np.uint8)
# 左髪後ろ中央
cv2.ellipse(img, (160, 300), ( 30, 120), 20, 0, 90, ( 50, 148, 188), thickness=-1)
# 左髪後ろ左
cv2.ellipse(img, (160, 300), ( 30, 120), 40, 0, 90, ( 50, 148, 188), thickness=-1)
# 左髪後ろ右
cv2.ellipse(img, (150, 310), ( 30, 120), 0, 0, 90, ( 50, 148, 188), thickness=-1)
# 右髪後ろ中央
cv2.ellipse(img, (340, 300), ( 30, 120), 340, 90, 180, ( 50, 148, 188), thickness=-1)
# 右髪後ろ右
cv2.ellipse(img, (340, 300), ( 30, 120), 320, 90, 180, ( 50, 148, 188), thickness=-1)
# 右髪後ろ左
cv2.ellipse(img, (350, 310), ( 30, 120), 0, 90, 180, ( 50, 148, 188), thickness=-1)
# 顔
cv2.circle(img, (250, 280), 150, (230, 240, 255), thickness=-1)
# 左眉
cv2.ellipse(img, (180, 270), (30, 10), 0, 210, 330, (0, 0, 0))
# 右眉
cv2.ellipse(img, (320, 270), (30, 10), 0, 210, 330, (0, 0, 0))
# 髪土台
cv2.ellipse(img, (250, 175), ( 90, 150), 90, 90, 270, ( 0, 186, 255), thickness=-1)
# 前髪中央左
cv2.ellipse(img, (240, 250), (110, 110), 220, 0, 40, ( 0, 186, 255), thickness=-1)
# 前髪中央右
cv2.ellipse(img, (260, 130), ( 60, 150), 140, 270, 360, ( 0, 186, 255), thickness=-1)
# 前髪中央右調整
cv2.ellipse(img, (300, 170), ( 30, 140), 140, 270, 360, (230, 240, 255), thickness=-1)
# 触覚左
cv2.ellipse(img, (130, 260), ( 60, 130), 0, 90, 270, ( 0, 186, 255), thickness=-1)
# 触覚左調整
cv2.ellipse(img, (135, 200), ( 20, 180), 180, 270, 360, (230, 240, 255), thickness=-1)
# 前髪左
cv2.ellipse(img, (170, 180), ( 60, 120), 200, 270, 360, ( 0, 186, 255), thickness=-1)
# 触覚左影
cv2.ellipse(img, (125, 300), ( 10, 70), 0, 90, 270, ( 36, 106, 134), thickness=-1)
# 触覚右
cv2.ellipse(img, (370, 260), ( 60, 130), 0, 270, 450, ( 0, 186, 255), thickness=-1)
# 触覚右調整
cv2.ellipse(img, (365, 200), ( 20, 180), 0, 0, 90, (230, 240, 255), thickness=-1)
# 前髪右
cv2.ellipse(img, (370, 155), ( 20, 220), 0, 0, 90, ( 0, 186, 255), thickness=-1)
cv2.ellipse(img, (310, 210), ( 70, 70), 35, 180, 360, ( 0, 186, 255), thickness=-1)
# 触覚右影
cv2.ellipse(img, (375, 300), ( 10, 70), 180, 90, 270, ( 36, 106, 134), thickness=-1)
# 口
cv2.ellipse(img, (250, 350), ( 15, 15), 0, 40, 140, ( 0, 0, 0))
# 左頬
cv2.ellipse(img, ((160, 350), ( 60, 80), -25), (225, 225, 250), thickness=-1)
# 右頬
cv2.ellipse(img, ((340, 350), ( 60, 80), 25), (225, 225, 250), thickness=-1)
# 左目白
cv2.ellipse(img, ((180, 320), ( 60, 80), 0), (255, 255, 255), thickness=-1)
# 左目青大
cv2.ellipse(img, ((185, 315), ( 48, 70), 0), (128, 77, 0), thickness=-1)
# 左目青中
cv2.ellipse(img, ((190, 326), ( 40, 50), 0), (186, 118, 0), thickness=-1)
# 左目青小
cv2.ellipse(img, ((193, 330), ( 30, 40), 0), (255, 162, 0), thickness=-1)
# 左目青中央
cv2.ellipse(img, ((190, 310), ( 15, 20), 0), (147, 84, 0), thickness=-1)
# 左目灰
cv2.ellipse(img, ((195, 340), ( 20, 20), 0), (169, 169, 169), thickness=-1)
# 左目光大
cv2.ellipse(img, ((190, 290), ( 10, 15), -20), (255, 255, 255), thickness=-1)
# 左目光小
cv2.ellipse(img, ((185, 290), ( 10, 5), 0), (255, 255, 255), thickness=-1)
# 左目線上
cv2.ellipse(img, (175, 300), ( 20, 40), 90, 120, 240, ( 0, 0, 0), thickness=5)
# 左目線下
cv2.ellipse(img, (175, 300), ( 20, 40), 60, 120, 190, ( 0, 0, 0), thickness=5)
# 右目白
cv2.ellipse(img, ((320, 320), ( 60, 80), 0), (255, 255, 255), thickness=-1)
# 右目青大
cv2.ellipse(img, ((315, 315), ( 48, 70), 0), (128, 77, 0), thickness=-1)
# 右目青中
cv2.ellipse(img, ((310, 326), ( 40, 50), 0), (186, 118, 0), thickness=-1)
# 右目青小
cv2.ellipse(img, ((307, 330), ( 30, 40), 0), (255, 162, 0), thickness=-1)
# 右目青中央
cv2.ellipse(img, ((310, 310), ( 15, 20), 0), (147, 84, 0), thickness=-1)
# 右目灰
cv2.ellipse(img, ((305, 340), ( 20, 20), 0), (169, 169, 169), thickness=-1)
# 右目光大
cv2.ellipse(img, ((320, 290), ( 10, 15), -20), (255, 255, 255), thickness=-1)
# 右目光小
cv2.ellipse(img, ((315, 290), ( 10, 5), 0), (255, 255, 255), thickness=-1)
# 右目線上
cv2.ellipse(img, (325, 300), ( 20, 40), 90, 120, 240, ( 0, 0, 0), thickness=5)
# 右目線下
cv2.ellipse(img, (325, 300), ( 20, 40), 120, 170, 250, ( 0, 0, 0), thickness=5)
# ピン留め左上
cv2.line(img, (150, 230), (140, 220), (255, 255, 255), thickness=10)
# ピン留め左下
cv2.line(img, (140, 245), (130, 235), (255, 255, 255), thickness=10)
# ピン留め右上
cv2.line(img, (260, 210), (270, 200), (255, 255, 255), thickness=10)
# ピン留め右下
cv2.line(img, (300, 240), (310, 230), (255, 255, 255), thickness=10)
# カチューシャ左
cv2.ellipse(img, (145, 160), ( 100, 20), 315, 180, 360, (255, 255, 255), thickness=-1)
# カチューシャ右
cv2.ellipse(img, (355, 160), ( 100, 20), 45, 180, 360, (255, 255, 255), thickness=-1)
# リボン左内側
cv2.circle(img, (190, 100), 50, (255, 255, 255), thickness=-1)
# リボン左外側
cv2.ellipse(img, (160, 60), ( 80, 70), 90, 0, 90, (255, 255, 255), thickness=-1)
# リボン右内側
cv2.circle(img, (310, 100), 50, (255, 255, 255), thickness=-1)
# リボン右外側
cv2.ellipse(img, (340, 60), ( 80, 70), 180, 180, 270, (255, 255, 255), thickness=-1)
# リボン中心
cv2.rectangle(img, (240, 80), (260, 120), (255, 255, 255), thickness=-1)
cv2.imwrite("rin.png", img)
※ この作品はピアプロ・キャラクター・ライセンスに基づいてクリプトン・フューチャー・メディア株式会社のキャラクター「鏡音リン」を描いたものです