簡単なペイントツールを作ってみた。
OpenCVのGUI基礎編、これが3回目です。1回は画像の表示、2回目は線の描画について解説しました。今回は簡単なペイントツールを作ってトラックバーについて解説します。
ペイントツール
# -*- coding: utf-8 -*-
import cv2
#sx, syは線の始まりの位置
sx, sy = 0, 0
#ペンの色
color = (0, 0, 0)
#ペンの太さ
thickness = 1
#マウスの操作があるとき呼ばれる関数
def callback(event, x, y, flags, param):
global img, sx, sy, color, thickness
#マウスの左ボタンがクリックされたとき
if event == cv2.EVENT_LBUTTONDOWN:
sx, sy = x, y
#マウスの左ボタンがクリックされていて、マウスが動いたとき
if flags == cv2.EVENT_FLAG_LBUTTON and event == cv2.EVENT_MOUSEMOVE:
cv2.line(img, (sx, sy), (x, y), color, thickness)
sx, sy = x, y
# トラックバーを変更したらペンを変更
def changePencil(pos):
global color, thickness
r = cv2.getTrackbarPos("R", "img")
g = cv2.getTrackbarPos("G", "img")
b = cv2.getTrackbarPos("B", "img")
color = (b, g, r)
thickness = cv2.getTrackbarPos("T", "img")
#画像を読み込む
img = cv2.imread("img.jpg")
#ウィンドウの名前を設定
cv2.namedWindow("img", cv2.WINDOW_NORMAL)
#マウス操作のコールバック関数の設定
cv2.setMouseCallback("img", callback)
#トラックバーのコールバック関数の設定
cv2.createTrackbar("R", "img", 0, 255, changePencil)
cv2.createTrackbar("G", "img", 0, 255, changePencil)
cv2.createTrackbar("B", "img", 0, 255, changePencil)
cv2.createTrackbar("T", "img", 1, 100, changePencil)
while(1):
cv2.imshow("img", img)
k = cv2.waitKey(1)
#Escキーを押すと終了
if k == 27:
break
#sを押すと画像を保存
if k == ord("s"):
cv2.imwrite("painted.png", img)
break
このコードを実行すると次のような画面が現れます。画面を左クリックでなぞると線が描けます。 このウィンドには4つのトラックバーが付いてます。RGBの3つのバーでペンの色を設定します。Tのトラックバーで線の太さを調整します。
トラックバーの解説
#トラックバーのコールバック関数の設定
cv2.createTrackbar("R", "img", 0, 255, changePencil)
cv2.createTrackbar("G", "img", 0, 255, changePencil)
cv2.createTrackbar("B", "img", 0, 255, changePencil)
cv2.createTrackbar("T", "img", 1, 100, changePencil)
cv2.createTrackbar(name, windowName, startPos, max, callback)でトラックバーを追加します。nameはトラックバーの名前です。windowNameはトラックを表示するウィンドウの名前です。 startPosはトラックバーが最初に表示されたときの初期値です。maxはトラックバーの目盛の最大値です。最小値は0なのは変えられません。callbackはトラックバーを変えたときに呼ばれる関数を設定します。
トラックバーのコールバック関数
# トラックバーを変更したらペンを変更
def changePencil(pos):
global color, thickness
r = cv2.getTrackbarPos("R", "img")
g = cv2.getTrackbarPos("G", "img")
b = cv2.getTrackbarPos("B", "img")
color = (b, g, r)
thickness = cv2.getTrackbarPos("T", "img")
トラックバーのコールバック関数はトラックバーの位置を引数として受け取ります。つまり、posには変更されたトラックバーの位置が入ってます。 けれど今回はトラックバーの位置をcv2.getTrackbarPosでトラックバーの位置を取得してます。これはペンの色を決めるには変更されたトラックバーの位置だけではなく他のトラックバーの位置も取得しなけらばいけないからです。 トラックバーが変更されたらグローバル変数のcolor,thicknessに値を入れます。colorはペンの色、thicknessはペンの太さを表しています。
カラーパレットの分離
このままだとペイントツールらしくないので、カラーパレットを別のウィンドに分離してみまた。
# -*- coding: utf-8 -*-
import cv2
import numpy as np
#sx, syは線の始まりの位置
sx, sy = 0, 0
#ペンの色
color = (0, 0, 0)
#ペンの太さ
thickness = 1
#マウスの操作があるとき呼ばれる関数
def callback(event, x, y, flags, param):
global img, sx, sy, color, thickness
#マウスの左ボタンがクリックされたとき
if event == cv2.EVENT_LBUTTONDOWN:
sx, sy = x, y
#マウスの左ボタンがクリックされていて、マウスが動いたとき
if flags == cv2.EVENT_FLAG_LBUTTON and event == cv2.EVENT_MOUSEMOVE:
cv2.line(img, (sx, sy), (x, y), color, thickness)
sx, sy = x, y
# トラックバーの値を変更する度にRGBを出力する
def changePencil(pos):
global palette_img, color, thickness
r = cv2.getTrackbarPos("R", "palette")
g = cv2.getTrackbarPos("G", "palette")
b = cv2.getTrackbarPos("B", "palette")
palette_img[:] = [b, g, r]
color = (b, g, r)
thickness = cv2.getTrackbarPos("T", "palette")
#画像を読み込む
img = cv2.imread("img.jpg")
#パレット画像を作成
palette_img = np.zeros((200, 512, 3), np.uint8)
#ウィンドウの名前を設定
cv2.namedWindow("img", cv2.WINDOW_NORMAL)
#パレットウィンドを生成
cv2.namedWindow("palette")
#マウス操作のコールバック関数の設定
cv2.setMouseCallback("img", callback)
#トラックバーのコールバック関数の設定
cv2.createTrackbar("R", "palette", 0, 255, changePencil)
cv2.createTrackbar("G", "palette", 0, 255, changePencil)
cv2.createTrackbar("B", "palette", 0, 255, changePencil)
cv2.createTrackbar("T", "palette", 1, 100, changePencil)
while(1):
cv2.imshow("img", img)
cv2.imshow("palette", palette_img)
k = cv2.waitKey(1)
#Escキーを押すと終了
if k == 27:
break
#sを押すと画像を保存
if k == ord("s"):
cv2.imwrite("painted.png", img)
break
numpyインポート
# -*- coding: utf-8 -*-
import cv2
import numpy as np
単色画像を作るために、numpyをインポートしましょう。
パレットウィンドの生成
#パレットウィンドを生成
cv2.namedWindow("palette")
paletteという名前でウィンドを生成しましょう。
パレット画像の生成
#パレット画像を作成
palette_img = np.zeros((200, 512, 3), np.uint8)
np.zerosで高さが200、幅が512、各値が[0, 0, 0]の画像を生成します。
パレットに色を表示
cv2.imshow("palette", palette_img)
palette_imgに現在のペンの色を表示します。色情報の更新はトラックバーのコールバック関数から行います。
トラックバーの表示ウィンドの変更
後はトラックバーの表示ウィンドを変更をすれば完成です。
# トラックバーの値を変更する度にRGBを出力する
def changePencil(pos):
global palette_img, color, thickness
r = cv2.getTrackbarPos("R", "palette")
g = cv2.getTrackbarPos("G", "palette")
b = cv2.getTrackbarPos("B", "palette")
palette_img[:] = [b, g, r]
color = (b, g, r)
thickness = cv2.getTrackbarPos("T", "palette")
#トラックバーのコールバック関数の設定
cv2.createTrackbar("R", "palette", 0, 255, changePencil)
cv2.createTrackbar("G", "palette", 0, 255, changePencil)
cv2.createTrackbar("B", "palette", 0, 255, changePencil)
cv2.createTrackbar("T", "palette", 1, 100, changePencil)
コメント