新着情報
1-3. 静止画像のGUI処理システム

Fig.1 は静止画像のGUI処理システムを立ち上げ、「顔と目の認識」ボタンをクリックした時の結果を表示している。
ここで示す静止画像のGUI処理システムは(2)のプロトタイプGUI画像処理システムを拡張して、14種類の異なる処理ボタンを配置した静止画像のGUI処理システムである。これを実現するサンプルプログラムImageProcessingGUIsystem.pyを以下に示す。
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Tue Mar 12 10:44:33 2019
@author: PBK-****
"""
from tkinter import *
from tkinter import filedialog
from tkinter import messagebox
from matplotlib import pyplot as plt
import sys
import os
import os.path
import numpy as np
import cv2
from PIL import Image, ImageTk, ImageFilter
import time
class App(Frame):
def __init__(self,master=None):
#フレーム
Frame.__init__(self, master)
self.master.title('画像処理システム')
self.master.minsize(1000,400)
# self.filename=None
#メニューバー
self.menu_bar = Menu(self.master)
self.master.config(menu=self.menu_bar)
self.menu_file = Menu(self.menu_bar,tearoff = False)
self.menu_edit = Menu(self.menu_bar,tearoff = False)
self.menu_heikatsu = Menu(self.menu_edit,tearoff = False)
self.menu_hanten = Menu(self.menu_edit,tearoff = False)
self.menu_bunkatsu = Menu(self.menu_edit,tearoff = False)
self.menu_bar.add_cascade(label='ファイル(F)', menu=self.menu_file, underline=5)
self.menu_file.add_command(label='開く', command=self.open, underline=3, accelerator = 'Ctrl-O')
self.menu_file.add_command(label='保存', command=self.save, underline=5, accelerator = 'Ctrl-S')
self.menu_file.add_separator()
self.menu_file.add_command(label='終了', command=self.quit, underline=5, accelerator = 'Ctrl-Q')
self.menu_bar.add_cascade(label='編集(E)', menu=self.menu_edit, underline=5)
self.menu_edit.add_command(label='二値化', command=self.binarization)
self.menu_edit.add_cascade(label='平滑化', command=self.quit,menu=self.menu_heikatsu)
self.menu_heikatsu.add_command(label='ガウシアンフィルター', command=self.gaussianfilter)
self.menu_heikatsu.add_command(label='メディアンフィルター', command=self.medianfilter)
self.menu_edit.add_command(label='濃淡化', command=self.grayimage)
self.menu_edit.add_command(label='ヒストグラム計算', command=self.histgram)
self.menu_edit.add_command(label='回転', command=self.rotation)
self.menu_edit.add_command(label='エッジ検出', command=self.edge)
self.menu_edit.add_cascade(label="反転", command=self.quit,menu=self.menu_hanten)
self.menu_hanten.add_command(label='上下反転', command=self.upsidedown)
self.menu_hanten.add_command(label='左右反転', command=self.mirrorimage)
self.menu_edit.add_command(label='色調反転', command=self.reversecolor)
self.menu_edit.add_command(label='顔と目の認識', command=self.face_eye)
self.menu_edit.add_command(label='RGB色分解', command=self.colordecomposition)
self.menu_edit.add_cascade(label='領域分割', command=self.quit,menu=self.menu_bunkatsu)
self.menu_bunkatsu.add_command(label='Watershed法', command=self.watershed)
self.menu_bunkatsu.add_command(label='平均値シフト法', command=self.meanshift)
self.menu_edit.add_command(label='HSV色空間変換', command=self.hsvcolorspace)
self.image1 = PhotoImage()
self.image2 = PhotoImage()
#ラベル1
self.la = Label(self,text='target image',image=self.image1,bg="#44aaaa",
width=400, height=400)
self.la.pack(side=LEFT,padx=50, pady=90)
#ラベル2
self.la2 = Label(self,text='processed image',image=self.image2, bg="#44aaaa",
width=400, height=400)
self.la2.pack(side=LEFT,padx=10, pady=90)
#ボタン
self.button_0 = Button(self,text='対象画像選択',command=self.open,width=10).pack(side=TOP,padx=10, pady=10,anchor=W)
self.button_1 = Button(self,text='2値化',command=self.binarization,width=10).pack(side=TOP,padx=10, pady=10,anchor=W)
self.button_2 = Button(self,text='エッジ検出',command=self.edge,width=10).pack(side=TOP,padx=10, pady=10,anchor=W)
self.button_3 = Button(self,text='濃淡画像',command=self.grayimage,width=10).pack(side=TOP,padx=10, pady=10,anchor=W)
self.button_4 = Button(self,text='色調反転',command=self.reversecolor,width=10).pack(side=TOP,padx=10, pady=10,anchor=W)
self.button_5 = Button(self,text='平滑化(Gauss)',command=self.gaussianfilter,width=10).pack(side=TOP,padx=10, pady=10,anchor=W)
self.button_6 = Button(self,text='平滑化(中央値)',command=self.medianfilter,width=10).pack(side=TOP,padx=10, pady=10,anchor=W)
self.button_7 = Button(self,text='ヒストグラム',command=self.histgram,width=10).pack(side=TOP,padx=10, pady=10,anchor=W)
self.button_8 = Button(self,text='上下反転',command=self.upsidedown,width=10).pack(side=TOP,padx=10, pady=10,anchor=W)
self.button_9 = Button(self,text='左右反転',command=self.mirrorimage,width=10).pack(side=TOP,padx=10, pady=10,anchor=W)
self.button_10 = Button(self,text='顔と目の認識',command=self.face_eye,width=10).pack(side=TOP,padx=10, pady=10,anchor=W)
self.button_11 = Button(self,text='RGB色分解',command=self.colordecomposition,width=10).pack(side=TOP,padx=10, pady=10,anchor=W)
self.button_12 = Button(self,text='HSV色空間',command=self.hsvcolorspace,width=10).pack(side=TOP,padx=10, pady=10,anchor=W)
self.button_13 = Button(self,text="終了",command=self.quit,width=10).pack(side=TOP,padx=10, pady=10,anchor=W)
#終了
def quit(self):
if messagebox.askokcancel('Confirm Close', 'Are you sure you want to close?'):
self.master.destroy()
#開く
def open(self):
global filename
global size
size=400,400
filename = filedialog.askopenfilename()
if filename != "":
im = Image.open(filename)
im.thumbnail(size, Image.ANTIALIAS)
if im.mode == '1': # 1 bit 白黒 bitmap image
self.image1 = ImageTk.BitmapImage(im, foreground="white")
else: # color photo image
self.image1 = ImageTk.PhotoImage(im)
self.la.config(text='Target Image',image=self.image1,
width=self.image1.width(), height=self.image1.height(),compound='top')
#保存
def save(self):
global filename
global filename2
currentdir=os.path.dirname(__file__)
filename = filedialog.asksaveasfilename(initialdir = currentdir,title = "Select file",filetypes = (("jpeg files","*.jpg"),("all files","*.*")))
# cv2.imwrite('result.jpg',filename2)
cv2.imwrite(filename,filename2)
# print(os.path.basename(filename))
def callback(self):
print( "Entererd from",self.x,self.y)
#二値化
def binarization(self):
global filename
global filename2
global size
filename2 = cv2.imread(filename,0);
filename2 = cv2.adaptiveThreshold(filename2,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY,11,2)
cv2.imwrite('binary.jpg',filename2)
im2 = Image.open('binary.jpg')
im2.thumbnail(size,Image.ANTIALIAS)
self.image2 = ImageTk.PhotoImage(im2)
self.la2.config(text='Binary Image',image=self.image2,
width=self.image2.width(), height=self.image2.height(),compound='top')
#平滑化1
def gaussianfilter(self):
global filename
global filename2
global size
image2 = cv2.imread(filename)
# ガウシアンフィルター処理
filename2 = cv2.GaussianBlur(image2,(5,5),0)
cv2.imwrite('smoothgaussianf.jpg',filename2)
im2 = Image.open('smoothgaussianf.jpg')
im2.thumbnail(size,Image.ANTIALIAS)
self.image2 = ImageTk.PhotoImage(im2)
self.la.config(image=self.image1,
width=self.image1.width(), height=self.image1.height())
self.la2.config(text='Smoothed by GaussianF',image=self.image2,
width=self.image2.width(), height=self.image2.height())
#平滑化2
def medianfilter(self):
global filename
global filename2
global size
image = cv2.imread(filename)
# メディアンフィルター処理
filename2 = cv2.medianBlur(image,9) #kernel size should be odd number
cv2.imwrite('smoothmedianf.jpg',filename2)
im2 = Image.open('smoothmedianf.jpg')
im2.thumbnail(size,Image.ANTIALIAS)
self.image2 = ImageTk.PhotoImage(im2)
self.la2.config(text='Smoothed by MedianF',image=self.image2,
width=self.image2.width(), height=self.image2.height(),compound='top')
#モノクロ処理
def grayimage(self):
global filename
global filename2
global size
filename2 = cv2.imread(filename,0)
cv2.imwrite('Gray.jpg',filename2)
im2 = Image.open('Gray.jpg')
im2.thumbnail(size,Image.ANTIALIAS)
self.image2 = ImageTk.PhotoImage(im2)
self.la2.config(text='Gray Image',image=self.image2,
width=self.image2.width(), height=self.image2.height(),compound='top')
#ヒストグラム計算
def histgram(self):
global filename
im = cv2.imread(filename)
graph = plt.figure()
graph.add_subplot(311)
plt.hist(im[:,:,0].ravel(), 256, range=(0, 255), fc='b')
plt.xlim(0,255)
graph.add_subplot(312)
plt.hist(im[:,:,1].ravel(), 256, range=(0, 255), fc='g')
plt.xlim(0,255)
graph.add_subplot(313)
plt.hist(im[:,:,2].ravel(), 256, range=(0, 255), fc='r')
plt.xlim(0,255)
#plt.show()
plt.savefig('Histgrams.png',figsize=(6,5),dpi=150)
im2=Image.open('Histgrams.png')
im2.thumbnail(size,Image.ANTIALIAS)
self.image2 = ImageTk.PhotoImage(im2)
self.la2.config(text='BGR Histograms',image=self.image2,
width=self.image2.width(),height=self.image2.height(),compound='top')
#回転
def rotation(self):
global filename
global filename2
global size
im = cv2.imread(filename)
h,w,ch = im.shape
M = cv2.getRotationMatrix2D((w/2,h/2),60,1)
filename2 = cv2.warpAffine(im,M,(w,h))
cv2.imwrite('Rotation.jpg',filename2)
im2=Image.open('Rotation.jpg')
im2.thumbnail(size,Image.ANTIALIAS)
self.image2 = ImageTk.PhotoImage(im2)
self.la2.config(text='Image Rotated by 60゜',image=self.image2,
width=self.image2.width(),height=self.image2.height(),compound='top')
#エッジ検出
def edge(self):
global filename
global filename2
global size
gray = cv2.imread(filename,0)
# cannyアルゴリズムでエッジ抽出
filename2 = cv2.Canny(gray,100,200)
cv2.imwrite('EdgedByCanny.jpg',filename2)
im2=Image.open('EdgedByCanny.jpg')
im2.thumbnail(size,Image.ANTIALIAS)
self.image2 = ImageTk.PhotoImage(im2)
self.la2.config(text='Edge by CannyM',image=self.image2,
width=self.image2.width(),height=self.image2.height(),compound='top')
#上下反転
def upsidedown(self):
global filename
global filename2
img=cv2.imread(filename)
filename2=img.copy()
filename2=cv2.flip(img,0)
cv2.imwrite('UpDownFlip.jpg', filename2)
im2=Image.open('UpDownFlip.jpg')
im2.thumbnail(size,Image.ANTIALIAS)
self.image2 = ImageTk.PhotoImage(im2)
self.la2.config(text='UpsideDown Flipped Image',image=self.image2,
width=self.image2.width(),height=self.image2.height(),compound='top')
#左右反転
def mirrorimage(self):
global filename
global filename2
global size
img=cv2.imread(filename)
filename2=img.copy()
filename2=cv2.flip(img,1)
cv2.imwrite('LeftRightFlip.jpg', filename2)
im2 = Image.open('LeftRightFlip.jpg')
im2.thumbnail(size,Image.ANTIALIAS)
self.image2 = ImageTk.PhotoImage(im2)
self.la2.config(text='LeftRight Flipped Image',image=self.image2,
width=self.image2.width(),height=self.image2.height(),compound='top')
#色調反転
def reversecolor(self):
global filename
global filename2
im = cv2.imread(filename)
filename2 = 255 - im
cv2.imwrite('ColorReversed.jpg',filename2)
im2 = Image.open('ColorReversed.jpg')
im2.thumbnail(size,Image.ANTIALIAS)
self.image2 = ImageTk.PhotoImage(im2)
self.la2.config(text='Color Reversed Image',image=self.image2,
width=self.image2.width(),height=self.image2.height(),compound='top')
#顔認識
def face_eye(self):
global filename
global filename2
face_cascade_path = './haarcascades/haarcascade_frontalface_default.xml'
eye_cascade_path = './haarcascades/haarcascade_eye.xml'
face_cascade = cv2.CascadeClassifier(face_cascade_path)
eye_cascade = cv2.CascadeClassifier(eye_cascade_path)
src = cv2.imread(filename)
src_gray = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(src_gray,1.1,3)
for x, y, w, h in faces:
cv2.rectangle(src, (x, y), (x + w, y + h), (0, 255, 255), 2)
face = src[y: y + h, x: x + w]
face_gray = src_gray[y: y + h, x: x + w]
eyes = eye_cascade.detectMultiScale(face_gray)
for (ex, ey, ew, eh) in eyes:
cv2.rectangle(face, (ex, ey), (ex + ew, ey + eh), (0, 255, 0), 2)
cv2.imwrite('face-eye_detected.jpg', src)
im2 = Image.open('face-eye_detected.jpg')
im2.thumbnail(size,Image.ANTIALIAS)
self.image2 = ImageTk.PhotoImage(im2)
self.la2.config(text='Face Detection',image=self.image2,
width=self.image2.width(), height=self.image2.height(),compound='top')
#成分抽出
def colordecomposition(self):
global filename
img = plt.imread(filename)
print (img.shape)
img_arr = np.asarray(img)
img_r = img_arr.copy()
img_r[:,:,(1,2)]=0
img_g = img_arr.copy()
img_g[:,:,(0,2)]=0
img_b = img_arr.copy()
img_b[:,:,(0,1)]=0
fig = plt.figure()
fig.suptitle('Color Components',fontsize = 16)
ax1 = fig.add_subplot(131)
ax1.set_title('Red')
plt.imshow(img_r)
ax2 = fig.add_subplot(132)
ax2.set_title('Green')
plt.imshow(img_g)
ax3 = fig.add_subplot(133)
ax3.set_title('Blue')
plt.imshow(img_b)
#plt.show()
plt.savefig('figure.jpeg',figsize=(9,3),dpi=150)
im2=Image.open('figure.jpeg')
im2.thumbnail(size,Image.ANTIALIAS)
self.image2 = ImageTk.PhotoImage(im2)
self.la2.config(text='Color Decomposition',image=self.image2,
width=self.image2.width(),height=self.image2.height(),compound='top')
#領域分割1
def watershed(self):
global filename
global filename2
filename2 = cv2.imread(filename)
gray = cv2.cvtColor(filename2,cv2.COLOR_BGR2GRAY)
th = cv2.threshold(gray,0,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)[1]
k = np.ones((3,3),np.uint8)
bg = cv2.dilate(th,k,iterations=3)
trans = cv2.distanceTransform(bg,cv2.DIST_L2,3)
fg = cv2.threshold(trans,0.1*trans.max(),255,0)[1]
fg = np.uint8(fg)
unknown = cv2.subtract(bg,fg)
marker = cv2.connectedComponents(fg)[1]
marker = marker + 1
marker[unknown == 255] = 0
marker = cv2.watershed(filename2,marker)
filename2[marker == -1] = [0,255,0]
cv2.imwrite("Watershed.jpg",filename2)
im2 = Image.open('Watershed.jpg')
im2.thumbnail(size,Image.ANTIALIAS)
self.image2 = ImageTk.PhotoImage(im2)
self.la2.config(text='Segmentation(Watershed法)',image=self.image2,
width=self.image2.width(), height=self.image2.height(),compound='top')
#領域分割2
def meanshift(self):
global filename
global filename2
filename2 = cv2.imread(filename)
cv2.pyrMeanShiftFiltering(filename2, 3, 50, filename2, 1)
cv2.imwrite('DividedByRegion.jpg',filename2)
im2 = Image.open('DividedByRegion.jpg')
im2.thumbnail(size,Image.ANTIALIAS)
self.image2 = ImageTk.PhotoImage(im2)
self.la2.config(text='Segmentation(平均シフト法)',image=self.image2,
width=self.image2.width(), height=self.image2.height(),compound='top')
#HSV色空間
def hsvcolorspace(self):
global filename
global filename2
filename2 = cv2.imread(filename)
filename2 = cv2.cvtColor(filename2, cv2.COLOR_RGB2HSV)
cv2.imwrite("hsv.jpg",filename2)
im2 = Image.open('hsv.jpg')
im2.thumbnail(size,Image.ANTIALIAS)
self.image2 = ImageTk.PhotoImage(im2)
self.la2.config(text='Image in HSV Color Space',image=self.image2,
width=self.image2.width(), height=self.image2.height(),compound='top')
if __name__ == '__main__':
f = App()