python 事始め (8) 画像の回転 第4弾

いくつか改良を加えました。大きな改良は,左ボタンをを押したままにすると,動作?が続くようにしたこと
です。いままでは,一端ボタンを離して再びクリックしないと,同じ動作の繰り返しができませんでしたが,
改良いたしました。ある方のプログラムをおかりしてます。考え方としては,PICでよく使った割り込み処理
と同じ方法のようです。

クリックである動作(一回実施)
ボタンを離すとある動作

の動作は比較的簡単にできるのですが,

クリックである動作を続ける(クリックされている間繰り返して行う)
ボタンを離すと上記の動作をやめる。

ができなかったので大助かりでした。
それと,一定の角度の開きで回転する部分を,開き方を調整できるようにしたこと,回転角度を指定できるよ
うにしたことです。
これで,表示部分は,ほぼ完成ですが,「回転」→→「開く」の切り替え時に,がうまくいかないのが課題で
どうしようかと思案してます。

以下が,プログラムの全文です。

# ライブラリのインポート
import cv2

#import tkinter as tk
#impor tk.filedialog, tk.messagebox
import tkinter, tkinter.filedialog, tkinter.messagebox
from PIL import Image, ImageTk
import os
import matplotlib.pyplot as plt
import numpy as np
import time

dt=100 # millisecond

class SpecialButton(tkinter.Button):

	#def activate_press_and_release(self):
	def __init__(self,*args,**kwargs):
		#tk.Button.__init__(self,*args,**kwargs)
		tkinter.Button.__init__(self,*args,**kwargs)
		self._is_pressed = False
		self.bind('',self.pressed)
		self.bind('',self.released)

	def pressed(self,value):
		self._is_pressed = True

	def released(self,value):
		self._is_pressed = False

# ファイル名を配列に格納
file_names = ['00.jpg', '01.jpg', '02.jpg','03.jpg','04.jpg','05.jpg','06.jpg','07.jpg','08.jpg','09.jpg','10.jpg',\
		'11.jpg','12.jpg','13.jpg','14.jpg','15.jpg','16.jpg','17.jpg','18.jpg','19.jpg','20.jpg','21.jpg',\
		'22.jpg','23.jpg','24.jpg','25.jpg','26.jpg','27.jpg','28.jpg','29.jpg','30.jpg','31.jpg','32.jpg',\
		'33.jpg','34.jpg','35.jpg','36.jpg','37.jpg','38.jpg','39.jpg','40.jpg','41.jpg','42.jpg','43.jpg',\
		'44.jpg','45.jpg','46.jpg','47.jpg','48.jpg','49.jpg','50.jpg','51.jpg','52.jpg','53.jpg','54.jpg',\
		'55.jpg','56.jpg','57.jpg','58.jpg','59.jpg','60.jpg','61.jpg','62.jpg','63.jpg','64.jpg','65.jpg']
file_names1 = [ '0.jpg', '1.jpg', '2.jpg','3.jpg','4.jpg','5.jpg','6.jpg','7.jpg','8.jpg','9.jpg','10.jpg',\
		'11.jpg','12.jpg','13.jpg','14.jpg','15.jpg','16.jpg','17.jpg','18.jpg','19.jpg','20.jpg','21.jpg',\
		'22.jpg','23.jpg','24.jpg','25.jpg','26.jpg','27.jpg','28.jpg','29.jpg','30.jpg','31.jpg','32.jpg',\
		'33.jpg','34.jpg','35.jpg','36.jpg','37.jpg','38.jpg','39.jpg','40.jpg','41.jpg','42.jpg','43.jpg',\
		'44.jpg','45.jpg','46.jpg','47.jpg','48.jpg','49.jpg','50.jpg','51.jpg','52.jpg','53.jpg','54.jpg',\
		'55.jpg','56.jpg','57.jpg','58.jpg','59.jpg','60.jpg']

#グローバル変数の定期
img=file_names[0]
kaisu=0
kaisu1=0
gazou=""
img1=""
revers=0
kaiten_deg=0
kaiten_ang=0
cw_f=0
ccw_f=0
button_f=0
dt=100

imagetk_list = list()

# ベースパスを設定
base_path = 'E:/python-kaihatu/nanikana/mask-jp'
base_path1 = 'E:/python-kaihatu/nanikana/mask-r1'

