Tải bản đầy đủ (.docx) (29 trang)

Xử lý ảnh - Nhận dạng ký tự toán học bằng phương pháp SVM dùng thư viện OpenCV

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (821.22 KB, 29 trang )

TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI

VIỆN ĐIỆN TỬ - TRUYỀN THÔNG

BÁO CÁO ĐỒ ÁN 1
ĐỀ TÀI: ỨNG DỤNG XỬ LÝ ẢNH TRONG NHẬN DẠNG KÝ
TỰ TOÁN HỌC BẰNG PHƯƠNG PHÁP SVM

Giảng viên hướng dẫn:
Sinh Viên Thực Hiện:

Hà Nội, 1/2017


Mục lục



Lời nói đầu
Xử lý ảnh và thị giác máy tính là lĩnh vực mà ngày nay được phát triển và ứng
dụng rất rộng rãi trong nhiều lĩnh vực khác nhau nhờ vào sự phát triển ngày càng
mạnh mẽ của các hệ thống máy tính, các thuật toán và công trình nghiên cứu khác
nhau của nhiều nhà khoa học trên thế giới.
Ở Việt Nam, các ứng dụng về xử lý ảnh đã bước đầu được triển khai trên một
số lĩnh vực như lắp đặt hệ thống nhận dạng biển số xe ở các bãi đỗ xe, hệ thống
phục vụ nhận dạng vân tay chấm công ở các công sở, các hệ thống camera giao
thông quan sát,…Tuy nhiên nhìn một cách khách quan thì số lượng các ứng dụng
được triển khai trên thực tế là quá ít ỏi, lĩnh vực này sẽ còn phát triển mạnh mẽ
trong tương lai nếu được quan tâm một cách nghiêm túc.
Đề tài đồ án 1 của nhóm chúng em cũng là một phần nhỏ liên quan đến ứng
dụng xử lý ảnh, mục tiêu của đề tài nhằm nhận biết được các ký tự toán học từ tài


liệu định dạng PDF, từ đó chuyển các ký tự sang định dạng có thể chỉnh sửa như
.doc, .txt,…
Nhóm chúng em xin gửi lời cảm ơn chân thành đến PGS.TS Hoàng Mạnh
Thắng, Giảng viên Viện điện tử truyền thông, Đại học Bách Khoa Hà Nội đã hướng
dẫn nhóm em hoàn thành đề tài này. Chúng em cũng xin cảm ơn anh Nguyễn Xuân
Sỹ và các thành viên trong SIPLAB đã trợ giúp chúng em trong quá trình làm đồ
án .

Sinh viên
Trần Ngọc Tiến

4


1. XỬ LÝ ẢNH DÙNG THƯ VIỆN OPEN CV
1.1. Giới thiệu về thư viện Opencv
OpenCV (Open Source Computer Vision) là một thư viện mã nguồn mở về thị
giác máy tính với hơn 500 hàm và hơn 2500 các thuật toán đã được tối ưu về xử lý
ảnh, và các vấn đề liên quan đến thị giác máy. OpenCV được thiết kế một các tối
ưu, sử dụng tối đa sức mạnh của các dòng chip đa lõi…để thực hiện các phép tính
toán trong thời gian thực, nghĩa là tốc độ đáp ứng của nó có thể đủ nhanh cho các
ứng dụng thông thường. OpenCV là thư viện được thiết kế để chạy trên nhiều nền
tảng khác nhau, nghĩa là nó có thể chạy trên hệ điều hành Window, Linux, Mac,…
1.2. Các phép xử lý cơ bản trong OpenCV
1.2.1. Chuyển đổi giữa các không gian màu
Trong OpenCV, các không gian màu được được chuyển đổi qua lại nhờ hàm
cvtColor (convert color), nguyên mẫu hàm này như sau:
cv::cvtColor(cv::InputArray src, cv::OutputArray dst, int code)

Trong đó, src, dst là ảnh gốc và ảnh thu được sau khi chuyển đổi không gian

màu, code là mã chuyển đổi không gian màu. OpenCV định nghĩa khá nhiều
chuyển đổi giữa các không gian màu chẳng hạn như code = CV_BGR2GRAY sẽ
chuyển ảnh ở không gian màu RGB sang ảnh xám, code = CV_HSV2BGR sẽ
chuyển ảnh ở không gian màu HSV sang không gian màu RGB.
1.2.2. Nhị phân hóa ngưỡng động
Trong thư viện OpenCV có hàm để chuyển từ ảnh xám sang ảnh nhị phân với
ngưỡng động là: adaptiveThreshold.
adaptiveThreshold(

InputArray src,
OutputArray dst,
double maxValue,
int adaptiveMethod,
int thresholdType,
int blockSize,
double C);

