PHÁT HIỆN ĐƯỜNG THẲNG SỬ DỤNG THUẬT TOÁN HOUGH TRANSFORM

20 29 0
PHÁT HIỆN ĐƯỜNG THẲNG SỬ DỤNG THUẬT TOÁN HOUGH TRANSFORM

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

Thông tin tài liệu

ĐẠI HỌC QUỐC GIA THÀNH PHỐ HỒ CHÍ MINH TRƯỜNG ĐẠI HỌC BÁCH KHOA  BÁO CÁO BÀI TẬP LỚN: NHẬP MƠN THỊ GIÁC MÁY TÍNH Đề tài: PHÁT HIỆN ĐƯỜNG THẲNG SỬ DỤNG THUẬT TOÁN HOUGH TRANSFORM GVHD: Lê Thanh Hải Nhóm: STT Họ tên lót Phạm Anh Nguyễn Minh Tên Đạt Cường MSSV 1911025 1912512 TP HCM, ngày 28 tháng 11 năm 2021 Mục lục: A Thuật toán phát đường thẳng Hough Transform: Giới thiệu thuật toán Hough Transform: 2 Lý thuyết: 2.1 Tiền xử lý 2.2 Bình chọn đường thẳng B Thuật toán phát biên dùng thuật toán Canny: Giới thiệu thuật toán Canny Edge Detector: Các bước thực thuật toán 2.1 Lọc nhiễu 2.2 Tính gradient ảnh 2.3 Loại bỏ giá trị không cực đại 2.4 Chọn biên đối tượng ảnh C Thực code: Code Kết 17 Đánh giá kết 18 Tài liệu tham khảo 19 A Thuật toán phát đường thẳng dùng Hough Transform Giới thiệu thuật toán Hough Transform: Hough Transform kĩ thuật dùng dùng xử lý ảnh kỹ thuật số nhằm tách đối tượng ảnh Mục đích thuật tốn dùng để xác định cạnh đối tượng cạnh đối tượng có khả chuyển đổi thành phương trình tốn học Nó có khả dò cạnh đối tượng kể cạnh bị số pixel q trình tiền xử lý đây, nhóm chúng em sử dụng thuật tốn Hough Transform để dị cạnh đối tượng dạng đường thẳng Lý thuyết: Như biết, đường thẳng đại diện phương trình bâc nhất, biểu diễn theo hai tham số a b sau: 𝑦 = 𝑎𝑥 + 𝑏 Đây phương trình đường thẳng Tuy nhiên, ta sử dụng phương trình cho việc tính tốn đường thẳng qua điểm có vấn đề xảy ra, số lượng giá trị a tạo lớn đến vơ Như vậy, việc tính tốn bất khả thi sử dụng phương trình đường thẳng Thay vào đó, ta sử dụng hệ trục tọa độ cực để biểu diễn phương trình đường thẳng: 𝜌 = 𝑥 cos 𝜃 + 𝑦 sin 𝜃 Với cách biểu diễn này, ta thấy giá trị góc 𝜃 bị chặn nửa khoảng [ ; 𝜋 ] Không thế, không gian ảnh không gian hữu hạn (các giá trị chiều cao rộng ảnh hữu hạn), giá trị 𝜌 hữu hạn Có thể thấy, việc sử dụng phương trình đường thẳng vơ thích hợp với thuật tốn Hough Transform Từ đường thằng khơng gian ảnh với hai tham số 𝜌 𝜃, định vị sang không gian Hough (Hough space) ta thu điểm Còn từ điểm khơng gian ảnh, có tọa độ (x,y), ta lại thu hình sin định vị khơng gian Hough Các điểm nằm đường thẳng biểu diễn hình sin giao điểm khơng gian Hough Dựa vào đây, thuật tốn Hough Transform chọn phương trình đường thẳng qua nhiều điểm thơng qua việc bình chọn Tuy nhiên, thực tế, ảnh thường có nhiều cạnh, vậy, việc lấy đường thẳng có số pixel qua nhiều khơng phù hợp, thay vào đó, đặt ngưỡng số lượng pixel định, ngưỡng xem đường thẳng ngược lại Như thuật toán này, bước để thực thuật tốn sau: 2.1 Tiền xử lý: Để thu đường thẳng mong muốn, ảnh cần phải xử lý trước thực thuật toán Hough Transform Để xác định đường thẳng đối tượng, ta áp dụng thuật toán Canny để lọc biên Việc lọc biên loại bỏ nhiễu, tạo thành ảnh nhị phân làm đầu vào cho thuật tốn, nhờ giới hạn số đường thẳng cần xét 2.2 Bình chọn đường thẳng: Ta chia không gian Hough thành lưới ô vuông nhỏ Ta thu lưới ô vuông (ma trận) với hàng trục 𝜌 cột trục 𝜃 Độ xác thuật tốn phụ thuộc vào số lượng ô vuông ta chọn cho cạnh (độ chia 𝜃), ta chọn cột 1° ta có số lượng hàng 180 độ Đối với 𝜌, khoảng cách lớn độ dài đường chéo ảnh, chúng chọn độ xác 𝜌 pixel số hàng độ dài đường chéo ảnh theo đơn vị pixel Giá trị vị trí ma trận ban đầu đặt Ta tiến hành xét điểm đầu vào điểm ảnh thu sử dụng lọc biên Canny, với điểm sáng này, ta xét 𝜃 khoảng [ ; 180 ] Mỗi điểm sáng có tọa độ (x,y), nên ta dễ dàng tính 𝜌 Với cặp (𝜌, 𝜃) ta thực bình chọn (mỗi bình chọn giá trị vị trí tăng thêm 1) Cuối cùng, ta thực lấy ngưỡng để xác định đường thẳng đường thẳng ảnh thực tế B Thuật toán phát biên Canny Edge Detector: Đối với thuật tốn Hough Transform, để xác định đường thẳng có ảnh, ta cần phải tìm biên đối tượng Bởi vì, có biên (cạnh) đối tượng tạo đường thẳng đủ lớn để nhận dạng Do vậy, cần phải có bước xử lý ảnh đầu vào (tiền xử lý) để tạo đường ta coi biên đối tượng Để làm việc này, thuật toán Canny thuật toán sử dụng để tìm biên phổ biến Giới thiệu thuật tốn Canny Edge Detector: Thuật toán phát biên theo phương pháp Canny phương pháp phát biên trực tiếp vật thể (Object) ảnh, áp dụng hiệu ảnh có nhiễu Phương pháp John F Canny phát triển vào năm 1986, ông thực phương pháp đưa giải thích cách thức hoạt động thuật toán Các bước thực thuật toán: 2.1 Lọc nhiễu: Nhiễu định nghĩa xử lý ảnh điểm ảnh có giá trị độ xám trội so với cục bộ, tức chênh lệch lớn so với điểm ảnh lân cận Bởi thuật tốn tìm cạnh Canny khơng kết mong muốn nhiễu, nên bước đầu tiên, để tìm cạnh vật thể cách xác, ta cần tiến hành lọc nhiễu cho ảnh Trong thuật toán này, ta lọc nhiễu với lọc Gaussian 2D Bộ lọc Gaussian 2D sử dụng công thức sau để tìm thành phần mặt nạ Gaussian: 2 𝑖 +𝑗 ) −( ℎ (𝑖, 𝑗) = 𝑒 2𝜎2 2𝜋𝜎 Trong đó: i,j hàng cột ma trận Gaussian với giá trị: h(-2,-2) h(-1,-2) h(-2,-1) h(-1,-1) h(-2,0) h(-1,0) h(-2,1) h(-1,1) h(-2,2) h(-1,2) h(0,-2) h(0,-1) h(0,0) h(0,1) h(0,2) h(1,-2) h(1,-1) h(1,0) h(1,1) h(2,-2) h(2,-1) h(2,0) h(2,1) Để triển khai ma trận Gaussian, ta tính trực tiếp từ: h(1,2) h(2,2) ℎ(𝑖, 𝑗) = 𝑘 −( 𝑖 +𝑗 ) −( 𝑒 2𝜎2 𝑖2 +𝑗2 ) 2𝜎2 Với c số, ta tính 𝑒 , tính ma trận Gaussian Phương pháp tính ma trận Gaussian triên khai theo sách Machine Vision, chương (trang 133 - 134) Làm mờ ảnh với ma trận Gaussian vừa tìm được: Ta sử dụng công thức: 2 𝑖 +𝑗 ) −( 𝑔(𝑖, 𝑗) = ∑ ∑ 𝑒 2𝜎2 𝑓(𝑖 − 𝑚, 𝑗 − 𝑛) 𝑠 Với 𝑔(𝑖, 𝑗) “pixel trung tâm” (current pixel) ta tiến hành nhân ma trận gồm “pixel hàng xóm” (neighbor pixel) với ma trận mặt nạ Gaussian Sau thực hết với current pixel ảnh, ta nhận ảnh làm mờ 2.2 Tính Gradient ảnh (Finding Intensity Gradient of the Image): Gradient hình ảnh đo lường cách thức thay đổi cường độ ánh sáng ảnh Nó cung cấp hai thông tin quan trọng: độ lớn gradient (magitude of gradient) cho ta biết tốc độ thay đổi cường độ sáng ảnh, hướng gradient (direction of gradient) cho ta biết hướng mà ảnh thay đổi nhanh Một cạnh hình nằm nhiều hướng khác nhau, đó, thuật toán Canny, người ta sử dụng lọc để nhận biết đường nằm ngang, dọc chéo từ ảnh lọc nhiễu để xác định cạnh vật thể (vị trí có cường độ sáng chênh lệch nhiều) Như biết, phương pháp Gradient phương pháp dò biên cục dựa vào cực đại đạo hàm, phương pháp đạo hàm bậc Chính ta thực việc đạo hàm bước hai cách nhân ảnh kết G lọc nhiễu với mặt nạ phương pháp Gradient dựa theo toán tử Sobel, Pixel Difference Trong thuật toán Canny, ta tiến hành nhân xoắn ảnh G với hai mặt nạ phương pháp Sobel theo hai hướng x y sau: Ma trận Sobel: Sau tiến hành tính độ lớn theo phương x phương y, ta tổng hợp hai kết để kết qua cuối theo công thức: 𝐺′ = √𝐺𝑥2 + 𝐺𝑦2 Hướng cạnh tính sau: 𝑎𝑛𝑔𝑙𝑒 (𝜃 ) = atan 𝐺𝑦 𝐺𝑥 Ảnh G’ mà ta tính góc 𝜃 kết bước 2.3 Loại bỏ giá trị không cực đại (Non – maximum Suppresion): Non – maximum Suppresion tức bỏ cạnh dư thừa, sau tìm cạnh với gradient, số cạnh có độ rộng tương đối lớn Như vậy, ta cần phải có bước tiến hành loại bỏ phần cạnh dư thừa Ở bước này, tiến hành giữ lại pixel thuộc cạnh mà có độ gradient lớn Đầu tiên, để giữ lại pixel có gradient lớn nhất, ta cần phải biết gradient nằm thuộc đường cạnh cạnh mà lọc Với giá trị góc 𝜃 mà ta tìm tính gradient, ta dễ dàng tìm cạnh hướng mà pixel có thay đổi lớn Tuy nhiên, giá trị góc 𝜃 tìm giá trị bất thuộc khoảng từ đến 180 độ, các pixel nằm cạnh (ma trận ảnh bao gồm điểm ảnh xếp kề nhau) thuộc góc 0° , 45°, 90° 135° Vậy, ta cần phải đưa góc 𝜃 góc này, việc ta cần làm đưa khoảng định mà góc 𝜃 tính thuộc khoảng khoảng đưa góc Bước thứ hai trình ta phải tìm cạnh mà ta tạo được, đâu vị trí pixel đại diện cho cạnh tìm được, sau tính gradient cạnh mà ta xác định chứa phần không cần thiết (phần thừa) Để tìm pixel đại diện này, ta tiến hành qt tồn hình tìm đâu pixel có cường độ sáng lớn pixel hàng xóm (neighbor pixel) Việc quét pixel cần phải dựa cạnh mà pixel thuộc thông qua góc 𝜃 mà ta xác định Như hình trên, A điêm thuộc cạnh xét với điểm B C xem có phải có phải lớn nhất, lớn nhất, A giữ lại ngược lại vậy, sau bước ta thu ảnh có cạnh làm mỏng (thin) 2.4 Chọn biên đối tượng ảnh (Hysteresis Thresholding): Sau làm chọn pixel đại diện cho cạnh mà ta dò được, ta thu nhiều cạnh, có cạnh nhiễu lớn Như vậy, cần phải xác định đâu cạnh thật đối tượng bên ảnh Như ta biết, xử lý ảnh, cạnh đối tượng xác định chênh lệch cường độ sáng, điểm ảnh có gradient lớn (sự chênh lệch cường độ sáng rõ rệt) thường có xác suất cạnh thật đối tượng cao Do đó, để xác định cạnh này, ta dùng lọc ngưỡng Tuy nhiên, dùng ngưỡng có khả xảy sai sót lớn trình tìm cạnh, nên thuật tốn Canny sử dụng lọc hai ngưỡng Khi đó, pixel có gradient lớn ngưỡng (upperthreshold), ta xác nhận điểm thuộc cạnh đối tượng, giá trị bé ngưỡng (lowertheshold), ta xác nhận cạnh đối tượng ảnh Trong trường hợp gradient điểm ảnh có giá trị nằm ngưỡng ngưỡng dưới, tính điểm biên điểm liền kề có giá trị lớn ngưỡng Ta hiểu rõ bước thơng qua hình ảnh sau: Trong hình này,cạnh A có giá trị lớn ngưỡng (maxVal), nên xác nhận cạnh đối tượng Cạnh C nằm ngưỡng trên, nhiên, nối liền với cạnh A cạnh đối tượng, nên ta xét cạnh C cạnh đối tượng Trong đó, canh B nằm ngưỡng dưới, lại khơng có liên kết với cạnh nên ta xác địn C không cạnh Và nhờ việc lọc ngưỡng vậy, pixel nhiễu không thuộc đường thẳng loại bỏ C Thực code: Trên phần lý thuyết có liên quan trực tiếp đến việc lập trình xử lý ảnh Đối với tập lớn này, nhóm chúng em dị cạnh đường thẳng vật thể sử dụng thuật tốn Hough Transform thơng qua việc sử dụng ngơn ngữ lập trình Python với thư viện dùng việc đọc ảnh đầu vào sử dụng bước tiền xử lý Trong đó, thuật tốn Canny dùng để cung cấp ảnh nhị phân đầu vào cho Hough Transform Trong đoạn chương trình lập trình này, nhóm chúng em đưa ảnh màu input vào để tính tốn thơng qua việc sửa đổi dòng lệnh đọc ảnh đoạn code Code: import matplotlib.pyplot as plt import numpy as np import imageio from scipy import ndimage import cv2 # chuyển ảnh rgb sang gray với công thức cường độ sáng ảnh gray: gray = 0.2989*r + 0.5870*g + 0.1140*b def rgb2gray(img) : return np.dot(img[ , :3], [0.2989, 0.5870, 0.1140]) def gaussian_kernel(size, sigma): # tạo ma trận Gaussian có kích thước theo u cầu g = np.zeros(shape=(size, size)) # lấy kích thước ma trận chia lấy phần ngun để tìm giá trị theo cơng thức m=size//2 # tạo biến tống s = nhằm tính tổng phần tử ma trận g s=0 # tính giá trị vị trí dòng lặp for for i in range(size): for j in range (size): g[i,j]=round( np.exp((-((i-m)**2 + (j-m)**2)/(2*sigma**2))),3) # làm tròn chữ số sau dấu phẩy # tạo biến k giá trị mà lấy chia cho giá trị vị trí h (-2, -2) làm tròn đến số nguyên k = round((1 / g [0,0])) # với số k vừa tìm được, ta nhân với ma trận g để tính phần tử số nguyên for i in range(size): for j in range (size): g[i,j] = round(g[i,j]*k) s+=g[i,j] return g,s # Phương pháp tính ma trận dựa theo sách Machine Vision chương (trang 133 - 134): # www.cse.usf.edu/%7Er1k/MachineVisionBook/MachineVision.files/MachineVision_Cha pter4.pdf def gaussian_filter(img,size,sigma): # tìm kích thước ảnh gray h = img.shape[0] w = img.shape[1] # tính ma trận Gaussian tổng S phần tử ma trận g,s=gaussian_kernel(size,sigma) # tạo kích thước số nguyên ma trận kernel size = size // # tạo biến s = để tính tổng phần tử nhân ma trận để gán cho current pixel sum = # tạo padding cho ảnh với kích thước phần padding nửa kích thước ma trận kernel # tạo padding có giá trị cường độ sáng với vùng biên ảnh # tạo duplicate padding nhằm tránh làm mờ, ta gặp đường thẳng tạo # pixel gần vùng biên ma thực làm mờ khơng xét đến pixel tính biên blank = cv2.copyMakeBorder(img, size,size,size,size,cv2.BORDER_REPLICATE) # tạo ảnh có kích thước ảnh đầu vào blank2=img # chạy vịng lặp để tính pixel gán cho blank2 for x in range(h): for y in range( w ): # khởi tạo lại biến sum = cho current pixel sum = # vòng lặp nhân với ma trận kernel for i in range (-size,size + 1): for j in range (-size, size + 1): # bước tính ma trận kernel, ta tạo gia trị số nguyên, # nên ta phải chia lại cho tổng giá trị ma trận kernel sum += blank[x - i, y - j]*g[i + size, j + size]/s # gán giá trị current pixel giá trị tổng nhân với ma trận kernel blank2[x , y] = sum return blank2 # bước tính nhân xoắn ma trận Sobel giống với Gaussian filter nên nhóm em # sử dụng hàm có thư viện để tính nhanh bước 10 # tìm giá trị Gx cách nhân xoắn ảnh lọc nhiễu với ma trận Sobel theo phương x def gradient_x(img) : grad_img = ndimage.convolve(img, np.array([[-1, 0, 1],[-2, 0, 2],[-1, 0, 1]])) return grad_img # tìm giá trị Gy cách nhân xoắn ảnh lọc nhiễu với ma trận Sobel theo phương y def gradient_y(img) : grad_img = ndimage.convolve(img, np.array([[-1, -2, -1],[0, 0, 0],[1, 2, 1]])) return grad_img # tìm giá trị magitude of gradient theo công thức def gradient_mag(fx, fy) : # hàm numpy.hypot hàm lấy tổng bình phương fx, fy grad_mag = np.hypot(fx, fy) return grad_mag # đưa hướng gradient điểm ảnh góc bản: def closest_dir_function(grad_dir) : closest_dir_arr = np.zeros(grad_dir.shape) for i in range(1, int(grad_dir.shape[0] - 1)) : for j in range(1, int(grad_dir.shape[1] - 1)) : # (theta < -22.5 theta < 22.5) (theta 157.5) theta = if((grad_dir[i, j] > -22.5 and grad_dir[i, j] 22.5 theta 22.5 and grad_dir[i, j] 67.5 theta 67.5 and grad_dir[i, j] grad_mag[i, j+1]) and (grad_mag[i, j] > grad_mag[i, j-1])) : thinned_output[i, j] = grad_mag[i, j] else : thinned_output[i, j] = elif(closest_dir[i, j] == 45) : if((grad_mag[i, j] > grad_mag[i+1, j+1]) and (grad_mag[i, j] > grad_mag[i-1, j-1])) : thinned_output[i, j] = grad_mag[i, j] else : thinned_output[i, j] = elif(closest_dir[i, j] == 90) : if((grad_mag[i, j] > grad_mag[i+1, j]) and (grad_mag[i, j] > grad_mag[i-1, j])) : thinned_output[i, j] = grad_mag[i, j] else : thinned_output[i, j] = else : if((grad_mag[i, j] > grad_mag[i+1, j-1]) and (grad_mag[i, j] > grad_mag[i-1, j+1])) : thinned_output[i, j] = grad_mag[i, j] else : thinned_output[i, j] = return thinned_output/np.max(thinned_output) # Xét điểm xung quanh pixel có ngưỡng gradient nằm ngưỡng ngưỡng def DFS(img) : for i in range(1, int(img.shape[0] - 1)) : for j in range(1, int(img.shape[1] - 1)) : # Nếu giá trị vị trí if(img[i, j] == 1) : 12 # ta xét giá trị xung quanh nó, có vị trí có giá trị (strong edge) # ta đặt giá trị t_max = max(img[i-1, j-1], img[i-1, j], img[i-1, j+1], img[i, j-1], img[i, j+1], img[i+1, j-1], img[i+1, j], img[i+1, j+1]) if(t_max == 2) : img[i, j] = # Hysteresis Thresholding # Trong bước này, nhằm tránh việc đặt ngưỡng cách ngẫu nhiên dẫn đến kết sai lệch # nên ta tiến hành đặt ngưỡng dựa theo độ lớn gradient mà ta tính def hysteresis_thresholding(img) : low_ratio = 0.1 high_ratio = 0.30 # Tính khoảng mà giá trị gradient ảnh thuộc diff = np.max(img) - np.min(img) # Chọn ngưỡng xét cách lấy giá trị nhỏ cộng với tích hệ số nhân với độ lớn khoảng giá trị t_low = np.min(img) + low_ratio * diff t_high = np.min(img) + high_ratio * diff # Tạo biến để lưu trữ xét temp_img = np.copy(img) # Xét giá trị pixel, Non maximum Suppresion không xét giá trị biên nên ta không xét for i in range(1, int(img.shape[0] - 1)) : for j in range(1, int(img.shape[1] - 1)) : # Đối với pixel có gradient ngưỡng trên, ta đặt giá trị if(img[i, j] > t_high) : temp_img[i, j] = # Đối với pixel có gradient ngưỡng dưới, ta đặt giá trị elif(img[i, j] < t_low) : temp_img[i, j] = # Đối với pixel có gradient nằm hai ngưỡng, ta đặt giá trị else : temp_img[i, j] = # Tiến hành nối pixel có gradient nằm ngưỡng vào nối với cạnh mạnh (temp_img[]=2) # Lập biến để làm cột mốc ta quét ảnh tổng giá trị strong pixel total_strong = np.sum(temp_img == 2) 13 # Ở đây, ta sử dụng vòng lặp while(True) để xác đạt điều kiện cột mốc thay đổi # tổng số strong pixel khỏi vịng lặp # Giải thích phải sử dụng vòng lặp bước này: # - sau lọc ngưỡng, nhận nhiều pixel có giá trị nằm ngưỡng # - nhiều pixel số pixel không kết nối trực tiếp với strong pixel nằm cạnh # - qua nhiêu bước lặp lại đến khơng cịn nối weak pixel với cạnh ta khỏi vịng lặp while(1) : DFS(temp_img) if(total_strong == np.sum(temp_img == 2)) : break total_strong = np.sum(temp_img == 2) # Loại bỏ pixel có giá trị ngưỡng mà không kết nối với cạnh for i in range(1, int(temp_img.shape[0] - 1)) : for j in range(1, int(temp_img.shape[1] - 1)) : if(temp_img[i, j] == 1) : temp_img[i, j] = # Đưa pixel giá trị thuộc (0,1) để thể ảnh temp_img = temp_img/np.max(temp_img) return temp_img # Dò đường thẳng sử dụng Hough Transform # Trong hàm này, thông số đầu vào gồm ảnh đầu vào áp dụng thuật toán Canny, độ phân giải rho, độ phân giải góc theta ta mặc định để có 181 giá trị theta (0

Ngày đăng: 06/12/2021, 11:25

Tài liệu cùng người dùng

  • Đang cập nhật ...

Tài liệu liên quan