# tkオブジェクトの作成
root = tkinter.Tk()
root.title("なにかな") #ウィンドウのタイトルを設定
root.geometry("700x570") #ウィンドウのサイズを設定

### キャンバス作成
canvas=tkinter.Canvas(root,width=550, height=550)
canvas.place(x = 10,y = 10)

#背景画像を読み込み
gazou= cv2.imread('E:/python-kaihatu/nanikana/gazou/isu.jpg')

def gazou_over():
	global kaisu,gazou

	# 「フルパス+ファイル名」を作成
	full_path = os.path.join(base_path, file_names[kaisu])

	# マスクファイルを開く
	mask = cv2.imread(full_path)

	if mask is not None:
		#画像の合成
		result = cv2.bitwise_and(mask,gazou)
		#BRG読み込みをRGBに変換
		result = cv2.cvtColor(result, cv2.COLOR_BGR2RGB)
		#フォーマットをPILに変換
		result = Image.fromarray(result)
	return result

def kaiten_mr():
	global result1,mask,kaiten_deg,kaiten_ang
	# フルパスを作成
	full_path = os.path.join(base_path,file_names[kaisu1] )

	# マスクファイルを開く
	mask = cv2.imread(full_path)

	#マスク画像の回転
	#	高さ・幅・回転の中心定義
	height = mask.shape[0]                         
	width =  mask.shape[1]                            
	center = (int(width/2), int(height/2))

	angle = kaiten_deg*kaiten_ang*(-1)
	scale=1.0
	trans = cv2.getRotationMatrix2D(center, angle , scale)
	mask = cv2.warpAffine(mask, trans, (width,height), borderMode=cv2.BORDER_CONSTANT, borderValue=(255, 255, 255))

	#画像の合成
	result1 = cv2.bitwise_and(mask,gazou)

	#BRG読み込みをRGBに変換
	result1= cv2.cvtColor(result1, cv2.COLOR_BGR2RGB)

	#フォーマットをPILに変換
	result1 = Image.fromarray(result1)
	
	#TkinterのPhotoImageに変換
	result1=ImageTk.PhotoImage(result1)

	canvas.create_image(273,273,image = result1,tag='p1')

def kaiten():
	global result1,mask
	# フルパスを作成
	full_path1 = os.path.join(base_path1, file_names1[kaisu1])

	# マスクファイルを開く
	mask = cv2.imread(full_path1)
	
	#画像の合成
	result1 = cv2.bitwise_and(mask,gazou)

	#cv2.imshow('test', result)

	#BRG読み込みをRGBに変換
	result1= cv2.cvtColor(result1, cv2.COLOR_BGR2RGB)

	#フォーマットをPILに変換
	result1 = Image.fromarray(result1)
	
	#TkinterのPhotoImageに変換
	result1=ImageTk.PhotoImage(result1)

	canvas.create_image(273,273,image = result1,tag='p1')

#クリック動作
def on_button_click():
	global kaisu,imagetk_list,button_f
	button_f=1

	if  kaisu<65:
		kaisu= kaisu+1

		#旧画像の削除
		canvas.delete('p1')

		result= gazou_over()
		result=ImageTk.PhotoImage(result)
		imagetk_list.append(result)
		canvas.create_image(273,273,image = result,tag='p1')

def on_button1_click():
	global kaisu,imagetk_list,button_f

	if  kaisu>0:
		kaisu= kaisu-1

		#旧画像の削除
		canvas.delete('p1')

		result= gazou_over()
		result=ImageTk.PhotoImage(result)
		imagetk_list.append(result)
		canvas.create_image(273,273,image = result,tag='p1')
	

def on_button2_click():
	global kaisu1,kaiten_deg,cw_f,ccw_f,kaiten_ang

	kaisu1=int(textbox1.get())
	kaiten_ang=int(textbox2.get())

	cw_f=1#時計回り回転
	
	if ccw_f==1:
		ccw_f=0
		kaiten_deg=kaiten_deg+2
			
	if kaiten_deg==0:
		kaiten_mr()
		kaiten_deg=kaiten_deg+1
	
	else:
		kaiten_mr()
		kaiten_deg=kaiten_deg+1