Trong đó:
- src là ảnh gốc.
- dst là ảnh nhị phân.
- maxValue là giá trị độ sáng lớn nhất trong ảnh (là 255 với ảnh xám).
- adaptiveMethod là cách tính ngưỡng động cho ảnh:
o ADAPTIVE_THRESH_MEAN_C: ngưỡng được tính bằng trung
bình của khu lân cận.
o ADAPTIVE_THRESH_GAUSSIAN_C: ngưỡng được tính bằng
tổng các giá trị lân cận trong cửa sổ Gaussian.
5


-


thresholdType quyết định điểm ảnh sẽ mang màu đen (0) hay màu trắng
(255):
o THRESH_BINARY:
255
dst ( x, y ) = 
0

if ( src( x, y ) ≥ T ( x, y )
otherwise

o THRESH_BINARY_INV:
0
dst ( x, y ) = 
255

-

if ( src( x, y ) ≥ T ( x, y )
otherwise

blockSize là kích thước cửa sổ áp dụng cho việc tính toán ngưỡng động
(nên chọn các giá trị %3 = 0, %5 = 0, %7 = 0).
C là thông số bù trừ trong trường hợp ảnh có độ tương phản quá lớn.

1.2.3. Phép dãn nở
Trong OpenCV, các phép toán hình thái học trong ảnh được cài đặt trong hàm
cv::morphologyEx, riêng phép giãn nở và phép co có thể gọi trực tiếp từ hàm
cv::dilate và cv::erode:
morphologyEx(const Mat& src, Mat& dst, int op, const Mat& element,

Point anchor, int iterations, int borderType, const Scalar&
borderValue)

Trong đó, src, dst là ảnh đầu vào và ảnh sau phép xử lý hình thái học, op là
kiểu lựa chọn phép hình thái học, chẳng hạn như phép giản nở là
MORPH_DILATE, phép đóng là MORPH_OPEN …. element là cấu trúc phần tử
ảnh, có ba cấu trúc cơ bản là theo khối hình vuông, hình chữ thập và hình elip. Để
tạo ra các cấu trúc này ta có thể tự định nghĩa một ma trận với các hình khối tương
ứng hoặc sử dụng hàm getStructuringElement, hàm này có cấu trúc như sau:
getStructuringElement(int shape, Size ksize, Point anchor), với shape là kiểu
hình khối (một trong 3 hình khối trên), ksize là kích thước của hình khối và là khích
thước của hai số nguyên lẻ, anchor là điểm neo và thông thường nhận giá trị là
((ksize.width – 1)/2, (ksize.height – 1)/2). Thông số tiếp theo anchor cũng có ý
nghĩa tương tự iterations là số lần lặp lại của phép toán hình thái.

6


2. TÁCH VÙNG CÔNG THỨC TỪ ẢNH
2.1. Ý tưởng
- Giãn nở các ký tự có trong ảnh để chúng dính lại với nhau
thì khi khoanh vùng thì ta sẽ được vùng văn bản được tách
riêng biệt so với vùng công thức do khoảng cách dòng giữa
2 dòng văn bản nhỏ hơn khoảng cách dòng giữa văn bản và
công thức.
-

Do các công thức được đánh số nên phần bên phải công
thức sẽ có 1 vùng để đánh số cho công thức đó.
Dựa vào đó ta có thể xác định được có những vùng nào có

thể là công thức.

Các bước thực hiện:
- Bước 1: Tiền xử lý file ảnh đầu vào thành ảnh nhị phân.
- Bước 2: Giãn nở các ký tự có trong ảnh.
- Bước 3: Sắp xếp và tìm contour theo chiều từ trên xuống
dưới.
- Bước 4: Tiến hành lưu lại tọa độ các contour.
- Bước 5: Xét 2 contour liên tiếp nhau, nếu thỏa mãn các điều
kiện để contour (i+1) là vùng đánh số của contour (i) thì lưu
lại tọa độ của contour (i).
- Bước 6: Tách contour (i) ra từ ảnh gốc và lưu vào vector ma
trận ảnh để tiến hành tái tạo lại công thức.
2.2. Triển khai và mô tả code
- Bước 1: Tiền xử lý ảnh.
imgTrainingNumbers = cv::imread("fom4.png");

// Doc anh dau vao

cv::cvtColor(imgTrainingNumbers, imgGrayscale,
CV_BGR2GRAY);
// Chuyen anh sang dang anh xam
cv::GaussianBlur(imgGrayscale,

//

imgBlurred,

// Loc nhieu


cv::Size(5, 5),

//

0);

//

cv::adaptiveThreshold(imgGrayscale,

//Lay nguong dong

imgThresh,

//

255,

//

cv::ADAPTIVE_THRESH_GAUSSIAN_C,

//

cv::THRESH_BINARY_INV,

//

11,


//

7


2);

-

//

Bước 2: Giãn nở các ký tự trong ảnh.

cv::Mat kernel = cv::getStructuringElement(MORPH_RECT, Size(25, 13));
cv::morphologyEx(imgThresh, imgThresh, MORPH_DILATE, kernel);

-

Bước 3: Sắp xếp và khoanh contour từ trên xuống dưới.

imgThreshCopy = imgThresh.clone();

// Tao ban copy cua imgThresh

cv::findContours(imgThreshCopy,

//

ptContours,


// Tim cac contour cua anh

v4iHierarchy,

//

cv::RETR_EXTERNAL,

//

cv::CHAIN_APPROX_SIMPLE);

//

sort(ptContours.begin(), ptContours.end(), comparator()); // Sap xep
lai contour tu tren xuong theo toa do y

-

Bước 4: Lưu tọa độ các contour.

for (int i = 0; i < ptContours.size(); i++){
cv::Rect boundingRect = cv::boundingRect(ptContours[i]);// xay dung
duong bien hinh chu nhat bao quanh moi contour
a[i].x = boundingRect.x;
hinh chu nhat

//Luu lai toa do cua cac dinh cua

a[i].y = boundingRect.y;


//bao quanh moi contour

a[i].w = boundingRect.width;

//

a[i].h = boundingRect.height;

//

}

-

Bước 5: Xét 2 contour liên tiếp nhau, nếu thỏa mãn điều kiện contour (i+1)
là chỉ số của contour (i) (bằng cách dùng tọa độ của mỗi contour) thì giữ
lại tọa độ của contour (i).

float consider[10][4];
int j = 0;
for (size_t i = 0; i < ptContours.size(); ++i)
{
if ((a[i].x + a[i].w)<(a[i+1].x))
if ((a[i].y + 2 * a[i].h / 3)>(a[i+1].y))

8


if (a[i].y

if (a[i].w > (a[i+1].w))
{
consider[j][0] = a[i].x;
consider[j][1] = a[i].y;
consider[j][2] = a[i].w;
consider[j][3] = a[i].h;
j++;
}
}

-

Bước 6: Lưu lại ma trận ảnh chứa công thức để tiến hành tái tạo.

vector<Mat> imgConsider;
for (int i = 0; i < 10; i++)
{
if (consider[i][2] > 0)
{
Mat cell = Mat(imgTrainingNumbers, Rect(consider[i][0],
consider[i][1], consider[i][2], consider[i][3]));
imgConsider.push_back(cell);
}
}

2.3. Kết quả thu được
- Ảnh đầu vào.

Hình 1: Ảnh cần tách công thức
-


Ảnh sau khi đã giãn nở các ký tự.

9


Hình 2: Ảnh sau khi giãn nở
-

Ảnh thu được sau khi khoanh vùng công thức: Thu được 2 vùng công thức
như hình dưới.

Hình 3: Ảnh thu được
-

Kết quả thu được với một ảnh đầu vào khác:

10


Hình 4: Kết quả thu được với một ảnh đầu vào khác
2.4. Nhận xét
- Ý tưởng nhận biết vùng công thức dựa vào vùng đánh số của công thức
nên những công thức nào không được đánh số sẽ không khoanh vùng
được.
- Chỉ đúng với trường hợp công thức ngắn, viết trên 1 dòng.

3. TÁCH KÝ TỰ TỪ VÙNG CÔNG THỨC
3.1. Tìm đường biên các ký tự
Khái niệm biên: Biên là một đặc tính rất quan trọng của đối tượng trong ảnh,

nhờ vào biên mà ta phân biệt được đối tượng này với đối tượng kia. Một điểm ảnh
được coi là điểm biên nếu ở đó có sự thay đổi đột ngột về mức xám. Tập hợp các
điểm này được gọi là đường biên hay đường bao ảnh.
Dùng đường biên ta có thể tách được từng ký tự ra trong ảnh bằng cách tạo
một hình chữ nhật bao quanh contour đó. Sau đó ta có thể tách ký tự trong hình chữ
nhật đó ra để xử lý.
Rect boundingRect(InputArray points)

Trong đó boundingRect là hàm được viết sẵn trong OpenCV để tạo một hình
chữ nhật bao quanh contour được trỏ bởi points.
Kết quả thu được:

11


Hình 5: Ký tự được tách ra từ ảnh đầu vào
3.2. Đánh nhãn các ký tự
Chia công thức thành các dòng, từ các dòng đó tìm được dòng chính của công
thức, dựa vào liên hệ của dòng chính với các dòng còn lại (dòng nằm trên hoặc
dưới) ta có thể tìm được mối liên hệ giữa các ký tự trong ảnh.
Cách làm:
- Các contour được sắp xếp từ trái qua phải theo tọa độ x.
- Xét ảnh từ trên xuống dưới theo tọa độ y tăng dần.
- Nếu gặp 1 contour thì lưu lại tọa độ của contour đó đồng thời tìm trong các
contour còn lại xem có thuộc cùng hàng với contour ban đầu hay không
nếu thuộc hàng thì đánh dấu contour đó là đã xét.
- Xét các contour còn lại chưa được đánh dấu thì làm tương tự cho đến khi
không còn contour nào nữa.
- Tìm trong các dòng đó dòng nào chứa contour có thứ tự là 0 từ trái sang
phải thì dòng đó được chọn làm dòng chính.


Kết quả chương trình:

12


Hình 6: Đánh dòng cho các ký tự trong ảnh
Giải thích kết quả:
-

Kết quả trên được in ra từ mảng 2 chiều với số dòng chính là số dòng trong
công thức.
Với dòng 1 có 1 ký tự nằm ở vị trí thứ 10 là ký tự “n”.
Dòng 2 có 1 ký tự nằm ở vị trí 22 là ký tự bình phương.
Dòng 3 có 14 ký tự thuộc dòng chính của công thức được sắp xếp từ trái
qua phải.
Dòng 4 có 2 ký tự i với số thứ tự là 16 và 20 thuộc hàng chỉ số dưới.
Dòng 5 có 3 ký tự là “i = 1” là chỉ số chạy của ký tự tổng.

Tọa độ của các contour được lưu trong một mảng riêng, từ tọa độ này hoàn
toàn có thể tách được các ký tự ra từ ảnh.

4. PHƯƠNG PHÁP NHẬN DẠNG SVM
4.1. Tổng quan về các phương pháp nhận dạng ký tự
4.1.1. Phương pháp tiếp cận cấu trúc
Cách tiếp cận của phương pháp này dựa vào việc mô tả đối tượng nhờ một số
khái niệm biểu diễn đối tượng cơ sở trong ngôn ngữ tự nhiên. Để mô tả đối tượng
13



người ta dùng một số dạng nguyên thuỷ như đoạn thẳng, cung,… Mỗi đối tượng
được mô tả như một sự kết hợp của các dạng nguyên thuỷ.
4.1.2. Phương pháp ngữ pháp (Grammatical Methods)
Các phương pháp ngữ pháp khởi tạo một số luật sinh để hình thành các ký tự
từ một tập các công thức ngữ pháp nguyên thủy. Các luật sinh này có thể kết nối bất
kỳ kiểu đặc trưng thống kê và đặc trưng hình thái nào dưới một số cú pháp hoặc các
luật ngữ nghĩa. Giống như lý thuyết ngôn ngữ, các luật sinh cho phép mô tả các cấu
trúc câu có thể chấp nhận được và trích chọn thông tin theo ngữ cảnh về chữ viết
bằng cách sử dụng các kiểu ngữ pháp khác nhau.
4.1.3. Phương pháp đồ thị (Graphical Methods)
Các đơn vị chữ viết được mô tả bởi các cây hoặc các đồ thị. Các dạng nguyên
thủy của ký tự (các nét) được lựa chọn bởi một hướng tiếp cận cấu trúc. Đối với
mỗi lớp, một đồ thị hoặc cây được thành lập trong giai đoạn huấn luyện để mô tả
các nét, các ký tự hoặc các từ. Giai đoạn nhận dạng gán một đồ thị chưa biết vào
một trong các lớp bằng cách sử dụng một độ đo để so sánh các đặc điểm giống nhau
giữa các đồ thị.
4.1.4. Mô hình Markov ẩn (HMM – Hidden Markov
Model)
Mô hình Markov ẩn (HMM) là một trong những mô hình máy học quan trọng
nhất trong xử lý ngôn ngữ tự nhiên và nhận dạng. Mô hình này là trường hợp mở
rộng của máy hữu hạn trạng thái có hướng, có trọng số. HMM thường được sử dụng
để xử lý những sự kiện không quan sát trực tiếp được (sự kiện ẩn). Do vậy, HMM
được ứng dụng để giải quyết những bài toán có độ nhiễu lớn, chẳng hạn, dự báo,
nhận dạng tiếng nói,…
4.1.5. Đối sánh mẫu
Kỹ thuật nhận dạng chữ đơn giản nhất dựa trên cơ sở đối sánh các nguyên mẫu
(prototype) với nhau để nhận dạng ký tự hoặc từ. Nói chung, toán tử đối sánh xác
định mức độ giống nhau giữa hai véc tơ (nhóm các điểm, hình dạng, độ cong...)
trong một không gian đặc trưng. Các kỹ thuật đối sánh có thể nghiên cứu theo ba
hướng sau:

-

Đối sánh trực tiếp.
Các mẫu biến dạng và đối sánh mềm.
Đối sánh giảm nhẹ.

4.1.6. Mạng Neural (neural networks)
Mạng neural nhân tạo, Artificial Neural Network (ANN) gọi tắt là mạng neural,
neural network, là một mô hình xử lý thông tin phỏng theo cách thức xử lý thông tin
của các hệ neural sinh học. Nó được tạo lên từ một số lượng lớn các phần tử (gọi là
phần tử xử lý hay neural) kết nối với nhau thông qua các liên kết (gọi là trọng số
liên kết) làm việc như một thể thống nhất để giải quyết một vấn đề cụ thể nào đó.

14


Một mạng neural nhân tạo được cấu hình cho một ứng dụng cụ thể (nhận dạng
mẫu, phân loại dữ liệu, ...) thông qua một quá trình học từ tập các mẫu huấn luyện.
Về bản chất học chính là quá trình hiệu chỉnh trọng số liên kết giữa các neural.
4.2. Máy vector hỗ trợ (SVM)
4.2.1. Khái niệm
Phương pháp máy véc tơ tựa (SVM - Support Vector Machines) được đánh giá
là phương pháp học máy tiên tiến đang được áp dụng rộng rãi trong các lĩnh khai
phá dữ liệu và thị giác máy tính…Ý tưởng chính của thuật toán này là cho trước
một tập huấn luyện được biểu diễn trong không gian vector trong đó mỗi tài liệu là
một điểm, phương pháp này tìm ra một mặt phẳng h quyết định tốt nhất có thể chia
các điểm trên không gian này thành hai lớp riêng biệt tương ứng lớp + và lớp -.
Chất lượng của siêu mặt phẳng này được quyết định bởi khoảng cách (gọi là biên)
của điểm dữ liệu gần nhất của mỗi lớp đến mặt phẳng này. Khoảng cách biên càng
lớn thì mặt phẳng quyết định càng tốt đồng thời việc phân loại càng chính xác. Mục

đích thuật toán SVM tìm ra được khoảng cách biên lớn nhất để tạo kết quả phân lớp
tốt.

Hình 7: Siêu phẳng h phân chia dữ liệu huấn luyện thành 2 lớp + và –
4.2.2. Thuật toán SVM
Xét bài toán phân lớp đơn giản nhất – phân lớp hai lớp với tập dữ liệu mẫu:

{(xi, yi) i = 1, 2,…, N, xi ∈ Rm } 11Equation Section
1
Trong đó mẫu là các vector đối tượng được phân lớp thành các
mẫu dương và mẫu âm như trong hình 1:
-

Các mẫu dương là các mẫu xi thuộc lĩnh vực quan tâm và
được gán nhãn
yi = 1.
Các mẫu âm là các mẫu xi không thuộc lĩnh vực quan tâm
và được gán yi = - 1.
15


Thực chất phương pháp này là một bài toán tối ưu, mục tiêu là
tìm ra một không gian H và siêu mặt phẳng quyết định h trên H
sao cho sai số phân lớp là thấp nhất.
Trong trường hợp này, tập phân lớp SVM là mặt siêu phẳng
phân tách các mẫu dương khỏi các mẫu âm với độ chênh lệch cực
đại, trong đó độ chênh lệch – còn gọi là Lề (margin) xác định bằng
khoảng cách giữa các mẫu dương và các mẫu âm gần mặt siêu
phẳng nhất. Mặt siêu phẳng này được gọi là mặt siêu phẳng lề tối
ưu.


Hình 8: Thuật toán SVM với phân lớp 2 lớp
Các mặt siêu phẳng trong không gian đối tượng có phương
trình là:

C + w1 x1 + w2 x2 + … + wn xn = 021Equation
Section 1
313\* MERGEFORMAT (.)
Tương đương với công thức:
i =n

C + ∑ w i xi = 0
i =1

414\*

MERGEFORMAT (.)
Với w = w1 + w2 + …+ wn là bộ hệ số siêu phẳng hay là vector
trọng số, C là độ dịch, khi thay đổi w và C thì hướng và khoảng
cách từ gốc toạ độ đến mặt siêu phẳng thay đổi.
Tập phân lớp SVM được định nghĩa như sau:

16


f ( x) = sign(C + ∑ w i xi )

515\*

MERGEFORMAT (.)


Trong đó
sign(z) = +1 nếu z ≥ 0,
sign(z) = -1 nếu z < 0.
Máy học SVM là một học các siêu phẳng phụ thuộc vào tham
số vector trọng số w và độ dịch C. Mục tiêu của phương pháp SVM
là ước lượng w và C để cực đại hoá lề giữa các lớp dữ liệu dương
và âm. Các giá trị khác nhau của lề cho ta các họ siêu mặt phẳng
khác nhau, và lề càng lớn thì năng lực của máy học càng giảm.
Như vậy, cực đại hoá lề thực chất là việc tìm một máy học có năng
lực nhỏ nhất. Quá trình phân lớp là tối ưu khi sai số phân lớp là cực
tiểu.
Ta phải giải phương trình sau:
1
C ∑η + w
min
η
2
l

w,b ,

i =1

2

i

yi [w.xi − b] + ηi ≥ 1


ηi ≥ 0, i = 1,...l

616\*

MERGEFORMAT (.)
Ta tìm ra được vector trọng số w và sai số của mỗi điểm trong
tập huấn luyện là ηi từ đó ta có phương trình tổng quát của siêu
phẳng tìm ra được bởi thuật toán SVM là:
n

f ( x1 , x2 ,...xn ) = C + ∑ w i xi
i =1

717\*

MERGEFORMAT (.)
Trong đó n là số dữ liệu huấn luyện. Sau khi đã tìm được
phương trình của siêu phẳng bằng thuật toán SVM, áp dụng công
thức này để tìm ra nhãn lớp cho các dữ liệu mới.
4.2.3. Huấn luyện SVM
Huấn luyện SVM là việc giải bài toán quy hoạch toàn phương SVM. Các
phương pháp số giải bài toán quy hoạch này yêu cầu phải lưu trữ một ma trận có
17


kích thước bằng bình phương của số lượng mẫu huấn luyện. Trong những bài toán
thực tế, điều này là không khả thi vì thông thường kích thước của tập dữ liệu huấn
luyện thường rất lớn (có thể lên tới hàng chục nghìn mẫu). Nhiều thuật toán khác
nhau được phát triển để giải quyết vấn đề nêu trên. Những thuật toán này dựa trên
việc phân rã tập dữ liệu huấn luyện thành những nhóm dữ liệu. Điều đó có nghĩa là

bài toán quy hoạch toàn phương với kích thước nhỏ hơn. Sau đó, những thuật toán
này kiểm tra các điều kiện KKT (Karush-KuhnTucker) để xác định phương án tối
ưu.

5.

NHẬN DẠNG KÝ TỰ TOÁN HỌC BẰNG SVM

5.1. Ý tưởng
Phương pháp SVM trong khuôn khổ của đồ án 1 có thể hiểu đơn giản như sau:
Cho một tập các mẫu huấn luyện, với mỗi mẫu ta sẽ gắn một nhãn, quá trình huấn
luyện SVM sẽ xây dựng một mô hình cho phép một tập dữ liệu khác thuộc về nhãn
nào, tức là phân loại tập dữ liệu đó thuộc lớp nào.
SVM là bộ máy phân loại dữ liệu, để dùng được ta cần có dữ liệu, dữ liệu đối
với các ký tự toán học mà ta cần nhận dạng chính là các đặc trưng trong ảnh của ký
tự đó. Giả sử ta cần phân loại dữ liệu của 60 lớp dữ liệu tương ứng với 60 ký tự toán
học khác nhau, với mỗi lớp dữ liệu ta tính toán được 10 vector đặc trưng, mỗi
vector đặc trưng tương ứng với các đặc trưng trong một ảnh.
Khi đã có được dữ liệu huấn luyện ta sẽ đưa vào bộ huấn luyện SVM. Để nhận
dạng một ảnh ta sẽ tính toán một vector đặc trưng của ảnh đó, mô hình SVM sẽ xem
xét vector đặc trưng này thuộc vào lớp nào trong số những lớp mà nó đã được huấn
luyện.
Kết quả cuối cùng của việc nhận dạng ký tự là ta sẽ in ra được mã Unicode
của ký tự cần nhận dạng.
5.2. Tính toán đặc trưng trong ảnh
Để phân biệt được hai ảnh ta cần phải tính được các đặc trưng của mỗi ảnh.
Trong phần này ta sẽ tính toán dựa trên ý tưởng của phương pháp Haar – like, giá trị
của đặc trưng Haar-like được xây dựng bởi độ chênh lệch giữa tổng các pixel của
các vùng đen so với tổng các pixel của các vùng trắng.
Giả sử ta có hai ký tự là 0 và 4, đưa hai ký tự này về cùng kích thước, chia nhỏ

các ký tự thành 16 ô nhỏ khác nhau:

18


Hình 9: Tính toán đặc trưng trong ảnh
Ta nhận thấy rằng nếu tính tổng các pixel đen trong các ô của hai bức ảnh thì
số 0 và số 4 có thể phân biệt dựa vào các ô (1,1), (1, 4), (2, 2), (3,3) … tại những ô
đó, tổng số các điểm ảnh đen là khác nhau hoàn toàn. Tính toán số điểm ảnh đen
của 16 ô vuông này ta có thể thu được 16 đặc trưng của một ảnh, 16 đặc trưng này
đủ để phân biệt kí tự 0 và 4.
Tuy nhiên, với 60 kí tự ta cần phải tính toán nhiều hơn các đặc trưng, các đặc
trưng không nhất thiết phải là 0 (tức không có điểm ảnh đen nào) hặc 1(tức là toàn
số điểm ảnh đen trong ô) mà có thể là một tỉ lệ tương đối nào đó. Từ 16 đặc trưng
cơ bản trên, ta kết hợp chúng lại để tạo ra những đặc trưng khác, chẳng hạn như lấy
tổng các đặc trưng trên đường chéo (1,1) + (2,2) + (3,3) + (4,4) hoặc tổng các đặc
trưng xung quanh đường biên của ảnh…
//-----------------Ham tinh toan dac trung-----------------------//
vector<float> calculator_feature(Mat imgTrainingNumbers)
{
//khau xu ly anh
Mat imgGrayscale;
Mat imgThresh;
Mat matROIResized;
cvtColor(imgTrainingNumbers, imgGrayscale, CV_BGR2GRAY);
adaptiveThreshold(imgGrayscale, imgThresh, 255,
ADAPTIVE_THRESH_GAUSSIAN_C,
THRESH_BINARY_INV, 11, 2);
resize(imgThresh, matROIResized,
Size(RESIZED_IMAGE_WIDTH, RESIZED_IMAGE_HEIGHT));

//khau tinh toan cac dac trung
vector<float> r;

19


int ww = matROIResized.rows / 4;
int hh = matROIResized.cols / 4;
int S = count_pixel(matROIResized);
int T = matROIResized.cols * matROIResized.rows;
for (int i = 0; i < matROIResized.rows; i += ww)
for (int j = 0; j < matROIResized.cols; j += hh)
{
Mat cell;
Coordinate top_left;
Coordinate bottom_right;
top_left.xx = i;
top_left.yy = j;
bottom_right.xx = top_left.xx + ww;
bottom_right.yy = top_left.yy + hh;
cell = matROIResized(Rect(i, j, ww, hh));
int s = count_pixel(cell);
float f = (float)s / S;
r.push_back(f);
}
for (int i = 0; i < 16; i += 4)
{
float f = r[i] + r[i + 1] + r[i + 2] + r[i + 3];
r.push_back(f);
}

for (int i = 0; i < 4; ++i)
{
float f = r[i] + r[i + 4] + r[i + 8] + r[i + 12];
r.push_back(f);
}
r.push_back(r[0] + r[5] + r[10] + r[15]);
r.push_back(r[3] + r[6] + r[9] + r[12]);
r.push_back(r[0] + r[1] + r[4] + r[5]);
r.push_back(r[2] + r[3] + r[6] + r[7]);
r.push_back(r[1] + r[2] + r[5] + r[6]);
r.push_back(r[4] + r[5] + r[8] + r[9]);
r.push_back(r[5] + r[6] + r[9] + r[10]);

20


r.push_back(r[7] + r[6] + r[10] + r[11]);
r.push_back(r[8] + r[9] + r[13] + r[12]);
r.push_back(r[9] + r[10] + r[13] + r[14]);
r.push_back(r[10] + r[11] + r[15] + r[15]);
r.push_back(r[0] + r[3] + r[4] + r[7]);
r.push_back(r[4] + r[7] + r[8] + r[11]);
r.push_back(r[3] + r[6] + r[9] + r[12]);
r.push_back(r[8] + r[11] + r[12] + r[15]);
r.push_back(r[0] + r[1] + r[12] + r[13]);
r.push_back(r[1] + r[2] + r[13] + r[14]);
r.push_back(r[2] + r[3] + r[14] + r[15]);
return r;
// 42 dac trung trong anh.
}


Trong đó hàm count_pixel là hàm tính toán số pixel đen trong một ảnh:
int count_pixel(Mat img)
{
int white = 0;
for (int i = 0; i < img.rows; ++i)
for (int j = 0; j < img.cols; ++j)
{
if (img.at<uchar>(i, j) != 0)
white++;
}
return white;
}

5.3. Tạo cơ sở dữ liệu
Ta cần chuẩn bị cơ sở dữ liệu là tập hợp của các kí tự toán học có trong bảng
mã Unicode. Trong khuôn khổ đồ án này chúng em lập cơ sở dữ liệu của 60 kí tự
thường gặp trong toán học, do đó ta cần phân loại 60 lớp này, trong trường hợp ở
đây giả sử với mỗi lớp, tức là mỗi ký tự ta có 6 ảnh, ta sẽ lưu các ảnh này vào các
folder, tên các folder được đặt theo tên mã của ký tự đó trong bảng mã Unicode,
chẳng hạn như folder u03A0 chứa 6 ảnh của kí tự số PI,…Việc đánh tên folder theo
mã Unicode là vì tên folder cũng chính là nhãn để đưa vào nhận dạng. Khi biết
được ký tự cần nhận dạng có nhãn là gì tức là biết mã Unicode của ký tự đó thì ta sẽ
dễ dàng in ký tự đó ra.
21


Hình 10: Dữ liệu huấn luyện được lưu vào các folder
5.4. Huấn luyện
5.4.1. Kịch bản huấn luyện

Dữ liệu huấn luyện sẽ được lưu vào một thư mục có đường dẫn D:/Data, ta sẽ
đọc lần lượt các folder con trong thư mục Data và tính toán các đặc trưng của ảnh
rồi lưu vào ma trận có tên là data. Tên của folder cũng chính là mã Unicode sẽ
được lưu vào ma trận label. Trong opencv hỗ trợ hàm trainAuto sẽ thực hiện việc
huấn luyện một cách tự động và tối ưu các thông số của mô hình. Các thông tin thu
được sau khi huấn luyện sẽ được lưu vào file svm.xml tại đường dẫn E:/svm.xml.
const int number_of_class = 60; //So ky tu trong toan hoc
const int number_of_sample = 6; //So mau ung voi moi ky tu
const int number_of_feature = 42;//So dac trung cua mot mau
float data[number_of_class*number_of_sample][number_of_feature];
float label[number_of_class*number_of_sample];
int main()
{
int index = 0;
string path = "D://Data//";
vector<string> folders = list_(path);
vector<string> files;
for (size_t i = 0; i < folders.size(); ++i)
{
string Path = path + folders.at(i);
files = list_(Path);
for (size_t j = 0; j < files.size(); ++j)
{
string Path2 = Path + "//" + files.at(j);
Mat imgTrainingNumbers = cv::imread(Path2);

22


vector<float> features =

calculator_feature(imgTrainingNumbers);
if (features.size() < number_of_feature)
{
std::cout << "error" << std::endl;
continue;
}
for (size_t t = 0; t < features.size(); ++t)
data[index][t] = features.at(t);
label[index] = i;
index++;
}
}
Mat labelsMat(number_of_class*number_of_sample, 1, CV_32SC1,
label);
Mat trainingDataMat(number_of_class*number_of_sample,
number_of_feature, CV_32FC1, data);
// Set up SVM's parameters
Ptr<SVM> svm = SVM::create();
svm->setType(SVM::C_SVC);
svm->setKernel(SVM::LINEAR);
svm->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER, 100,
1e-6));
Ptr<TrainData> td = TrainData::create(trainingDataMat,
ROW_SAMPLE, labelsMat);
//train the SVM with optimal parameters
svm->trainAuto(td);
svm->save("E://svm.xml");
return 0;
}


Trong đó hàm list_ là hàm đọc các folder chứa dữ liệu được viết dựa trên thư
viện dirent.h:
vector<string> list_(string path)
{
DIR *dp;

23


struct dirent *ep;
dp = opendir(path.c_str());
vector<string> prepare;
if (dp != NULL)
while (ep = readdir(dp)){
string Ep = (ep->d_name);
if ((!strcmp(Ep.c_str(), ".")) || (!strcmp(Ep.c_str(),
".."))){
}
else
prepare.push_back(Ep);
}
closedir(dp);
return prepare;
}

5.4.2. Thông số huấn luyện
// Set up SVM's parameters
Ptr<SVM> svm = SVM::create();
svm->setType(SVM::C_SVC);
svm->setKernel(SVM::LINEAR);

svm->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER, 100,
1e-6));

