新着情報
1-3. 静止画像の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()