กระบวนการทํา inpainting คือเทคนิคตกแต่งภาพส่วนที่เสียหาย โดยการเติมข้อมูลที่สังเคราะห์จากข้อมูลบริเวณโดยรอบเรามาดูวิธีการผ่าน Python OpenCV กัน
เอาจริงๆ เพิ่งเห็น Email Alert บน PyImageSearch แล้วนึกได้ว่าเออเทคนิคนี้เคยทำสมัยเรียน ตอน ป.โท แล้วทำไม่ได้ (แป่ววววววว) มารื้อฟื่นตัวอย่างในเว็บเค้าดู แล้วรู้สึกว่ายากไปนิดก็เลย Simple Code ให้ใหม่จะได้ย่อยและเข้าถึงได้ง่ายสำหรับใครที่อยากทดลองดู
บทเรียน ก่อนหน้า ที่ควรศึกษาร่วมกัน:
- การทำ Face Detection บน Video ด้วย Python และ OpenCV
- Python กับ OpenCV ดึงฐานข้อมูล Face Recognition ผ่านระบบ Firebase
- Object Detection ตรวจจับวัตถุด้วย Python และ TensorFlow ร่วมกับ MatplotLib
- Face Recognition การเปรียบเทียบใบหน้าจากรูปภาพด้วย Python
เป็นบทเรียนการทำ Image Processing กันอีกรอบครับกับ Python และ OpenCV คราวนี้เราจะมาลองเทคนิคประมวลผลภาพเพื่อซ่อมแซมภาพถ่ายที่เสียหาย หรือสูญหายซึ่งเรียกว่าการ Inpainting โดยเราจะทำผ่าน Python กัน ซึ่งอยากให้ทุกคนดาวน์โหลดตัวอย่างภาพต่อไปนี้ครับ
Download ตัวอย่างภาพที่ใช้ทดสอบกับบทเรียนนี้ คลิกที่นี่: Download
ตัวอย่างแรกเราต้องนำภาพที่เสียหายมาใช้ก่อนซึ่งผมเตรียมไว้แล้ว (เราจำเป็นต้องเอา Mask โดยการแก้ไขลอยที่เสียหายมาทำ Processing ซึ่งใช้ OpenCV invert ขาวดำเอาจะได้แบบตัวอย่าง (ขาว ดำ) บางคนก็ใช้ Photoshop เอาก็ได้นะ แต่ถ้าจะเทพควรใช้ image processing trace ค่ารอยออกมาบนพื้นดำ
ตัวอย่างแรกให้แตก zip ไฟล์ออกมาใช้ Picture.png ภาพที่มีรอยขาด และ tearmask.png คือภาพที่ trace สีเป็นรอยอย่างเดียวบนพื้นดำ
สร้างไฟล์ Python ขึ้นมาตั้งชื่อว่า inpaint.py แล้วทำการประกาศ Header ดังนี้:
import cv2 flags = cv2.INPAINT_TELEA
ซึ่งค่า flags นั้นจะมีเทคนิคอยู่สองแบบ คือแบบวิธี fast marching เรียกใช้งานโดยคำสั่ง INPAINT_TELSA (วิธีการเดินเร็ว ตามชื่อ) เป็นวิธีการคำนวณเลขที่สร้างขึ้นโดย James Sethian เน้นความสัมพันธ์ฟังก์ชันของเวลาด้วยความเร็วในทิศทางปกติ ขึ้นตรงกับ จุดบนพื้นผิวแต่ละบริเวณที่เสียหายจะถูกคํานวณหาระยะทางระหวางจุดที่อยู่ใกล้สุดแล้วค่อยทำงานต่อไปยังลำดับชั้นถัดไป [1]
แต่ถ้าใช้อีกวิธี
import cv2 flags = cv2.INPAINT_NS
ค่า flags สามารถเลือกเป็น INPAINT_NS ซึ่ง NS ก็มาจากเทคนิค Dynamic Fluid การไหลไม่สมบูรณ์ของ สมการนาเวียร์-สโตกส์ (Navier Stokes) เป็นการคำนวณตำแหน่งโดยรอบเช่นกัน เพียงแค่การคำนวณนั้นเป็นรูปแบบอนุพันธ์ย่อยที่ไม่เป็นเส้นตรง (non-linear) มีค่าความปรวนแปรเข้ามาช่วยในการประมวลผล จำลองกระบวนการเหมือนของเหลวไหลจาก พื้นที่ (region) ที่รู้จักไปยัง พื้นที่ (region) ที่ไม่รู้จัก [2]
ปล. เอาไว้ว่างๆ จะมาเปรียบเทียบให้ครับ แนบ References ให้แล้วลองไปอ่านดู ในเว็บต้นทางเค้าก็อธิบายไว้นะว่าเลือกใช้อะไรดี
ตอนนี้ของใช้แบบ TELEA ก่อน
ให้เรา Read ภาพที่เราจะใช้เข้าไปในตัวแปร image ชื่อ “Picture.png” ก่อน:
image = cv2.imread("images/Picture.png")
หลังจากนั้น read ค่ mask จากภาพ “tearmask.png” อย่าลืมเข้ารหัส BRG2GRAY
mask = cv2.imread("images/tearmask.png") mask = cv2.cvtColor(mask, cv2.COLOR_BGR2GRAY)
นำมาประมวลผลด้วยฟังก์ชัน inpaint()
output = cv2.inpaint(image, mask, 3, flags=flags)
ค่า 3 คือ radius เป็นรัศมีในการปรับฟื้นฟูภาพ สามารถปรับเลขได้ครับ ตอนนี้ใส่ 3 ก่อน ส่วน flags = จะไปเรียกตัวแปร floag ซึ่งเราเลือกแบบ cv2.INPAINT_TELEA ไปจะใช้แบบ NS (Navier Stokes) ก็ได้นะครับ
cv2.imshow("Image", image) cv2.imshow("Mask", mask) cv2.imshow("Output", output) cv2.waitKey(0)
ข้างบนคือแสดงผลภาพหลังประมวลผล (กด run) ดูจะเห็นโปรแกรมจะเรียกขึ้นมา 3 ภาพให้เราเห็นผ่านคำสั่ง
ทีนี้ลองภาพของตัวเองบ้าง ก็เปลี่ยนจาก Picture.png เป็น banyapon.png และ tearmask.png เป็น mask.png
ภาพmask.pngใช้เทคนิค theadhold ให้เป็น masking เพื่อจะลบ Sticker บนแล็ปท๊อปออก
import cv2 #flags = cv2.INPAINT_TELEA flags = cv2.INPAINT_NS image = cv2.imread("images/banyapon.png") mask = cv2.imread("images/mask.png") mask = cv2.cvtColor(mask, cv2.COLOR_BGR2GRAY) output = cv2.inpaint(image, mask, 3, flags=flags) cv2.imshow("Image", image) cv2.imshow("Mask", mask) cv2.imshow("Output", output) cv2.waitKey(0)
รันดูหน่อยแบบ Navier Stokes
ลบออกไปอยู่ที่วง Raduis และเทคนิคแล้วว่าแบบไหนเวิร์ค เพราะนี่มันเล่นลบแบบหยาบๆ ไปหน่อย ลองไปศึกษาดูครับ
ปล. ตัวอย่างของ PyImageSearch ค่อนข้างครบอธิบายดี แต่ยากไม่เหมาะกับมือใหม่ ผม Simple ให้แล้วทีนี้ก็ไปศึกษาของที่ Advance ได้ที่ PyImageSearch ต่อเลยครับ
[2] cv2.INPAINT_NS : Navier-stokes, Fluid dynamics, and image and video inpainting (Bertalmío et al., 2001)
One Comment