def on_button3_click():
	global kaisu1,kaiten_deg,cw_f,ccw_f,kaiten_ang

	kaisu1=int(textbox1.get())
	kaiten_ang=int(textbox2.get())


	ccw_f=1#逆時計回り回転

	if cw_f==1:
		cw_f=0
		kaiten_deg=kaiten_deg-2
	
	if kaiten_deg==0:
		kaiten_deg=kaiten_deg-1
		kaiten_mr()
		kaiten_deg=kaiten_deg-1

	else:
		kaiten_mr()
		kaiten_deg=kaiten_deg-1

def on_button4_click():
	global gazou

	fTyp = [("","*")]
	#iDir = os.path.abspath(os.path.dirname(__file__))
	iDir='E:/python-kaihatu/nanikana/gazou/'
	tkinter.messagebox.showinfo('なにかな','処理ファイルを選択してください!')
	file = tkinter.filedialog.askopenfilename(filetypes = fTyp,initialdir = iDir)

	# 処理ファイル名の出力
	#tkinter.messagebox.showinfo('なにかな',file)

	if file=="":
		gazou=cv2.imread('E:/python-kaihatu/nanikana/gazou/isu.jpg')
		
	else:
		gazou=cv2.imread(file)

	img_pil=gazou_over()
	img_pil=ImageTk.PhotoImage(img_pil)
	#画像ファイルをキャンバスの(0,0)に合わせて表示してみる
	canvas.create_image(273,273,image = img_pil,tag='p1')

def on_button5_click():
	global kaisu1,kaiten_deg

	kaisu1=4

	kaiten_mr()

	kaiten_deg=kaiten_deg+1


def callback():
	global root,button1,button2

	if button._is_pressed:
		on_button_click()
	if button1._is_pressed:
		on_button1_click()
	if button2._is_pressed:
		on_button2_click()
	if button3._is_pressed:
		on_button3_click()
	time.sleep(0.05)
	root.after(dt,callback)


#PILでjpgを使用
img_pil=gazou_over()
img_pil=ImageTk.PhotoImage(img_pil)
#画像ファイルをキャンバスの(0,0)に合わせて表示してみる
canvas.create_image(273,273,image = img_pil,tag='p1')

# ウィジェットの配置や、イベント処理などを記述
textbox1 = tkinter.Entry(root,width=3)
textbox1.place(x=635, y=230)
textbox1.insert(0,"4")
textbox2 = tkinter.Entry(root,width=3)
textbox2.place(x=635, y=250)
textbox2.insert(0,"5")

#button = tkinter.Button(root, text="cw開く", bg="cyan4", fg="white",width=8, height=1,)
button = SpecialButton(text="cw開く", bg="cyan4", fg="white",width=8, height=1,)
button.place(x=595, y=30)

button1 = SpecialButton(text="ccw閉じる", command=on_button1_click, bg="cyan4", fg="white",width=8, height=1)
button1.place(x=595, y=60)

button2 = SpecialButton(text="回転", command=on_button2_click, bg="cyan4", fg="white",width=8, height=1)
button2.place(x=595, y=170)

button3 = SpecialButton(text="逆回転", command=on_button3_click, bg="cyan4", fg="white",width=8, height=1)
button3.place(x=595, y=200)

button4 = tkinter.Button(root,text="ファイル", command=on_button4_click, bg="cyan4", fg="white",width=8, height=1)
button4.place(x=595, y=400)


# メインループの実行
#root = tkinter.Tk()
root.after(dt,callback)
root.mainloop()

今回の目玉は,tkinter.Button の代わりに諸兄の作られた SpecialButton のを使ったことと,下記の
callback()
関数を使ったことです。この関数は,一定時間間隔で,自分自身を呼び出す,「再帰」を使っていることで
す。今回のプログラムを考えるにあたって,左ボタンのチェックを,無限ループのなかで,チェックして,
フラグによって,ループを抜ける方法もやってみましたが,うまく動作しませんでした。またしても,諸兄
に助けられました,それにしても,すごい方がいるもんです。

def callback():
	global root,button1,button2

	if button._is_pressed:
		on_button_click()
	if button1._is_pressed:
		on_button1_click()
	if button2._is_pressed:
		on_button2_click()
	if button3._is_pressed:
		on_button3_click()
	time.sleep(0.05)
	root.after(dt,callback)

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA