Điều này cho phép người sử dụngtạo ra và dùng các đối tượng phù hợp với các khái niệm của ứng dụng đó, do đó C++ cung cấp kiểu lập trình thao tác trực tiếp tài nguyên phần cứng và mô hìn
Trang 1ĐẠI HỌC BÁCH KHOA HÀ NỘI TRƯỜNG ĐIỆN – ĐIỆN TỬ
- - -
-BÁO CÁO BÀI TẬP LỚN
MÔN KỸ THUẬT LẬP TRÌNH C/C++
Đề tài: Xuất dữ liệu từ ảnh thẻ sinh viên
Lớp : Điện tử 010 – K63
Mã lớp học : 133362
Hà Nội, 8/2022
Trang 2L I M ĐẦẦUỜ Ở 3
1 T ng quan vềề ngôn ng l p trình C++ổ ữ ậ 4
2 T ng quan vềề x lý nhổ ử ả 6
3 Ph ương pháp th c hi n đềề tài “Trích xuấất thông tn t th sinh viền”ự ệ ừ ẻ 8
3.1 Th vi n OpenCVư ệ 8
3.2 S đôề khôấi mô t phơ ả ương pháp 8
3.2.1 Phát hi n góc thệ ẻ 9
3.2.2 M t sôấ phép biềấn đ i nhộ ổ ả 10
3.2.3 Phát hi n vùng chệ ữ 10
3.2.4 Nh n d ng ký tậ ạ ự 10
4 Các s d ng và source codeử ụ 14
5 Kềất lu n và hậ ướng phát tri nể 18
L I KẾẾTỜ 19
TÀI LI U THAM KH OỆ Ả 20
LỜI MỞ ĐẦU
Trang 3Hiện nay, nhu cầu về việc rút trích từ ngữ từ hình ảnh đang ngày càng phát triển, bên cạnh sự gia tăng về nhu cầu là sự phát triển của công nghệ nhận dạng ký
tự quang học (Optical Character Recognition) hay còn được gọi tắt là OCR Đây là một công nghệ giúp chuyển đổi hình ảnh của chữ viết tay hoặc đánh máy thành các
ký tự đã được mã hóa trong máy tính Chẳng hạn như chúng ta cần trích xuất thông tin các nhân trên thẻ căn cước công dân hoặc thẻ sinh viên, …
Trích xuất thông tin từ ảnh Thẻ sinh viên giúp cho nhiều ứng dụng cần dùng xác minh sinh viên được thuận lợi hơn chính xác hơn Mục tiêu đề tài là nghiên cứu các giải thuật xử lý ảnh, thư viện lập trình OpenCV kết hợp với bộ ký tự Tesseract
và luyện tập khả năng lập trình ngôn ngữ C/C++ để trích xuất thông tin từ file ảnh chuyển sang dạng text
Cảm ơn tới TS Nguyễn Quang Minh đã tạo điều kiện cho chúng em có thể trình bày bài tập này để có cơ hội được tìm hiểu và nâng cao kỹ năng lập trình C/C+ + cũng như về lĩnh vực xử lý ảnh
Trang 4
1 Tổng quan về ngôn ngữ lập trình C++
Ngôn ngữ lập trình C++ được phát triển năm 1980 bởi Bjarne Stroustrup tại
phòng thí nghiệm Bell của AT&T ((American Telephone & Telegraph)), Mỹ Nó được phát triển bằng cách bổ sung thêm tính năng OOP (Object Oriented Programming - Lập trình hướng đối tượng) vào C mà không thay đổi quá lớn tới các thành phần của C
C++ là ngôn ngữ lập trình bậc trung bởi nó mang tính chất của cả ngôn ngữ bậc cao (tính trừu tượng) và ngôn ngữ bậc thấp (liên quan chặt chẽ đến ngôn ngữ máy) C++ cung cấp mô hình bộ nhớ và tính toán cho hầu hết các máy tính Mở rộng từ ngôn ngữ C, C++ mang những tính chất tối ưu hơn như tính hướng đối tượng (Object Oriented Programming) nhằm cung cấp cơ chế mạnh mẽ và linh hoạt hơn để trương tượng hóa vấn đề cần giải quyết Điều này cho phép người sử dụng tạo ra và dùng các đối tượng phù hợp với các khái niệm của ứng dụng đó, do đó C+ + cung cấp kiểu lập trình thao tác trực tiếp tài nguyên phần cứng và mô hình dữ liệu gần với quan điểm người hơn so với tác vụ của máy tính
- Ngôn ngữ lập trình C++ có thể được dùng để làm những công việc sau:
C++ được thiết kế để viết những hệ thống lớn, thậm chí C++ được dùng để tạo nên hệ điều hành máy tính (Linux, Mac OS X, Windows…)
C++ được dùng để tạo nên các game lớn của hãng Blizzard (World of Warcraft, Diablo series, StarCraft series…) Gần như toàn bộ các game bom tấn trên thị trường hiện nay cũng dùng C++ để phát triển Một số công cụ sử dụng trong việc lập trình game có sử dụng C++ như Unreal engine,
Cocos2d-x framework,… Các ông lớn trong ngành công nghiệp game như Valve, CryTek cũng sử dụng C++
Trang 5 Thao tác vào ra trong C++ :
Thao tác vào ra dữ liệu trong C++ sử dụng khái niệm luồng (stream) Luồng
là một chuỗi các bytes hoặc đường đi của dữ liệu Nó khiến hiệu suất thực hiện cao hơn C++ hỗ trợ thư viện <iostream> để sử dụng chức năng cin và cout
Kiểu dữ liệu trong C++
- C++ hỗ trợ lưu trữ và thao tác trên 4 loại kiểu dữ liệu:
o Kiểu dữ liệu cơ bản : int (integer) và float
o Kiểu dữ liệu Enum: kiểu dữ liệu dạng liệt kê
o Kiểu dữ liệu Void: không trả lại giá trị gì (thường dùng để tạo hàm)
o Kiểu dữ liệu nâng cao: con trỏ, mảng, structure, union, function…
- Tính chất OOP trong C++ : cũng như các các ngôn ngữ bậc cao, OOP trong C++ có 4 tính chất cơ bản:
o Tính trừu tượng
o Tính đa hình
o Tính kế thừa
o Tính đóng gói
Trang 62 Tổng quan về xử lý ảnh
Con người thu nhận thông tin qua các giác quan, trong đó thị giác đóng vai trò quan trọng nhất Những năm trở lại đây với sự phát triển của phần cứng máy tính,
xử lý ảnh và đồ hoạ đó phát triển một cách mạnh mẽ và có nhiều ứng dụng trong cuộc sống Xử lý ảnh và đồ hoạ đóng một vai trò quan trọng trong tương tác người máy Quá trình xử lý ảnh được xem như là quá trình thao tác ảnh đầu vào nhằm cho
ra kết quả mong muốn Kết quả đầu ra của một quá trình xử lý ảnh là ảnh phù hợp với nhu cầu của người lập trình
Ảnh có thể xem là tập hợp các điểm ảnh và mỗi điểm ảnh được xem như là đặc trưng cường độ sáng hay một dấu hiệu nào đó tại một vị trí nào đó của đối tượng trong không gian và nó có thể xem như một hàm n biến P(c1, c2, , cn) Do đó, ảnh trong xử lý ảnh có thể xem như ảnh n chiều
Sơ đồ tổng quát của một hệ thống xử lý ảnh:
Các vấn đề cơ bản trong xử lý ảnh:
Ảnh và điểm ảnh:
Điểm ảnh được xem như là dấu hiệu hay cường độ sáng tại 1 toạ độ trong không gian của đối tượng và ảnh được xem như là 1 tập hợp các điểm ảnh
Mức xám, màu: Là số các giá trị có thể có của các điểm ảnh của ảnh
Nắn chỉnh biến dạng: Ảnh thu nhận thường bị biến dạng do các thiết bị quang học và điện tử
Khử nhiễu: Có 2 loại nhiễu cơ bản trong quá trình thu nhận ảnh
- Nhiễu hệ thống: là nhiễu có quy luật có thể khử bằng các phép biến đổi
- Nhiễu ngẫu nhiên: vết bẩn không rõ nguyên nhân ->khắc phục bằng các phép lọc
Chỉnh mức xám:
Nhằm khắc phục tính không đồng đều của hệ thống gây ra Thông thường có
2 hướng tiếp cận:
o Giảm số mức xám: Thực hiện bằng cách nhóm các mức xám gần nhau thành một bó Trường hợp chỉ có 2 mức xám thì chính là chuyển về ảnh đen trắng Ứng dụng: In ảnh màu ra máy in đen trắng
Trang 7o Tăng số mức xám: Thực hiện nội suy ra các mức xám trung gian bằng kỹ thuật nội suy Kỹ thuật này nhằm tăng cường độ mịn cho ảnh
Trích chọn đặc điểm
- Các đặc điểm của đối tượng được trích chọn tuỳ theo mục đích nhận dạng trong quá trình xử lý ảnh Có thể nêu ra một số đặc điểm của ảnh sau đây:
- Đặc điểm không gian: Phân bố mức xám, phân bố xác suất, biên độ, điểm uốn v.v
- Đặc điểm biến đổi: Các đặc điểm loại này được trích chọn bằng việc thực hiện lọc vùng (zonal filtering) Các bộ vùng được gọi là “mặt nạ đặc điểm” (feature mask) thường là các khe hẹp với hình dạng khác nhau (chữ nhật, tam giác, cung tròn v.v )
- Đặc điểm biên và đường biên: Đặc trưng cho đường biên của đối tượng và
do vậy rất hữu ích trong việc trích trọn các thuộc tính bất biến được dùng khi nhận dạng đối tượng Các đặc điểm này có thể được trích chọn nhờ toán tử gradient, toán
tử la bàn, toán tử Laplace, toán tử “chéo không” (zero crossing) v.v
Việc trích chọn hiệu quả các đặc điểm giúp cho việc nhận dạng các đối tượng ảnh chính xác, với tốc độ tính toán cao và dung lượng nhớ lưu trữ giảm xuống
Nhận dạng
Nhận dạng tự động (automatic recognition), mô tả đối tượng, phân loại và phân nhóm các mẫu là những vấn đề quan trọng trong thị giác máy, được ứng dụng trong nhiều ngành khoa học khác nhau Tuy nhiên, một câu hỏi đặt ra là: mẫu (pattern) là gì? Watanabe, một trong những người đi đầu trong lĩnh vực này đã định nghĩa:
“Ngược lại với hỗn loạn (chaos), mẫu là một thực thể (entity), được xác định một cách ang áng (vaguely defined) và có thể gán cho nó một tên gọi nào đó” Ví dụ mẫu có thể là ảnh của vân tay, ảnh của một vật nào đó được chụp, một chữ viết, khuôn mặt người hoặc một ký đồ tín hiệu tiếng nói Khi biết một mẫu nào đó, để nhận dạng hoặc phân loại mẫu đó có thể:
Hoặc phân loại có mẫu (supervised classification), chẳng hạn phân tích phân biệt (discriminant analyis), trong đó mẫu đầu vào được định danh như một thành phần của một lớp đã xác định
Hoặc phân loại không có mẫu (unsupervised classification hay clustering) trong
đó các mẫu được gán vào các lớp khác nhau dựa trên một tiêu chuẩn đồng dạng nào
đó Các lớp này cho đến thời điểm phân loại vẫn chưa biết hay chưa được định danh
Trang 83 Phương pháp thực hiện đề tài “Xuất dữ liệu từ ảnh thẻ
sinh viên”
3.1 Thư viện OpenCV
OpenCV là mã nguồn mở của Intel, nó là một thư viện có khả năng nhúng vào trong các chương trình có khả năng nhận diện hình ảnh của máy tính Nó bao gồm khả năng tiên tiến như phát hiện, theo dõi, nhận diện vật thể… Ngoài
ra, nó cung cấp rất nhiều các thuật toán xử lý ảnh thông qua các hàm API OpenCV hỗ trợ đa nền tảng Nó hỗ trợ cả Windows và Linux, và gần đây hơn
là MacOSX Với giao diện của nó là nền tảng độc lập
Các ứng dụng chính của OpenCV:
Đọc và ghi hình ảnh
Chụp và lưu video
Xử lý hình ảnh (lọc, biến đổi)
Thực hiện phát hiện tính năng
Phát hiện các đối tượng cụ thể như khuôn mặt, mắt, ô tô, trong video hoặc hình ảnh
Phân tích video, tức là ước tính chuyển động trong đó, trừ hậu cảnh và theo dõi các đối tượng trong đó
Thị giác máy tính
Computer Vision có thể được định nghĩa là một môn học giải thích cách tái tạo, ngắt và hiểu một cảnh 3D từ hình ảnh 2D của nó, xét về các thuộc tính của cấu trúc có trong cảnh đó Nó đề cập đến việc mô hình hóa và tái tạo tầm nhìn của con người bằng phần mềm và phần cứng máy tính
Thị giác Máy tính trùng lặp đáng kể với các trường sau:
Image Processing - Nó tập trung vào thao tác hình ảnh
Pattern Recognition - Nó giải thích các kỹ thuật khác nhau để phân loại các mẫu
Photogrammetry - Có liên quan đến việc thu được các phép đo chính xác từ hình ảnh
3.2 Sơ đồ khối mô tả phương pháp
Ảnh đầu vào là ảnh được chụp từ điện thoại nên sẽ có thành phần nhiễu cũng như vị trí ảnh bị lệch, dẫn đến không thể dùng phương pháp detect vật thể trực tiếp
mà cần phải thực hiện xử lý ảnh như xoay thẳng, lọc nhiễu… Để việc nhận dạng chữ viết được diễn ra thuận lợi, chúng ta cần khoanh vùng vùng có chữ và cuối cùng mới tiến tới bước nhận dạng kí tự Dưới đây là phương pháp đơn giản mà em
sử dụng cho bài toán:
Trang 93.2.1 Phát hiện góc thẻ
Như đã nêu bên trên, việc thu thập ảnh là bước thủ công nên ảnh có thể bị xoay, nghiêng Chúng ta thực hiện tìm đường viền cạnh (contours) bằng thư viện OpenCV
Vậy contour là gì? Contour là tập hợp tất cả các điểm ảnh liên tục có cùng màu hoặc cường độ Để thêm chính xác cho việc tìm contour thì ảnh đầu vào nên là ảnh đã được detected edge sử dụng Canny hoặc threshold edge detection
Trong một bức ảnh có nhiều contours khác nhau phân tầng bằng quan hệ hierarchy, tuy vậy mục đích của chúng ta là đi tìm ra 4 góc của ảnh nên sẽ chỉ lấy contour có diện tích mặt lớn nhất và sau đó lấy ra hoành độ và tung độ của 4 góc bằng hàm approxPolyDP()
Mat img, img_resized, img_original, img_gray, img_canny, edged, hstack; img imread( = "C:/Downloads/AI_PHOTOS/data/thesinhvien1.jpg");
resize (img, img_resized, Size(), 0.5, 0.5);
cvtColor (img_resized, img_original, COLOR_BGR2GRAY );
bilateralFilter (img_original, img_gray, 20, 30, 30);
Canny (img_gray, edged, 10, 20);
vector vector Point < < > > contours; // list of contours in an image
vector Vec4i < > hierarchy; // relationship of contours in an image
findContours(edged, contours, hierarchy, RETR_TREE CHAIN_APPROX_SIMPLE , );
int index = getMaxAreaContourId(contours);
Scalar color = Scalar (rng.uniform(0, 256), rng.uniform(0, 256), rng.uniform(0, 256)); drawContours(img_resized, contours, ( int )index, color, 2, LINE_8 , hierarchy, 0); // Find four corner points
vector<cv::Point2i> approx;
approxPolyDP(contours index [ ], approx, 40, true );
for auto ( p : approx)
{
cout << p.x << endl;
cout << p.y << endl;
if (p.y > mean[ ] 1 ) bottomCorners.push_back(p);
if (p.y < mean[ ] 1 ) topCorners.push_back(p);
}
if (topCorners [ ] 0 x > topCorners [1] x) {
swap(topCorners [0], topCorners[ ] 1 );
}
if (bottomCorners [ ] 0 x > bottomCorners [1] x) {
Trang 103.2.2 Một số phép biến đổi ảnh
- Biến đổi phối cảnh (perspective transform):
Để biến đổi phối cảnh thì chúng ta cần một ma trận biến đổi 3x3 Đường thẳng sẽ giữ nguyên là đường thẳng sau biến đổi Để tìm ra ma trận biến đổi này, chúng ta sử dụng 4 góc của ảnh đã phát hiện ở trên Thông qua
getPerspectiveTransform() áp dụng warpPerspective() với ma trận biến đổi 3x3
Ảnh sau khi thực hiện phép biến đổi đã được đặt về vị trí thẳng cố định, giúp việc nhận dạng chữ trở nên dễ dàng hơn
3.2.3 Phát hiện vùng chữ
Chúng ta thực hiện phân đoạn màu để chuyển ảnh về dạng nhị phân (chỉ vùng đen và trắng) sau đấy kết nối những vùng ký tự trắng liên tục bằng phương thức getStructuringElement() và cuối cùng là tìm đường viền (contour) thỏa mãn ngưỡng tỷ lệ co và xóa phần không thỏa mãn tỷ lệ cũng như vẽ thêm contour giữ lại bằng các bounding box xấp xỉ với contours
cv:: threshold ( img_sobel , img _ threshold , 0, 255, THRESH_OTSU + THRESH_BINARY );
element = getStructuringElement (cv:: MORPH_RECT , cv:: Size (20, 7));
cv:: morphologyEx ( img_threshold img_threshold , , MORPH_GRADIENT , element);
// draw rectangles on output image
rectangle(output, letterBBoxes1[i], cv::Scalar(0, 255, 0), 3, 1, 0);
3.2.4 Nhận dạng ký tự
Qua các bước xử lý ảnh bên trên thì đến đây chúng ta mới thực hiện nhận dạng ký tự và đưa ra kết quả
OCR (Optical Charater Recognition) hay còn gọi là kỹ thuật nhận dạng ký tự quang học được dùng phổ biến trong việc nhận dạng ký tự từ dạng ảnh để chuyển
về dạng text Được biết đến là một công cụ scan kỹ thuật số chuyên nhận dạng các
ký tự, chữ viết tay, hay chữ đánh máy, công nghệ này chuyên dùng để truyền tải, nhập liệu dữ liệu Đặc biệt, ở OCR có khả năng kỹ thuật số nhiều dưới nhiều dạng tài liệu khác nhau: hóa đơn, hộ chiếu, danh thiếp, tài liệu…
Trang 11Tesseract OCR – phát triển bởi HP, được đề xuất là bộ nhận dạng kí tự mạnh
mẽ với mã nguồn mở và được sử dụng phổ biến Tesseract chuyển đổi hình ảnh 2D của văn bản, chứa văn bản được in bằng máy hoặc chữ viết tay thành văn bản điện tử
Cấu trúc của Tesseract
Tạo ngưỡng thích nghi giúp loại bỏ các yếu tố nền của hình ảnh (ví dụ như ánh sáng, bóng,…) và giúp phân tích các pixel thành ảnh nhị phân
Nhận dạng được tiến hành qua một quá trình với hai lần nhận dạng Lần thứ nhất: nhận ra lần lượt từng từ Mỗi từ có nghĩa là đạt yêu cầu và được thông qua và được lưu vào dữ liệu Lần thứ hai, khi phân loại thích ứng, công cụ sẽ nhận dạng lại các từ không được nhận dạng tốt ở lần trước đó
Xác định dòng
Trang 12Mục đích của bước này là nhận dạng các dòng của các hình ảnh bị nghiêng, giúp giảm sự mất thông tin khi nhận dạng ảnh nghiêng Các bộ phận quan trọng của quá trình này là lọc dãy màu (còn được gọi là blobs) và xây dựng dòng Bước này cũng giúp loại bỏ các văn bản có drop-cap
Thiết lập dòng cơ sở
Khi dòng văn bản được tìm thấy, các dòng cơ sở được thiết lập chính xác hơn bằng cách sử dụng một đường có tên là spline toàn phương (là dòng mà được kết hợp từ nhiều đoạn) Nó giúp Tesseract xử lý các trang có đường cơ sở là đường cong
Các dòng cơ sở được thiết lập bằng cách phân vùng các blobs thành các nhóm có thể thay thế thích hợp liên tục trong đường cơ sở thẳng ban đầu Một spline toàn phương được thiết lập cho phân vùng dày đặc nhất, (giả định là đường
cơ sở) của một hình có phương ít nhất Spline có lợi thế là tính toán ổn định, nhược điểm là sự gián đoạn có thể xảy ra khi nhiều phân đoạn spline được yêu cầu
Cắt nhỏ từ
Tesseract sẽ xác định xem có các ký tự dính với nhau trong một từ hay không Nếu có nó sẽ cắt nhỏ các ký tự ra thành các ký tự riêng lẻ
Nhận dạng khoảng cách giữa chữ hoặc số
Xác định khoảng cách giữa các số hoặc giữa các chữ là một vấn đề khá phức tạp Tesseract giải quyết những vấn đề này bằng cách đo khoảng cách trong một phạm vi hạn chế theo chiều dọc giữa dòng cơ sở và dòng trung bình
Nhận dạng từ
Quá trình nhận dạng một từ là quá trình phân tích một từ được chia ra thành các ký tự như thế nào
Ở đây em đã sử dụng thư viện Tesseract để khởi tạo 1 biến ocr lấy bộ dữ liệu
đã huấn luyện sẵn của Tesseract Ở đây, chúng ta thiết lập khởi tạo bằng ngôn ngữ tiếng Anh (“eng”)
tesseract::TessBaseAPI * ocr = new tesseract:: TessBaseAPI ();
ocr->Init("D:\\KTLT\\vcpkg\\installed\\x64-windows\\include\\tesseract_data" "eng" , , tesseract:: OEM_LSTM_ONLY );
// Phan chia ky tu
ocr->SetPageSegMode(tesseract:: PSM_AUTO );
Duyệt với từng bounding box và thực hiện OCR:
for int ( i = 0; i < letterBBoxes1.size(); i++) {
rectangle(output, letterBBoxes1 [i] , cv:: Scalar(0, 255, 0), 1, 1, 0);
Mat cropped_image = output(letterBBoxes1 i ; [ ])
ocr->SetImage(cropped_image.data, cropped_image.cols, cropped_image.rows, 3, cropped_image.step);
string outText = string(ocr->GetUTF8Text());