-

setType: Thông số này thể hiện loại mô hình SVM được chọn, ở đây là
SVM::C_SVC cho phép phân loại n lớp dữ liệu với n ≥ 2.
setKernel: SVM là một họ các phương pháp dựa trên cơ sở các hàm nhân
(kernel) để tối thiểu hóa rủi ro ước lượng, setKernel là loại hàm nhân sẽ
dùng, ở đây là SVM::LINEAR, không có ánh xạ được thực hiện,

K ( xi , x j ) = xiT x j

-

.
setTermCriteria: Tiêu chuẩn kết thúc các thuật toán lặp. MAX_ITER là
loại setTermCriteria, sau max_iter lần lặp thì sẽ dừng lại, ở đây max_iter =
100, độ chính xác là 1e-6.

24


6.

KẾT QUẢ

Kết quả cuối cùng của việc nhận dạng là ta sẽ lấy được mã Unicode của ký tự
cần nhận dạng từ cơ sở dữ liệu. Dựa vào mã Unicode có được ta sẽ xây dựng
chương trình xuất ra ký tự trong bảng mã Unicode và nhận được ký tự cần nhận

dạng, sau đó tái tạo lại công thức toán học hoàn chỉnh như trong ảnh đầu vào.
6.1. Kết quả nhận dạng từng ký tự
Kết quả nhận dạng chính xác các ký tự:

Hình 11: Ký tự ∑ được nhận dạng chính xác

25


×