Wednesday, December 3, 2014

[OpenCV กับการแสดงผลใน Tkinter] และ [PIL กับการแสดงผลด้วย OpenCV]

ตั้งใจจะเขียนเรื่องนี้นานแล้ว พึ่งจำได้ครับ

ตอนเราประมวลผลรูปด้วย OpenCV มันก็จะมีหน้าต่างแสดงผลมาให้ ด้วยคำสั่ง เช่น imshow

อย่างไรก็ตาม ถ้าเราใช้ Python ทางเลือกหนึ่งในการแสดงผลก็คือ การใช้ Tkinter ซึ่งเป็น UI ที่มีมากับ Python เลย

สิ่งที่ต้องทำคือ
1. รูปแบบการเก็บข้อมูลภาพของ OpenCV ต่างกับแบบอื่น คือเป็น BGR จำเป็นต้องเปลี่ยนให้เป็น RGB ก่อน
2. OpenCV เก็บข้อมูลภาพเป็น NumPy Array การอ่านไปแสดงผลใน Tkinter จำเป็นต้องใช้คำสั่งการอ่านจาก Array แทน

โค้ดก็จะเป็นประมาณนี้ครับ คืออ่านค่าภาพ (และประมวลผล) ด้วย OpenCV จากนั้นสร้าง UI ด้วย Tkinter และแสดงผล
import cv2
from Tkinter import Tk, Label
from PIL import Image, ImageTk

#load image in grayscale, output is numpy array
img = cv2.imread("lena.jpg", cv2.IMREAD_COLOR)

if img==None:
    print "Image not loaded"
else:
    #convert BGR to RGB
    imgRGB = img[:,:,::-1]
    #convert to PIL format
    imgtk = Image.fromarray(imgRGB)
    #create main window
    root = Tk()
    root.title("Image Display")
    #convert to Tkinter format
    imgTk = ImageTk.PhotoImage(imgtk)
    #create a label to store and display image
    lbl = Label(root, image=imgTk)
    #pack a label to fit image
    lbl.pack()
    #lbl.image = imgTk
    root.mainloop()

ผลลัพธ์ที่ได้ก็คือ


ในทางกลับกันถ้าเราต้องการโหลดรูปด้วย PIL แต่ไปแสดงผลแบบ OpenCV กระบวนการก็จะกลับกันคือ
1. แปลงรูปให้เป็น numpy array ก่อน
2. เปลี่ยนจาก RGB ให้เป็น BGR

ลองดูโค้ดตามนี้ครับ
import cv2
from PIL import Image
import numpy as np

#load image by PIL
img = Image.open("lena.jpg")

#convert PIL image to numpy array
img = np.array(img)

#convert RGB to BGR
imgBGR = img[:,:,::-1]

#display in opencv
cv2.namedWindow("Output")
cv2.imshow("Output",imgBGR)
cv2.waitKey()
cv2.destroyAllWindows()

ผลลัพธ์ที่ได้น่าจะประมาณนี้


อ้างอิง
http://stackoverflow.com/questions/384759/pil-and-numpy

No comments:

Post a Comment