Professional Documents
Culture Documents
def auto_threshold(img):
m, n = img.shape
img_arr = np.array(img).flatten()
# Sử dụng hàm sort() của NumPy để sắp xếp các giá trị
điểm ảnh trong mảng theo thứ tự tăng dần
g = np.sort(img_count).astype(float)
# g * hg
g_hg = np.zeros(len(g)).astype(float)
for i in range(len(g_hg)):
g_hg[i] = g[i] * hg[i]
# mg = (1 / tg) * xichma_g_hg
mg = np.zeros(len(g)).astype(float)
for i in range(len(mg)):
mg[i] = (1 / tg[i]) * xichma_g_hg[i]
return img_new
# Prewitt
def Prewitt(threshold_img):
# Bộ lọc Prewitt theo hướng X
Prewitt_X = np.array(([-1, 0, 1],
[-1, 0, 1],
[-1, 0, 1]))
# Bộ lọc Prewitt theo hướng Y
Prewitt_Y = np.array(([-1, -1, -1],
[0, 0, 0],
[1, 1, 1]))
# Sobel
def Sobel(threshold_img):
# Lọc Sobel
# Bộ lọc Sobel theo hướng X
Sobel_X = np.array(([-1, 0, 1],
[-2, 0, 2],
[-1, 0, 1]))
# Bộ lọc Sobel theo hướng Y
Sobel_Y = np.array(([-1, -2, -1],
[0, 0, 0],
[1, 2, 1]))
return sobel_img
return new_img
def sobel(img):
x = np.array([[-1, 0, 1],
[-2, 0, 2],
[-1, 0, 1]])
y = np.array([[-1, -2, -1],
[0, 0, 0],
[1, 2, 1]])
sobel_x = convolution(img, x)
sobel_y = convolution(img, y)
sobel_img = np.sqrt(sobel_x * sobel_x) +
np.sqrt(sobel_y * sobel_y)
gradient_direction = np.arctan2(sobel_x, sobel_y)
def non_max_suppression(gradient_magnitude,
gradient_direction):
img_row, img_col = gradient_magnitude.shape
output = np.zeros(gradient_magnitude.shape)
PI = 180
return output
return output
def hysteresis(img):
img_row, img_col = img.shape
weak = 50
final_img = img.copy()
return final_img
2.2. Các ứng dụng của phương pháp phân vùng bằng biên
2.2.1. Nhận diện vùng chứa biển số xe.
2.2.1.1. Ý tượng bài toán
1. Tiền xử lý ảnh: Áp dụng các bước tiền xử lý để làm sạch ảnh và cải thiện
chất lượng ảnh. Các bước tiền xử lý có thể bao gồm làm mờ, cân bằng
histogram, điều chỉnh độ tương phản, chuyển đổi không gian màu, loại bỏ
nhiễu, v.v.
2. Phân vùng bằng biên: Sử dụng phương pháp phân vùng bằng biên, tìm
các biên cạnh trong ảnh. Các biên cạnh sẽ giúp phát hiện vùng chứa biển
số xe, vì biên cạnh của biển số thường có độ tương phản cao và sắc nét.
Ta sẽ áp dụng toán tử Prewitt, Sobel đã cài đặt ở trên để tìm biên cho
bước này.
3. Phát hiện vùng chứa biển số: Dựa trên các biên cạnh đã tìm được, áp
dụng các thuật toán phân đoạn hoặc phương pháp phát hiện vùng để xác
định vùng chứa biển số xe trong ảnh.
4. Xử lý và nhận dạng ký tự: Sau khi xác định được vùng chứa biển số xe,
áp dụng các bước xử lý và nhận dạng ký tự để trích xuất thông tin từ biển
số.
5. Post-processing: xử lý nhiễu, kiểm tra kiểu ký tự, sử dụng thông tin ngữ
cảnh,.. ảnh kết quả cuối cùng.
2.2.1.2. Áp dụng phương pháp phân vùng bằng biên để xác định vùng chứa biển
số xe.
Ta sẽ phân vùng bằng biên ảnh sử dụng Sobel, Prewitt.
• Source code
import cv2
from Sobel_Prewitt import Sobel, Prewitt, threshold
from auto_threshold import auto_threshold
img = cv2.imread("D:\Image_Processing\\biensoxe2.jpg", 0)
img = cv2.GaussianBlur(img, (5, 5), 0)
threshold_img = threshold(img, auto_threshold(img))
sobel_img = Sobel(img)
sobel_img = threshold(sobel_img, auto_threshold(sobel_img))
prewitt_img = Prewitt(threshold_img)
prewitt_img = threshold(prewitt_img,
auto_threshold(prewitt_img))
cv2.imshow("Sobel", sobel_img)
cv2.imshow("Prewitt", prewitt_img)
cv2.waitKey()
cv2.destroyAllWindows()
• Ảnh ban đầu
Hình:
• Kết quả tìm biên ảnh bằng toán tử Sobel
Hình:
• Kết quả tìm biên ảnh bằng toán tử Prewitt
Hình:
Sau khi có biên ảnh bắt đầu xác định vùng chứa biển số xe, sử hàm
cv2.findContours.
• Source code
import cv2
from Sobel_Prewitt import Sobel, threshold
from auto_threshold import auto_threshold
img = cv2.imread("D:/Image_Processing/biensoxe2.jpg")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# Làm mờ ảnh để làm giảm nhiễu
blurred_img = cv2.GaussianBlur(gray, (5, 5), 0)
threshold_img = threshold(blurred_img,
auto_threshold(blurred_img))
# Áp dụng Sobel
edges = Sobel(threshold_img)
edges = threshold(edges, auto_threshold(edges))
# Vẽ vùng chứa biển số lên ảnh gốc (đường viền màu xanh lá
cây)
if license_plate_contour is not None:
cv2.drawContours(img, [license_plate_contour], -1, (0,
255, 0), 2)
img = cv2.imread("D:\Image_Processing\\vikhuan.png", 0)
threshold_img = threshold(img, auto_threshold(img))
sobel_img = Sobel(threshold_img)
sobel_img = threshold(sobel_img, auto_threshold(sobel_img))
cv2.imshow("Sobel", sobel_img)
cv2.waitKey()
cv2.destroyAllWindows()
Hình:
• Ảnh sau khi phân vùng bằng biên
Hình:
Sau khi có được biên ảnh ta hàm cv2.findContours để đếm số lượng contours từ
đó suy ra số lượng vi khuẩn.
• Source code
import cv2
import numpy as np
from Sobel_Prewitt import Sobel, threshold
from auto_threshold import auto_threshold
# Áp dụng Sobel
edges = Sobel(gray_img)
edges = threshold(edges, auto_threshold(edges))
# Lọc các đường biên theo diện tích và hình dạng (gần hình
tròn)
min_area = 10 # Diện tích tối thiểu để loại bỏ các contour
nhỏ
circularity_threshold = 0.1 # Ngưỡng hình dạng gần tròn
count = 0
# In số lượng vi khuẩn
print("Số lượng vi khuẩn: ", count)
Hình:
Hình:
Vì sử dụng contours của ảnh biên nên số lượng vi khuẩn có thể bị tính nhầm,
hoặc không tìm được do đè, che lấp bởi môi trường. Trường hợp nhiều vi khuẩn
trùng nhau cũng khó xác định số lượng vi khuẩn. Do giới hạn đề tài nên chỉ áp
dụng cách đơn giản để minh họa. Để tăng độ chính xác nên sử dụng các phương
pháp học máy cho bước này.
2.2.3. Nhận diện khuôn mặt
2.2.3.1. Ý tượng bài toán
1. Tiền xử lý ảnh: Áp dụng các bước tiền xử lý để làm sạch ảnh và cải thiện
chất lượng ảnh. Các bước tiền xử lý có thể bao gồm làm mờ, cân bằng
histogram, điều chỉnh độ tương phản, loại bỏ nhiễu,...
2. Phân vùng bằng biên: Sử dụng phương pháp phân vùng bằng biên, tìm
các biên cạnh trong ảnh. Các biên cạnh sẽ giúp xác định các đường viền
của khuôn mặt.Trong bài toán này ta sẽ sử dụng phương pháp tìm biên
Canny.
3. Phân đoạn khuôn mặt: Dựa trên các biên cạnh đã tìm được, áp dụng các
thuật toán phân đoạn hoặc phương pháp phát hiện vùng để xác định và
phân đoạn vùng khuôn mặt trong ảnh.
4. Xử lý và nhận dạng khuôn mặt: Sau khi xác định được vùng khuôn mặt,
áp dụng các bước xử lý và nhận dạng khuôn mặt để trích xuất thông tin từ
khuôn mặt.
5. Post-processing: xử lý nhiễu, kiểm tra kiểu khuôn mặt, sử dụng thông tin
ngữ cảnh,.. ảnh kết quả cuối cùng.
Ta sẽ dùng hàm Canny ở trên.
• Source code
if __name__ == '__main__':
img = cv2.imread("D:\Image_Processing\\test1.png", 0)
new_img = non_max_suppression(gradient_magnitude,
gradient_direction)
new_img = hysteresis(new_img)
Hình:
• Ảnh kết quả sử dụng hàm Canny
Hình:
Ảnh kết quả nếu áp dụng hàm Sobel, Prewitt
Hình:
Một ví dụ khác.
• Source code
if __name__ == '__main__':
img = cv2.imread("D:\Image_Processing\cogai.jpg", 0)
new_img = non_max_suppression(gradient_magnitude,
gradient_direction)
new_img = threshold(new_img, 0.95, 0.1)
new_img = hysteresis(new_img)
Hình:
• Ảnh kết quả sử dụng hàm Canny.
Hình:
• Ảnh kết quả nếu áp dụng hàm Sobel, Prewitt
Hình:
Có thể thấy hàm Canny cho đường biên rõ nét, chi tiết hơn khi dùng hàm Sobel,
Prewitt. Đồng thời đường biên của hàm Canny cho ra mỏng hơn, và thể hiện
chính xác phạm vi đối tượng hơn nên rất phù hợp để áp dụng vào bài toán nhận
diện khuôn mặt- bài toán yêu cầu xác định chính xác các đối tượng.
Sau khi có chính xác ví trị đối tượng, ta sẽ dùng những phương pháp học máy
để nhận dạng khuôn mặt để trích xuất thông tin từ vùng đối tượng đã xác định.