Spaces:
Sleeping
Sleeping
| import numpy as np | |
| import cv2 | |
| # --- 1. Convolution 2D (พื้นฐานของ Blur และ Sobel) --- | |
| def convolution2d(image, kernel): | |
| """ | |
| ทำ Convolution ระหว่างภาพกับ Kernel | |
| """ | |
| # ดึงขนาดภาพและ Kernel | |
| image_h, image_w = image.shape | |
| kernel_h, kernel_w = kernel.shape | |
| # คำนวณ Padding (เพื่อให้ภาพผลลัพธ์ขนาดเท่าเดิม) | |
| pad_h = kernel_h // 2 | |
| pad_w = kernel_w // 2 | |
| # สร้างภาพที่มี Padding (ใช้ขอบเป็น 0) | |
| padded_image = np.pad(image, ((pad_h, pad_h), (pad_w, pad_w)), mode='constant') | |
| output = np.zeros_like(image) | |
| # วนลูป (Vectorized way เพื่อความเร็วที่ดีกว่า Loop ปกติ) | |
| # หมายเหตุ: การเขียน Loop ซ้อนกัน 2 ชั้นใน Python จะช้ามาก | |
| # ตรงนี้จึงขอใช้ Numpy ช่วยในการคูณ Matrix เพื่อประสิทธิภาพ | |
| for y in range(image_h): | |
| for x in range(image_w): | |
| # ตัดส่วนของภาพที่ตรงกับ Kernel | |
| roi = padded_image[y:y+kernel_h, x:x+kernel_w] | |
| # คูณกันแล้วหาผลรวม (Element-wise multiplication & Sum) | |
| k = (roi * kernel).sum() | |
| output[y, x] = k | |
| return output | |
| def gaussian_kernel(size=5, sigma=1.0): | |
| """ สร้าง Gaussian Kernel สำหรับทำ Smoothing """ | |
| ax = np.linspace(-(size - 1) / 2., (size - 1) / 2., size) | |
| xx, yy = np.meshgrid(ax, ax) | |
| kernel = np.exp(-0.5 * (np.square(xx) + np.square(yy)) / np.square(sigma)) | |
| return kernel / np.sum(kernel) | |
| # --- 2. Sobel Edge Detection (เขียนเอง) --- | |
| def sobel_edge_detection(image): | |
| # Kernel ของ Sobel แกน X และ Y | |
| Kx = np.array([[-1, 0, 1], | |
| [-2, 0, 2], | |
| [-1, 0, 1]], dtype=np.float32) | |
| Ky = np.array([[-1, -2, -1], | |
| [0, 0, 0], | |
| [1, 2, 1]], dtype=np.float32) | |
| # ทำ Convolution | |
| Ix = convolution2d(image, Kx) | |
| Iy = convolution2d(image, Ky) | |
| # คำนวณความแรงของขอบ (Gradient Magnitude) | |
| G = np.sqrt(Ix**2 + Iy**2) | |
| # Normalize ให้ค่าอยู่ช่วง 0-255 | |
| G = (G / G.max()) * 255 | |
| return G.astype(np.uint8) | |
| # --- 3. Threshold (เขียนเอง) --- | |
| def manual_threshold(image, thresh_value=100): | |
| """ เปลี่ยนภาพเป็น Binary (ขาว-ดำ) ตามค่า Threshold """ | |
| binary_image = np.zeros_like(image) | |
| # ถ้า pixel ไหนค่ามากกว่า thresh_value ให้เป็น 255 (ขาว) นอกนั้น 0 (ดำ) | |
| binary_image[image > thresh_value] = 255 | |
| return binary_image | |
| # --- 4. Morphology - Dilation (เขียนเอง) --- | |
| def manual_dilation(image, kernel_size=3): | |
| """ ขยายเส้นขอบให้หนาขึ้น (เชื่อมเส้นที่ขาด) """ | |
| h, w = image.shape | |
| pad = kernel_size // 2 | |
| padded_image = np.pad(image, ((pad, pad), (pad, pad)), mode='constant') | |
| output = np.zeros_like(image) | |
| # หลักการ Dilation: เลือกค่าที่ "มากที่สุด" ในหน้าต่าง Kernel | |
| for y in range(h): | |
| for x in range(w): | |
| roi = padded_image[y:y+kernel_size, x:x+kernel_size] | |
| output[y, x] = np.max(roi) | |
| return output | |
| # --- 5. จัดเรียงจุดมุม (Perspective Transform Helper) --- | |
| def order_points(pts): | |
| # (โค้ดเดิมที่เขียนเองถูกต้องแล้ว) | |
| rect = np.zeros((4, 2), dtype="float32") | |
| # บนซ้าย (ผลบวกน้อยสุด) / ล่างขวา (ผลบวกมากสุด) | |
| s = pts.sum(axis=1) | |
| rect[0] = pts[np.argmin(s)] | |
| rect[2] = pts[np.argmax(s)] | |
| # บนขวา (ผลต่างน้อยสุด) / ล่างซ้าย (ผลต่างมากสุด) | |
| diff = np.diff(pts, axis=1) | |
| rect[1] = pts[np.argmin(diff)] | |
| rect[3] = pts[np.argmax(diff)] | |
| return rect | |
| def four_point_transform(image, pts): | |
| rect = order_points(pts) | |
| (tl, tr, br, bl) = rect | |
| # คำนวณความกว้าง | |
| widthA = np.sqrt(((br[0] - bl[0]) ** 2) + ((br[1] - bl[1]) ** 2)) | |
| widthB = np.sqrt(((tr[0] - tl[0]) ** 2) + ((tr[1] - tl[1]) ** 2)) | |
| maxWidth = max(int(widthA), int(widthB)) | |
| # คำนวณความสูง | |
| heightA = np.sqrt(((tr[0] - br[0]) ** 2) + ((tr[1] - br[1]) ** 2)) | |
| heightB = np.sqrt(((tl[0] - bl[0]) ** 2) + ((tl[1] - bl[1]) ** 2)) | |
| maxHeight = max(int(heightA), int(heightB)) | |
| dst = np.array([ | |
| [0, 0], | |
| [maxWidth - 1, 0], | |
| [maxWidth - 1, maxHeight - 1], | |
| [0, maxHeight - 1]], dtype="float32") | |
| M = cv2.getPerspectiveTransform(rect, dst) | |
| warped = cv2.warpPerspective(image, M, (maxWidth, maxHeight)) | |
| return warped |