TRƯỜNG ĐẠI HỌC HẢNG HẢI VIỆT NAMKHOA CÔNG NGHỆ THÔNG TIN ---***---BÁO CÁO BÀI TẬP LỚN HỌC PHẦN “NHẬN DIỆN VÀ XỬ LÝ ẢNH” Đề tài: Xây dựng chương trình nhận dạng biển báo giao thông GVHD:
Trang 1TRƯỜNG ĐẠI HỌC HẢNG HẢI VIỆT NAM
KHOA CÔNG NGHỆ THÔNG TIN
-*** -BÁO CÁO BÀI TẬP LỚN HỌC PHẦN “NHẬN DIỆN VÀ XỬ LÝ ẢNH”
Đề tài:
Xây dựng chương trình nhận dạng biển báo giao thông
GVHD: TS Nguyễn Hữu Tuân Sinh viên thực hiện: Khổng Đỗ Hạ Vũ - 87018
Hải Phòng, tháng năm 2023
Trang 2LỜI NÓI ĐẦU
Với công nghệ ngày một phát triển, ứng dụng công nghệ vào cuộc sống thườngnhật hay công việc đang là xu hướng phát triển của xã hội hiện nây Điều này vừagiúp các công việc được ứng dụng sẽ vận hành chính xác ,trơn tru vừa đảm bảo sự
an toàn , tính chính xác cao cho các công việc với những đặc thù riêng
Một đất nước phát triển luôn đi kèm với sự phát triển về kỹ thuật trong đó có thể
kể đến việc sản xuất ô tô nội địa VinFast hiện đang rất thành công trong việc sảnxuất ô tô với chính sách mới tiến tới sản xuất ô tô điện và theo xu hướng công nghệ
ô tô tự lái khả năng cao sẽ là bước phát triển tiếp theo của tập đoàn này
Một trong những điều quan trọng để có thể sản xuất ô tô tự lái chính là khả năngnhận diện và hiểu được các quy tắc giao thông – Hay nói cách khác là khả năngnhận diên biển báo giao thông.Đó là ứng dụng cho phép máy tính tự động xác định
và nhận dạng các vật thể qua hình ảnh hay khung hình của video Để làm đượcđiều này cần có một cơ sở dữ liệu về biển báo giao thông, khi ứng dụng quét hìnhảnh sẽ đối chiếu với cơ sở dữ liệu để đưa ra kết quả và nhận dạng hình ảnh đó.Xuất phát từ việc đó em đã nghiên cứu và tham khảo để hoàn thành bài tập lớn
“Xây dựng chương trình nhận dang biển báo giao thông”
Trang 3Mục lục
CHƯƠNG I.GIỚI THIỆU BÀI TOÁN 4
1.1 Đặt vấn đề 4
1.2 Mục tiêu và nhiệm vụ nghiên cứu 4
1.3 Phương tiện công cụ sử dụng 4
1.4 Phương pháp sử dụng 4
CHƯƠNG II.CÁC THUẬT TOÁN VÀ KHÁI NIỆM ĐƯỢC SỬ DỤNG 5
2.1 Thuật toán Gauss 5
2.2 Toán tử Laplacian 5
2.3 Ảnh nhị phân (Binary image) 5
2.4 Ảnh xám (Gray image) 5
2.5 Biến đổi Hough (Hough Transform) 5
2.6 Giải thuật Canny 6
CHƯƠNG III : XÂY DỰNG CHƯƠNG TRÌNH 7
3.1 Khái quát bài toán 7
3.2 Các bước thực hiện bài toán 7
3.3 Các hàm tiền xử lý ảnh 8
3.3.1 Hàm constrastLimit: 8
3.3.2 Hàm LaplacianOfGaussian 9
3.3.3 Hàm binarization 9
3.3.4 Hàm preprocess_image 9
3.3.5 Hàm removeSmallComponents 10
3.3.6 Hàm FindContour 10
3.3.7 Hàm contourIsSign 10
3.3.8 Các hàm crop sign 11
3.3.9 Hàm tìm kiếm biển báo 12
3.3.10 Hàm localization 13
3.3.11 Hàm remove_line 14
3.3.12 Hàm remove_other_color 15
3.3.13 Hàm main() 16
Trang 4CHƯƠNG IV: KẾT QUẢ CHẠY CHƯƠNG TRÌNH 22
CHƯƠNG V: ĐÁNH GIÁ VỀ CHƯƠNG TRÌNH VÀ KẾT LUẬN 25
Ưu điểm: 25
Nhược điểm: 25
Hướng phát triển trong tương lai 25
Lời kết 25
Trang 5CHƯƠNG I.GIỚI THIỆU BÀI TOÁN
1.1 Đặt vấn đề
Với việc ứng dụng công nghệ thông tin để giải quyết các vấn đề trong giao thông làmột vấn đề thiết yếu và quan trọng Việc xây dựng hệ thống giao thông thông minh
ở các xe tự động là vấn đề được quan tâm và phát triển trong và cả ngoài nước
Sự phát triển thường xuyên của công nghệ trong sản xuất ô tô với những cải tiếnliên tục cho các dòng xe mới thì việc có một hệ thống nhận diện biển báo là một sựcải tiện nên có và được quan tâm đảm bảo sự chính xác trong xử lý và an toàntrong giao thông
1.2 Mục tiêu và nhiệm vụ nghiên cứu
Mục tiêu: tạo ra một hệ thống có thể nhận dạng được cơ bản một số biển báo giaothông
Nhiệm vụ nghiên cứu:
Nghiên cứu tổng quan về xử lý ảnh
Nghiên cứu, phân tích các phương pháp nhận dạng, xử lý hình ảnh biển báo giaothông
Tìm hiểu các biển báo giao thông
Thu thập dữ liệu các biển báo cho cơ sở dữ liệu hình ảnh để nhận dang biển báogiao thông
1.3 Phương tiện công cụ sử dụng
Thư viện sử dụng: OpenCV
Ngôn ngữ lập trình: Python
Phần mềm sử dụng : Anaconda-Spyder
1.4 Phương pháp sử dụng
Trang 6CHƯƠNG II.CÁC THUẬT TOÁN VÀ KHÁI NIỆM ĐƯỢC
SỬ DỤNG
2.1 Thuật toán Gauss
Gaussian blur (làm mờ/mịn Gaussian) là kết quả của việc làm mờ hình ảnh bởi mộthàm Gaussian
Kỹ thuật này được sử dụng để giảm nhiễu ảnh và các chi tiết Hiệu ứng hình ảnhcủa kỹ thuật Gaussian tương tự như việc nhìn một hình ảnh qua màn hình mờ.Trong thị giác máy tính, Gaussian được sử dụng để tăng cường hình ảnh ở các quy
mô khác nhau hoặc như một kỹ thuật tăng cường dữ liệu trong học sâu
2.2 Toán tử Laplacian
Là một toán tử vi phân, đặc biệt trong các toán tử elliptic, với nhiều áp dụng.Trong vật lý, nó được sử dụng trong mô tả của quá trình truyền sóng, quá trìnhtruyền nhiệt
Dựa vào toán tử Laplacian, ảnh sắc nét sẽ thu được bằng cách lấy ảnh gốc trừ điLaplacian của nó
2.3 Ảnh nhị phân (Binary image)
Ảnh nhị phân (hay còn gọi là binary image trong tiếng Anh) là ảnh đen trắng chỉ có
2 giá trị là 0 và 255 (miền số nguyên) hoặc 0 và 1 (miền số thực / đối với ROI)
2.4 Ảnh xám (Gray image)
Ảnh xám hay còn gọi là ảnh đơn sắc (monochromatic) Ảnh 8 mức xám mỗi điểmảnh sẽ có giá trị nằm trong đoạn [0-7], ảnh 256 mức xám mỗi điểm ảnh sẽ có giá trịnằm trong đoạn [0-255]
Giá trị của điểm ảnh bằng 0 đại diện cho điểm ảnh tối (đen), giá trị điểm ảnh lơnnhất đại diện cho điểm ảnh sáng (trắng)
Trang 72.5 Biến đổi Hough (Hough Transform)
Là một kỹ thuật phổ biến để phát hiện bất kỳ hình dạng nào nếu có thể biểu diễnhình dạng đó dưới dạng toán học Có thể phát hiện hình dạng ngay cả khi nó bịhỏng hoặc bị bóp méo một chút
2.6 Giải thuật Canny
Gồm 4 bước:
Giảm nhiễu: Làm mờ ảnh, giảm nhiễu
Tính Gradient và hướng gradient
Non-maximum Suppression (viết tắt NMS): loại bỏ các pixel ở vị trí không phải
cực đại toàn cục
Ngưỡng kép (Double threshold)
Theo dõi cạnh bằng độ trễ (Edge Tracking by Hysteresis)
Trang 8CHƯƠNG III : XÂY DỰNG CHƯƠNG TRÌNH
3.1 Khái quát bài toán
Bài toán nhận dang biển báo giao thông trải qua các bước sau:
Thông qua nguồn dữ liệu cụ thể là video được ghi lại , hệ thống sẽ xác định cácbiển báo trong khung hình và dối chiếu với cơ sở dữ liệu được lưu sẵn của hệthống và xác định xem hình ảnh nhận được trong đó có phải biển báo giao thôngkhông Sau khi nhận dang được đó là biển báo giao thông , hệ thống sẽ xử lý, nhậndang và đưa thông tin là tên của biển báo giao thông
3.2 Các bước thực hiện bài toán
Thu nhập các ảnh biển báo giao thông
Tạo 1 folder “Dataset” và đưa vào CSDL hình ảnh gồm các biển báo gồm các biểnbáo sau đây
Huấn luyện model phân loại biển bảo và kiểm thử
Trang 9return img_hist_equalized
Trang 10Đầu tiên chuyển đổi từ ảnh sang định dạng YCrCb, thực hiện chia lấy các kênhmàu của ảnh , thực hiện cần bằng sáng bằng equalizeHist , hàm cv2.merge lấy từngkênh màu của ảnh và hợp nhất thành một ảnh để chứa nhiều channel – multichannel image Sau đó tiếp tục chuyển đổi ảnh về lại RGB và trả lại ảnh ở địnhdang RGB
3.3.2 Hàm LaplacianOfGaussian
def LaplacianOfGaussian(image):
LoG_image = cv2.GaussianBlur(image, (3,3), 0)
gray = cv2.cvtColor( LoG_image, cv2.COLOR_BGR2GRAY)
LoG_image = cv2.Laplacian( gray, cv2.CV_8U,3,3,2)
LoG_image = cv2.convertScaleAbs(LoG_image)
return LoG_image
Hàm sẽ sử dụng GaussiaanBlur làm mịn ảnh được cho vào , sao đó chuyển ảnhđược làm mịn sang ảnh xám bằng cv2.cvtColor rồi tiếp tục dùng hàmcv2.Laplacian để làm giảm thiệu độ nhiễu của ảnh Sau cùng dùngcv2.convertScaleAbs chia tỷ lệ,lấy giá trị tuyệt đối, chuyển đổi thành loại 8-bit
Trang 113.3.5 Hàm removeSmallComponents
def removeSmallComponents(image, threshold):
nb_components, output, stats, centroids =cv2.connectedComponentsWithStats(image, connectivity=8)
sizes = stats[1:, -1]; nb_components = nb_components - 1
img2 = np.zeros((output.shape),dtype = np.uint8)
for i in range(0, nb_components):
def contourIsSign(perimeter, centroid, threshold):
# perimeter, centroid, threshold
# # Compute signature of contour
Trang 12signature = [float(dist) / max_value for dist in result ]
# Check signature of contour
temp = sum((1 - s) for s in signature)
temp = temp / len(signature)
if temp < threshold: # is the sign
return True, max_value + 2
else: # is not the sign
return False, max_value + 2
Hàm sẽ tính toán dựa vào tâm vầ chu vi và ngưỡng threshold , tạo một list resultnhập thêm kết quả của mỗi distance theo công thức , tính giá trị max_value bằnggiá trị lớn nhất của list result Tạo list signature với mỗi giá trị bên trong list bằngkhoảng cách chia cho giá trị lớn nhất của list kết quả Tạo biến temp bằng tổngcủa 1 – s với mỗi s là biến trong list signature Sau đó gán temp = temp chia cho sốlượng biến trong signature Nếu như nhỏ hơn thì trả về kết quả đúng tức là biểnbáo và max_value +2 ngược lại nếu lớn hơn trả về kết quả sai tức ko phải biển báo
top = max([int(center[0] - max_distance), 0])
bottom = min([int(center[0] + max_distance + 1), height-1])
left = max([int(center[1] - max_distance), 0])
right = min([int(center[1] + max_distance+1), width-1])
print(left, right, top, bottom)
return image[left:right, top:bottom]
def cropSign(image, coordinate):
Trang 13right = min([int(coordinate[1][0]), width-1])
#print(top,left,bottom,right)
return image[top:bottom,left:right]
Các hàm này sẽ cắt phần ảnh biển báo và lưu lại
3.3.9 Hàm tìm kiếm biển báo
def findLargestSign(image, contours, threshold, distance_theshold):
is_sign, distance = contourIsSign(c, [cX, cY], 1-threshold)
if is_sign and distance > max_distance and distance > distance_theshold: max_distance = distance
coordinate = np.reshape(c, [-1,2])
left, top = np.amin(coordinate, axis=0)
right, bottom = np.amax(coordinate, axis = 0)
coordinate = [(left-2,top-2),(right+3,bottom+1)]
sign = cropSign(image,coordinate)
return sign, coordinate
def findSigns(image, contours, threshold, distance_theshold):
signs = []
coordinates = []
for c in contours:
Trang 14# compute the center of the contour
is_sign, max_distance = contourIsSign(c, [cX, cY], 1-threshold)
if is_sign and max_distance > distance_theshold:
sign = cropContour(image, [cX, cY], max_distance)
signs.append(sign)
coordinate = np.reshape(c, [-1,2])
top, left = np.amin(coordinate, axis=0)
right, bottom = np.amax(coordinate, axis = 0)
binary_image = cv2.bitwise_and(binary_image,binary_image,mask=remove_other_color(image))
#binary_image = remove_line(binary_image)
cv2.imshow('BINARY IMAGE', binary_image)
contours = findContour(binary_image)
Trang 15#signs, coordinates = findSigns(image, contours, similitary_contour_with_circle,15)
sign, coordinate = findLargestSign(original_image, contours,similitary_contour_with_circle, 15)
text = ""
sign_type = -1
i = 0
if sign is not None:
sign_type = getLabel(model, sign)
sign_type = sign_type if sign_type <= 8 else 8
text = SIGNS[sign_type]
cv2.imwrite(str(count)+'_'+text+'.png', sign)
if sign_type > 0 and sign_type != current_sign_type:
cv2.rectangle(original_image, coordinate[0],coordinate[1], (0, 255, 0), 1) font = cv2.FONT_HERSHEY_PLAIN
cv2.putText(original_image,text,(coordinate[0][0], coordinate[0][1] -15), font,1,(0,0,255),2,cv2.LINE_4)
return coordinate, original_image, sign_type, text
Hàm này sẽ xử lý dữ liệu ảnh đầu vào và trình chiếu ra ảnh nhị phân sau đó xácđịnh biển báo nhận được là biển báo gì
Trang 16mask = np.ones(img.shape[:2], dtype="uint8") * 255
if lines is not None:
for line in lines:
for x1,y1,x2,y2 in line:
cv2.line(mask,(x1,y1),(x2,y2),(0,0,0),2)
return cv2.bitwise_and(img, img, mask=mask)
Sử dụng biến đổi Hough thể hiện hình ảnh dưới dạng toán học sử dụngcv2.bitwise_and qua đó loại bỏ viền
# Threshold the HSV image to get only blue colors
mask_blue = cv2.inRange(hsv, lower_blue, upper_blue)
lower_white = np.array([0,0,128], dtype=np.uint8)
upper_white = np.array([255,255,255], dtype=np.uint8)
# Threshold the HSV image to get only blue colors
mask_white = cv2.inRange(hsv, lower_white, upper_white)
lower_black = np.array([0,0,0], dtype=np.uint8)
upper_black = np.array([170,150,50], dtype=np.uint8)
mask_black = cv2.inRange(hsv, lower_black, upper_black)
mask_1 = cv2.bitwise_or(mask_blue, mask_white)
mask = cv2.bitwise_or(mask_1, mask_black)
# Bitwise-AND mask and original image
Trang 17#res = cv2.bitwise_and(frame,frame, mask= mask)
return mask
Hàm dùng gaussianBlur để làm mịn ảnh sau đó chuyển định dạng ảnh sang khônggian màu HSV, định dạng vùng xanh của ảnh trong không gian màu , chỉnhngưỡng để lấy vùng xanh của ảnh, loại bỏ các màu sắc khác
width = vidcap.get(3) # float
height = vidcap.get(4) # float
# Define the codec and create VideoWriter object
fourcc = cv2.VideoWriter_fourcc(*'XVID')
out = cv2.VideoWriter('output.avi',fourcc, fps , (640,480))
# initialize the termination criteria for cam shift, indicating
# a maximum of ten iterations or movement by a least one pixel
# along with the bounding box of the ROI
termination = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT,
10, 1)
roiBox = None
roiHist = None
Trang 18#image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
coordinate, image, sign_type, text = localization(frame,args.min_size_components, args.similitary_contour_with_circle, model, count,current_sign)
if coordinate is not None:
Trang 19# grab the ROI for the bounding box and convert it
# to the HSV color space
roi = frame[tl[1]:br[1], tl[0]:br[0]]
roi = cv2.cvtColor(roi, cv2.COLOR_BGR2HSV)
#roi = cv2.cvtColor(roi, cv2.COLOR_BGR2LAB)
# compute a HSV histogram for the ROI and store the
# bounding box
roiHist = cv2.calcHist([roi], [0], None, [16], [0, 180])
roiHist = cv2.normalize(roiHist, roiHist, 0, 255, cv2.NORM_MINMAX) roiBox = (tl[0], tl[1], br[0], br[1])
elif current_sign:
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
backProj = cv2.calcBackProject([hsv], [0], roiHist, [0, 180], 1)
Trang 20# apply cam shift to the back projection, convert the
# points to a bounding box, and then draw them
(r, roiBox) = cv2.CamShift(backProj, roiBox, termination)
Trang 21position = [count, sign_type if sign_type <= 8 else 8, tl[0], tl[1], br[0],br[1]]
cv2.rectangle(image, (tl[0], tl[1]),(br[0], br[1]), (0, 255, 0), 1)
font = cv2.FONT_HERSHEY_PLAIN
cv2.putText(image,current_text,(tl[0], tl[1] -15), font, 1,(0,0,255),2,cv2.LINE_4)
Trang 23CHƯƠNG IV: KẾT QUẢ CHẠY CHƯƠNG TRÌNH
Sau khi chạy video đầu vào sẽ xuất ra video output với kết quả nhận dạng các ảnhsau
Trang 26CHƯƠNG V: ĐÁNH GIÁ VỀ CHƯƠNG TRÌNH VÀ KẾT LUẬN
Khả năng nhận diện còn phụ thuộc vào ánh sáng và môi trường xung quanh
Dữ liệu biển báo còn khá ít chưa nhiều
Hướng phát triển trong tương lai
Phát triển thuật toán nhận diện các biển báo phức tạp hơn
Tạo cơ sở dữ liệu lớn hơn
Sử dụng thuật toán CNN để phân lớp và xử lý ảnh
Lời kết
Sau khi nghiên cứu và tham khảo , em đã có thể xây dựng một chương trìnhnhận diện cơ bản các biển báo giao thông, tuy nhiên vẫn còn nhiều thiếu xót và hạnchế về thuật toán và lập trình