cvproject / utils.py
sompimnara's picture
Upload 7 files
a1916d2 verified
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