Mục lục
Phần mở đầu 1
Chương 1: Giới thiệu bài toán và giải pháp 3
1.1. Vấn đề đăng nhập tự động 3
1.2. Tác hại của đăng nhập tự động 3
1.3. Phương pháp giải quyết 4
1.3.1. Giải pháp 4
1.3.2. Ảnh xác nhận là gì? 6
1.3.3. Hoạt động của ảnh xác nhận 6
1.3.4. Tại sao không sử dụng các ảnh lưu trữ trong cơ sở dữ liệu? 6
1.4. Giải pháp sinh ảnh tự động đã có người thực hiện chưa? Thực hiện như thế nào và có thể sử dụng lại được không? 7
1.4.1. Giải pháp đã có của yahoo, hotmail, gmail 7
1.4.2. Giải pháp có mã nguồn mở 9
Chương 2: Cơ sở lý thuyết 12
2.1. Thuật toán sinh chuỗi ngẫu nhiên 12
2.1.1. Tại sao lại sinh chuỗi gồm từ 6 đến 12 ký tự? 12
2.1.2. Kỹ thuật biến đổi chuỗi thành ảnh 13
2.2. Các thuật toán sinh ảnh nền 14
2.2.1. Tại sao phải sinh ảnh nền? 14
2.2.2. Sinh ảnh nền dạng dải màu (ribbon) 14
2.2.3. Sinh ảnh nền dạng vải sợi(Fabric) 15
2.2.4. Sinh ảnh nền dạng bàn cờ(Checkboard) 16
2.2.5. Sinh ảnh nền dạng tổ ong(Beehive) 18
2.2.6. Sinh ảnh nền dạng sóng(Wave) 19
2.2.7. Sinh ảnh nền dạng các hình chữ nhật(Rectangle) 20
2.2.8. Sinh ảnh nền dạng các đường tròn đồng tâm(HomoCentricCircle) 21
2.2.9. Sinh ảnh nền dạng các đường tròn ngẫu nhiên(RandCircle) 22
2.2.10. Sinh ảnh nền dạng đá hoa cương (Granite) 23
2.2.11. Sinh ảnh nền dạng thác nước (waterfall) 24
2.3. Các thuật toán biến đổi bề mặt 25
2.3.1. Tại sao phải biến đổi bề mặt? 25
2.3.2. Thuật toán biến đổi theo hình sin 25
2.3.3. Thuật toán biến đổi hình thang 27
2.3.4. Thuật toán biến đổi hình bình hành 29
2.4. Các thuật toán gây nhiễu bề mặt 30
2.4.1. Tại sao phải gây nhiễu bề mặt ? 30
2.4.2. Gây nhiễu bằng các điểm ngẫu nhiên 30
2.4.3. Gây nhiễu bằng các đường thẳng ngẫu nhiên 31
2.4.4. Gây nhiễu bằng các đường cong ngẫu nhiên 33
2.4.5. Gây nhiễu bằng các đường tròn ngẫu nhiên 34
2.4.6. Kết hợp các kiểu gây nhiễu 36
Chương 3: Triển khai thành phần 39
3.1. Cấu trúc của tập tin ảnh bitmap 39
3.1.1. Tiêu đề ảnh 39
3.1.2. Thông tin ảnh 40
3.1.3. Bảng màu 41
3.1.4. Dữ liêu ảnh 42
3.2. Thủ tục hỗ trợ để triển khai chương trình 42
3.2.1. Cấu trúc ảnh 42
3.1.2. Thủ tục hỗ trợ 42
3.3. Tạo và sử dụng thành phần phục vụ 44
3.3.1. Định nghĩa ActiveX DLL 44
3.3.2. Cách tạo ra thành phần phục vụ 45
3.3.3. Sử dụng thành phần trong trang tin 46
3.4. Trang tin sử dụng thành phần 46
3.4.1. Cách viết trang đăng nhập 46
3.4.2. Cách viết trang xử lý đăng nhập 47
Chương 4: Thực nghiệm 48
4.1. Môi trường thực nghiệm 48
4.2. Thực nghiệm và kết quả 48
4.3. Các vấn đề phát sinh 49
Kết luận 51
Tài liệu tham khảo 52
Phụ lục A – Danh mục các thuật toán 53
Phụ lục B – Danh sách các hình 54
57 trang |
Chia sẻ: lethao | Lượt xem: 1518 | Lượt tải: 4
Bạn đang xem trước 20 trang tài liệu Khóa luận Xây dựng thành phần sinh ảnh chống đăng nhập tự động, để xem tài liệu hoàn chỉnh bạn click vào nút DOWNLOAD ở trên
eviceCaps(dc,HORZRES), GetDeviceCaps(dc, VERTRES))
tạo một ảnh bitmap tương ứng với chiều rộng và chiều cao của thiết bị ngữ cảnh
Hàm GetDeviceCaps(dc, HORZRES) trả về thông tin chiều ngang của thiết bị ngữ cảnh
Hàm GetDeviceCaps(dc, VERTRES) trả về thông tin chiều cao của thiết bị ngữ cảnh
Hàm SelectObject(memdc, bmp) chọn một ảnh bitmap đưa vào bộ nhớ thiết bị ngữ cảnh, ảnh mới sẽ thay thế ảnh cũ
Hàm SetFontForText(memdc, fontname, fontsize) xác định kiểu chữ và kích cỡ cho chuỗi ảnh
Hàm SetTextColor(memdc, RGB(0,0,0)) xác định màu của chuỗi ảnh
Hàm GetTextExtentPoint(memdc, str, strlen(str), &sz) trả về chiều dài chuỗi ký tự
Hàm TextOut(memdc, 0, 0, str, strlen(str)) ghi chuỗi ký tự ra bộ nhớ thiết bị ngữ cảnh
GetPixel(memdc, k, i): trả về mầu của điểm ảnh (i, k) cho bộ nhớ thiết bị ngữ cảnh
sz: kích cỡ của chuỗi ngẫu nhiên
2.2. Các thuật toán sinh ảnh nền
2.2.1. Tại sao phải sinh ảnh nền?
Với những ảnh đơn giản, chương trình nhận dạng dễ dàng thực hiện việc tách cạnh, tìm biên, tách chuỗi ảnh ra khỏi nền để sau đó có thể thực hiện việc dò chuỗi ảnh ngẫu nhiên được sinh ra. Vì vậy để làm cho các thuật toán tách cạnh, tìm biên không hiệu quả chúng tôi sẽ cho sinh ra những nền có cấu trúc phức tạp hơn.
2.2.2. Sinh ảnh nền dạng dải màu (ribbon)
Các dải màu được tạo ra rất đơn giản bằng cách sử dụng hàm tuyến tính hai biến. Phương pháp sinh là duyệt tất cả các điểm. Với mỗi điểm ta thay giá trị màu bằng giá trị của hàm số. Hàm số để sinh dải màu như sau:
f(x, y) = 255 – a*x – b*y
Trong chương trình, chúng tôi sử dụng ảnh 256 màu do đó phương trình chỉ cần cho hệ số 255. Trong trường hợp tổng quát, chúng ta có thể sử dụng phương trình đường thẳng:
f(x, y) = a*x + b*y + c
Có thể viết đơn giản thuật toán sinh dưới ngôn ngữ tựa lập trình như sau
void GenRibbon(left, right, top, bottom)
{ for(x=left; x<right; x++)
for(y=top; y<bottom; y++){
t = 255 – 8x – 6y;
SetPixel(x, y, RGB(t+rand()%128, t+rand()%128, t));
}
}
Kết quả sau khi áp dụng thuật toán:
Hình 8: Ảnh nền dạng dải màu
2.2.3. Sinh ảnh nền dạng vải sợi(Fabric)
Miếng vải thường được trang trí với mẫu khác nhau. Các mẫu này được tạo ra bằng cách lặp lại một mẫu nguyên tố nào đó. Chúng tôi không dùng phương pháp này mà sử dụng hàm sin và cos vì bản thân hai hàm này tuần hoàn dẫn đến việc các mẫu tự động lặp lại. Công thức để sinh nền vải sợi như sau:
Có thể viết đơn giản thuật toán sinh dưới ngôn ngữ tựa lập trình như sau:
void GenFabric(left, right, top, bottom)
{
for(x=left; x<=right; x++)
for(y= top;y<=bottom; y++){
pixel=
SetPixel(x, y, RGB(pixel, pixel, pixel));
}
}
Kết quả sau khi áp dụng thuật toán
Hình 9: Ảnh nền dạng vải sợi
2.2.4. Sinh ảnh nền dạng bàn cờ(Checkboard)
Bàn cờ caro là bàn cờ gồm các ô đỏ và đen xen kẽ nhau. Để sinh ra bàn cờ caro chúng ta cần duyệt tất cả các điểm x, y theo chiều ngang và chiều dọc màn hình sau đó xác định vị trí của những ô mầu đỏ và đen để tô mầu tương ứng. Ở đây chúng tôi sử dụng hàm floor để xác định vị trí của các ô đỏ và đen.
Công thức để sinh bàn cờ như sau:
()
Trong đó
Hàm là hàm tìm số nguyên lớn nhất dưới
Hàm là hàm tìm số nguyên lớn nhất dưới
Ở đây độ lớn của các ô cờ phục thuộc vào hệ số của k. Nếu trị tuyệt đối của k càng nhỏ thì độ lớn của các ô cờ càng lớn. Ngược lại, trị tuyệt đối của k lớn độ lớn của các ô cờ càng nhỏ. Tuy nhiên việc lựa chọn các giá trị cho hàm RGB() cũng rất quan trọng, nó sẽ quyết định màu sắc của bàn cờ.
Có thể viết đơn giản thuật toán dưới ngôn ngữ giả lập trình như sau
void GenCheckboard(left, right, top, bottom)
{
for(x<left; x<right; x++)
for(y=top; y<bottom; y++){
t = floor(x*0.7/12 ) + floor(y*0.7/12);
SetPixel(x, y, RGB(t*256, t*256,t*128));
}
}
Kết quả sau khi áp dụng thuật toán
Hình 10: Ảnh nền dạng bàn cờ
2.2.5. Sinh ảnh nền dạng tổ ong(Beehive)
Xuất phát từ ý tưởng là các tổ ong thường gồm các ô tròn được sắp xếp rất đều nhau. Chúng ta có thể sinh ra kiểu nền này bằng cách sinh một mẫu tròn rồi sao chép lại nhiều lần mẫu này theo một hệ số nào đó. Tuy nhiên chúng tôi có thể tạo ra kiểu nền này bằng cách kết hợp hai hàm sin và cos bởi các hàm này là các hàm tuần hoàn dẫn đến khi kết hợp với nhau tạo thành các mẫu tròn tự động lặp. Công thức để sinh nền tổ ong như sau:
Trong công thức này việc lựa chọn các giá trị của a và b cũng quyết định độ lớn và mức độ tròn của tổ ong. Trong quá trình triển khai chúng tôi chọn giá trị của b nằm trong khoảng (-1,1) và giá trị của b thường lớn hơn 1.
Thuật toán để sinh nền kiểu tổ ong có thể được viết dưới ngôn ngữ tựa lập trình như sau:
void GenBeehive(left, right, top, bottom)
{ for(x<left; x<right; x++)
for(y<top; y<bottom; y++){
t = sin(x*cos(2)/3 ) + cos(y*cos(2)/3);
SetPixel(x,y, RGB(t*10, t*16, t*40));
}
}
Kết quả sau khi áp dụng thuật toán
Hình 11: Ảnh nền kiểu tổ ong
2.2.6. Sinh ảnh nền dạng sóng(Wave)
Các con sóng được tạo ra đơn giản bằng cách duyệt tất cả các điểm, mỗi điểm ta thay giá trị màu bằng giá trị của hàm số. Hàm số là tổng của một hàm sin và toạ độ chiều cao của của ảnh. Các toạ độ ứng với chiều ngang của ảnh cho làm đối số của hàm sin.
Công thức để vẽ con sóng:
Công thức có thể được triển khai dưới ngôn ngữ tựa lập trình như sau:
void GenWave(left, right, top, bottom)
{
for(x= left; x<right; x++)
for(y= top; y<bottom; y++)
{
t = sin(x*sin(-1)/12 ) + (y*sin(-1)/15);
SetPixel(x, y, RGB(t*19,t*12, t*256));
}
}
Kết quả sau khi áp dụng thuật toán
Hình 12: Ảnh nền dạng sóng
2.2.7. Sinh ảnh nền dạng các hình chữ nhật(Rectangle)
Chúng tôi sử dụng công thức để sinh các hình chữ nhật như sau:
Trong đó
là hàm tính sine hyperbolic của
là hàm xác định số nguyên bé nhất trên
Công thức được triển khai như sau:
void GenRectangle(left, right, top, bottom)
{
for(x= left; x<right; x++)
for(y= top; y<bottom; y++)
{
t = sinh(x*tan(128)/25 ) + ceil(y*tan(128)/5);
SetPixel(x, y, RGB(t*128,t*128, t*128));
}
}
Kết quả sau khi áp dụng thuật toán
Hình 13: Ảnh nền dạng hình chữ nhật
2.2.8. Sinh ảnh nền dạng các đường tròn đồng tâm(HomoCentricCircle)
Công thức để sinh đường tròn đồng tâm
Thuật toán có thể được triển khai dưới dạng giả mã như sau:
void GenHoCenCirlce(left, right, top, bottom)
{
for(x = left; x<right; x++)
for(y = top; y<bottom; y++)
{
t = floor(x*y*tan(122)/12);
SetPixel(x, y, RGB(t*128, t*128,t*128));
}
}
Trong quá trình triển khai công thức chúng tôi thấy rằng việc lựa chọn các giá trị cho hàm RGB() rất quan trọng, vì vậy chúng tôi đã chọn các giá trị của hàm RGB() như trên
Kết quả sau khi áp dụng thuật toán
Hình 14: Ảnh nền các đường tròn đồng tâm
2.2.9. Sinh ảnh nền dạng các đường tròn ngẫu nhiên(RandCircle)
Sinh các đường tròn ngẫu nhiên đơn giản chỉ là tại các vị trí ngẫu nhiên nào đó trong không gian của bức tranh cần vẽ ta tô màu cho các đường tròn với bán kính khác nhau. Trong chương trình chúng tôi sử dụng hàm Ellipse để vẽ các đường tròn.
Có thể viết thuật toán như sau:
void GenRanCircle(HDC dc, int width, int height) {
for(int i=0; i<150; i++) {
int x = rand()%(width);
int y = rand()%(height);
int r = 10 + rand()%10;
Ellipse(dc, x-r, y-r, x+r, y+r);
}
}
Kết quả sau khi áp dụng thuật toán
Hình 15: Ảnh nền là các đường tròn ngẫu nhiên
2.2.10. Sinh ảnh nền dạng đá hoa cương (Granite)
Đá hoa cương là một mảnh đá được tạo ra từ các hạt cát có các màu khác nhau. Do đó chúng ta có thể tạo ra đá hoa cương bằng cách đơn giản là đưa ra ngẫu nhiên các điểm có màu khác nhau.
void granite(left, right, top, bottom)
{
for(x=left; x<=right; x++)
for(y=top; y<=bottom; y++)
{
t = 120 + rand()%128;
SetPixel(x,y, RGB(t*rand()%128, t*rand()%128, t*rand()%128));
}
}
Kết quả sau khi áp dụng thuật toán
Hình 16: Ảnh nền dạng đá hoa cương
2.2.11. Sinh ảnh nền dạng thác nước (waterfall)
Thác nước theo cách nhìn đơn giản chỉ là tập hợp các giọt nước song song đi từ đỉnh ảnh xuống đáy ảnh. Trong đó độ dài các giọt cũng như vị trí xuất phát của các giọt là ngẫu nhiên.
Để tạo ra thác nước cần duyệt theo chiều ngang ảnh trước. Tại mỗi vị trí chiều ngang ta sẽ xây dựng giọt nước từ trên đỉnh ảnh xuống đáy ảnh. Tất nhiên là số điểm từ đỉnh tới đáy phải bằng đúng độ cao ảnh cần sinh. Do đó chúng ta cần duyệt theo chiều dọc của ảnh. Nhưng màu bắt đầu vẽ là một màu ngẫu nhiên r và độ lặp lại của màu hay độ dài của giọt nước là s ngẫu nhiên. Do vậy thuật toán của chúng ta như sau
void waterfall(left, right, top, bottom) {
for(x=left; x<=right; x++) {
s = (rand()%256)<<10;
r = 256+rand()%128<<3;
for(y=top; y<=bottom; y++, r+=s);
SetPixel(x, y, RGB(r + y, r + y, r + y));
}
}
Kết quả sau khi áp dụng thuật toán
Hình 17: Ảnh nền Waterfall
2.3. Các thuật toán biến đổi bề mặt
2.3.1. Tại sao phải biến đổi bề mặt?
Ngày nay có rất nhiều hệ nhận dạng rất nhạy, chúng có thể nhận dạng được chuỗi ảnh nếu kiểu của chuỗi là kiểu có sẵn trong hệ thống windows như chuỗi được làm béo, chuỗi nghiêng theo kiểu italic hay chuỗi được gạch chân. Do đó để tránh cho hệ nhận dạng này có thể phát hiện, chúng tôi đã thực hiện việc biến đổi bề mặt các chuỗi theo các cách khác nhau như biến bề mặt chuỗi thành dạng cong hình sin, biến chuỗi ảnh thành dạng hình thang, hình bình hành. Mỗi khi chuỗi ảnh được sinh ra, chúng sẽ được làm biến đổi bề mặt ngẫu nhiên có thể cong theo hình sin, hoặc có thể biến dạng theo kiểu hình thang hoặc cũng có thể biến dạng thành hình bình hành.
2.3.2. Thuật toán biến đổi theo hình sin
Tư tưởng của thuật toán rất đơn giản, từ chuỗi ảnh ban đầu, copy chuỗi ảnh đến vị trí đã được làm cong sẵn. Như ta đã biết hàm sin, cos khi biểu diễn trên mặt phẳng toạ độ nó là một đường cong. Do đó ta sẽ copy chuỗi ảnh ban đầu và ghi lại dưới dạng một hàm của sin. Kết quả là sau khi thực hiện việc copy như trên chuỗi mà chúng ta ghi lại trên nền là một chuỗi cong theo dạng hình sin.
Trong quá trình triển khai chúng tôi thực hiện việc biến đổi trên bộ nhớ DC, đây là kiểu bộ nhớ lưu trữ các ảnh vào trong bộ nhớ trước khi gửi chúng tới thiết bị ra, do đó toạ độ các điểm mới sẽ được tính theo công thức:
x ‘= x
y’ = y + a*sin(x/b)
Trong đó:
(x, y) là toạ độ ban đầu mà chuỗi được sinh ra
( x ‘, y’ ) là toạ độ sau khi được biến đổi
Quá trình biến đổi ảnh thành dạng hình sin đã được triển khai như sau:
Chúng tôi sử dụng vùng nhớ DC khi xuất ra màn hình có kích thước (400, 400). Trước tiên chúng tôi sinh chuỗi ngẫu nhiên trên vùng nhớ DC đó tại toạ độ (10, 300), đồng thời một ảnh nền có kích thước (400, 200) cũng được sinh trên DC tại toạ độ (0,0). Sau đó chúng tôi thực hiện việc copy chuỗi vừa sinh ra lên vùng nhớ có chứa ảnh nền theo công thức như trên. Do ảnh nền có kích thước (400, 200) nên khi lưu lại chúng ta chỉ nhận được ảnh với chuỗi đã được làm cong.
Thuật toán được viết dưới ngôn ngữ lập trình như sau:
void VariWithSin(){
CreateDC(400, 400) //Tạo vùng nhớ DC
RandomString(str) //Sinh chuỗi ngẫu nhiên
GenHoCenCircle(memdc, 400, 200); //Sinh nền
TextOut(memdc, 10, 300, str, strlen(str)); //Ghi chuỗi ra bộ nhớ memdc
for(i=0; i<str.width; i++) {
for(k=0; k<str.height; k++) {
long t = GetPixel(memdc, 10+k, 300+i);
SetPixel(memdc, k+10, i+10*sin(k/18.0)+75, t);
}
}
Quá trình thực hiện biến đổi được minh hoạ theo hình dưới đây
Hình 18: Minh hoạ quá trình thực hiện biến đổi chuỗi ảnh theo hình sin
Sau khi triển khai chương trình chúng tôi thu được kết quả như sau:
Hình 19: Chuỗi ảnh cong theo hình sin
Nhận xét: Với việc làm cong như trên, các hệ nhận dạng mặc dù có thể đọc được chuỗi ảnh trên nhưng rất dễ bị nhầm giữa các ký tự. Chúng sẽ không thể phân biệt được số 2 tại vị trí thứ 2 là chữ số “2” hay là chữ “z”, chữ “o” tại vị trị thứ 3 là chữ “o” hay số “0”, chữ o tại vị trí thứ 6 là chữ o hay chữ “D”, chữ s tại vị trí thứ 7 là chữ “s” hay số “5”. Do đó việc đăng nhập tự động rất khó thực hiện được.
2.3.3. Thuật toán biến đổi hình thang
Công thức biến đổi tứ giác chúng tôi sử dụng được tính theo chiều trải xuống y trước và chiều ngang x sau. Các điểm mới (x', y') sẽ được tính theo công thức
Trong đó các hệ số (xAy, yAy) và (xBy, yBy) là các đầu đường thẳng nằm ngang phụ thuộc vào y theo công thức sau
Trong quá trình triển khai chúng tôi đã thực hiện việc biến đổi hình thang theo hai trường hợp:
Trường hợp 1: Đáy lớn ở dưới, đáy nhỏ ở trên
Trường hợp 2: Đáy lớn ở trên, đáy nhỏ ở dưới
Sau khi áp dụng thuật toán ta thu được kết quả như sau:
Hình 20a: Đáy nhỏ ở trên, đáy lớn ở dưới
Hình 20b: Đáy lớn ở trên, đáy nhỏ ở dưới
Hình 20: Minh hoạ biến đổi theo hình thang
Nhận xét: Việc biến đổi chuỗi ảnh theo dạng hình thang làm cho các chữ bị nghiêng không theo một hướng nhất định, mà ta biết rằng việc nhận dạng chữ phải theo một mẫu nhất định do đó khi hướng hoặc độ nghiêng luôn luôn thay đổi thì việc nhận dạng không thể thực hiện được. Đồng thời khi biến đổi theo kiểu hình thang, nhiều chữ bị biến đổi đi làm cho hệ nhận dạng không thể xác định đó là chữ gì, ví dụ số “1” và số “7”, chữ “p” và “D”, chữ “g” và số “9” khi biến đổi đi trông khá giống nhau, tuy nhiên người dùng vẫn nhận được ra đó là chữ gì.
2.3.4. Thuật toán biến đổi hình bình hành
Biến đổi bình hành là phép biến đổi vị trí theo công thức của hình bình hành. Một ảnh hình chữ nhật sẽ được biến đổi thành hình bình hành xác định bởi ba toạ độ.
Công thức các toạ độ biến đổi như sau
(x', y') = (x0, y0) + (a1, b1)x + (a2, b2)y
Trong đó (x, y) là toạ độ của điểm trên ảnh cũ. x<width và y<height còn (x', y') là toạ độ của điểm trên ảnh mới tương ứng của điểm (x, y).
Điểm gốc (x0, y0) là một điểm trên ảnh mới
Điểm (x1, y1) xác định đường kéo theo chiều ngang của ảnh mới.
Điểm (x2, y2) là điểm xác định đường trải xuống bên dưới của ảnh mới
Sau khi triển khai thuật toán ta thu được kết quả:
Hình 21a: Ảnh nghiêng sang phải theo kiểu hình bình hành
Hình 21b: Ảnh nghiêng sang trái theo kiểu hình bình hành
Hình 21: Minh hoạ biến đổi ảnh theo hình bình hành
Nhận xét : Trong hình 21b, ta thấy rằng hệ nhận dạng sẽ không thể nhận dạng được đâu là số “9” và đâu là chữ “g” hoặc chữ nào là số “0” và chữ nào là chữ “o”.
2.4. Các thuật toán gây nhiễu bề mặt
2.4.1. Tại sao phải gây nhiễu bề mặt ?
Cũng giống như biến đổi bề mặt, gây nhiễu bề mặt nhằm làm cho hệ nhận dạng khó tách riêng chuỗi ra để nhận dạng do đó nó không thể nhận dạng được chuỗi ảnh hoặc nhận dạng nhầm kỹ tự này sang ký tự khác. Có rất nhiều thuật toán để gây nhiễu bề mặt nhưng trong khoá luận này chúng tôi chú trong đến bốn thuật toán chính đó là gây nhiễu bằng các điểm, gây nhiễu bằng các đường thẳng ngẫu nhiên, gây nhiễu bằng các đường cong ngẫu nhiên và gây nhiễu bằng các đường tròn.
2.4.2. Gây nhiễu bằng các điểm ngẫu nhiên
Thuât toán này rất đơn giản, chúng ta chỉ cần lấy ngẫu nhiên một điểm và tô màu điểm đó
Thuật toán có thể viết lại như sau
void GenRanPoint(int x, int y, unsigned char color)
{
SetPixel(x, y, color) ;
}
Kết quả sau khi triển khai chương trình :
Hình 22: Gây nhiễu ảnh bằng các điểm ngẫu nhiên
Ta thấy rằng, với việc gây nhiễu như trên, các hệ nhận dạng rất khó nhận dạng ra có chuỗi xuất hiện bên trên. Hơn nữa việc các điểm gây nhiễu còn có tác dụng đánh lừa hệ nhận dạng bởi với việc làm nhiễu như trên, các chữ tại vị trí thứ 4 và thứ 5 là chữ r và v gần như dính vào nhau trở thành một chữ. Do đó hệ nhận dạng không thể xác định được đó là chữ gì.
2.4.3. Gây nhiễu bằng các đường thẳng ngẫu nhiên
Để sinh đường thẳng chúng tôi sử dụng thuật toán DDA(Digital Differential Analizer)
Có thể miêu tả ngắn gọn thuật toán như sau
Xét phương trình tham số theo t
(x1, y1) x(t) = x1 + t*(x2-x1);
(x2, y2) y(t) = y1 + t*(y2-y1);
Bắt đầu với t = 0;
Tại mỗi bước tăng t một lượng dt
xmới = xcũ +
ymới = ycũ +
Chọn giá trị thích hợp cho dt sao cho không bỏ mất điểm nào
nghĩa là cần <1 và <1;
Chọn dt là giá trị max của dx và dy
Có thể viết đơn giản thuật toán sinh dưới ngôn ngữ tựa lập trình như sau:
void GenRanDdaLine(x1, y1, x2, y2)
{
a = (x2-x1);
b = (y2-y1);
dt = 1.0 / ( fabs(a)>fabs(b) ? fabs(a)+1 : fabs(b)+1 );
for( t=0; t<=1; t+=dt) {
x = x1 + a*t;
y = y1 + b*t;
SetPixel(x, y, random(256));
}
}
Kết quả sau khi áp dụng thuật toán:
Hình 23: Gây nhiễu ảnh bằng các đường thẳng
Nhận xét : Khi nhận dạng các hệ nhận dạng sẽ bị nhầm chữ “u” tại vị trí thứ 4 thành chữ “o” bởi đường thẳng đã đè lên đầu chữ “u” nên khi nhận dạng chúng chỉ xác định được tại vị trí đó có những điểm ảnh tạo thành một vòng tròn giống chữ “o”. Chữ s tại vị trí thứ 6 chắc chắn sẽ bị nhầm thành số 8 bởi đường thẳng đi ngang qua hai đầu chữ “s” tạo thành một ký tự trông giống số 8. Tuy nhiên đối với người dùng, họ sẽ xác định được chính xác đó là chữ “s”. Do đó việc gây nhiễu bằng đường thẳng để tránh nhận dạng có hiệu quả khá cao.
2.4.4. Gây nhiễu bằng các đường cong ngẫu nhiên
Chúng tôi sử dụng công thức Bezier – Berstain để sinh các đường cong ngẫu nhiên.
Công thức được xác định như sau :
p(u) = Bi, n(u)pi
Trong đó Bi, n(u) = C(n, i)*ui*(i-u)n-i
C(n,i) =
p0...pn: Vector vị trí của đa giác n+1 đỉnh
Triển khai thuật toán dưới dạng chương trình như sau:
void Bezier_curve(const int *cp)
{
for( u=0.0005;u<=1;u+=0.0005)
{
x=0;
y=0;
for(k=0;k<=3;k++)
{
x+=(cp[(k*2)]*nCr(3,k)*pow(u,k)*powl((1-u),(3-k)));
y+=(cp[((k*2)+1)]*nCr(3,k)*pow(u,k)*powl((1-u),(3-k)));
}
SetPixel((int)(x+0.5),(int)(y+0.5),color);
}
}
Trong đó
nCr(3, k) là tổ hợp chập k của 3
pow(u, k) là hàm tính u mũ k
Kết quả sau khi áp dụng thuật toán:
Hình 24: Gây nhiễu ảnh bằng các đường cong
Việc gây nhiễu bằng các đường cong là một trong những biện pháp gây nhiễu nhằm làm cho các hệ nhận dạng không thể nhận dạng chính xác các ký tự được sinh ra. Trong hình 24, chính sự gây nhiễu đã che mất đặc điểm nhận dạng của chữ “e” tại vị trí thứ 7. Khi đó các hệ nhận dạng sẽ bị nhầm thành chữ “c” bởi vòng tròn trên đầu chữ “e” đã bị đường cong che mất. Hơn nữa nhiều đường cong được sinh ngẫu nhiên trông rất giống các chữ cái như chữ “c”, chữ “s”, chữ “z”, chữ “g”, hay số “9”. Vì thế các hệ nhận dạng không thể biết được đó là ký tự trong chuỗi xác nhận hay là đường cong gây nhiễu.
2.4.5. Gây nhiễu bằng các đường tròn ngẫu nhiên
Để làm nhiễu ảnh bằng các đường tròn ngẫu nhiên, chúng tôi sử dụng thuật toán Bresenham để vẽ các đường tròn[4]
Phương trình đường tròn có toạ độ tâm là xt và yt:
(x - xt)2 + (y - yt)2 = R2
Xét đường tròn có tâm tại gốc toạ độ. Cho x thay đổi mỗi bước một đơn vị từ 0 đến R. giả sử nếu bắt đầu từ điểm xi thì giá trị của xi+1 = xi + 1
Từ phương trình đường tròn, giá trị y thực sự thuộc đường tròn với giá trị toạ độ xi+1 là:
y2 = R2 – (xi + 1)2
Đặt d1 và d2 là khoảng cách từ vị trí nguyên yi và yi+1 đến vị trí y thật của đường tròn khi x = xi+1. Ta có:
d1 = yi2 – y2
= yi2 – R2 + (xi+1)2
d2 = y2 – (yi - 1)2
= R2 – (xi + 1)2 – (yi - 1)2
Việc xét chọn điểm yi hay yi+1 phụ thuộc vào kết quả so sánh giữa hai giá trị d1 và d2. Giả sử đặt pi = d1 – d2. Lúc này việc so sánh d1 và d2 được thay bằng việc so sánh pi với 0.
pi = 2*(xi + 1)2 + yi2 + (yi - 1)2 – 2*R2
Có 3 trường hợp xảy ra:
- Trường hợp 1:
d1<d2 nên pi < 0, điểm chọn là yi(đường tròn nằm hoàn toàn trên với giá trị yi)
- Trường hợp 2:
d1>d2 nên pi >0, điểm chọn là yi-1(đường tròn nằm dưới với giá trị yi-1)
- Trường hợp 3:
đường tròn nằm giữa yi và yi-1
Thuật toán được viết dưới dạng giả mã như sau:
void BresenhamCircle(Radius)
{ p = p -2*Radius
x = 0, y = Radius
for x =0 to R
if p<0 then
p = p + 4*x +6;
else if p>=0 then
y = y-1;
p = p + 4*x +10;
SetPixel(x, y);
Lặp lại bước trên cho đến khi x = y
}
Kết quả sau khi áp dụng thuật toán:
Hình 25: Gây nhiễu ảnh bằng các đường tròn
Nhận xét: Trong quá trình nhận dạng các hệ nhận dạng không thể phân biệt các đường tròn gây nhiễu có phải là một phần của chuỗi xác nhận hay không, bởi các đường tròn này trông giống chữ “o” và số “0”. Tuy nhiên con người vẫn có thể phân biệt được đâu là đường tròn gây nhiễu, đâu là chữ “o” hoặc số “0”. Trong hình 25, chữ “f” và số “7” đứng cạnh nhau tại vị trí 1, 2, khi nhận dạng các chương trình nhận dạng sẽ bị nhầm là một ký tự “n”. Khi đọc đến vị trí số 5, chúng không thể biết được đó là ký tự gì, số “0” hay chữ “o” hay số “6”.
2.4.6. Kết hợp các kiểu gây nhiễu
Với mỗi kiểu gây nhiễu chúng tôi nhận thấy rằng cũng khá đảm bảo cho các hệ nhận dạng không thể nhận dạng được chuỗi ảnh. Tuy nhiên trong triển khai, để đảm bảo chắc chắn hơn chúng tôi đã kết hợp các kiểu gây nhiễu lại với nhau đối với mỗi lần chuỗi ngẫu nhiên sinh ra, có thể là kết hợp giữa các điểm với đường thẳng, có thể là kết hợp giữa đường thẳng và đường cong, có thể kết hợp giữa đường thẳng với đường tròn hoặc có thể kết hợp ba hoặc cả bốn kiểu gây nhiễu lại với nhau. Đồng thời chuỗi lại được biến đổi theo các kiểu khác nhau. Khi đó chúng tôi nghĩ rằng các hệ nhận dạng dù rất nhạy cũng khó có thể xác định được đúng chuỗi ngẫu nhiên vừa sinh ra.
Kết quả sau khi áp dụng các kiểu gây nhiễu:
Hình 26a: Kết hợp các kiểu gây nhiễu
Nhận xét: Đối với người dùng việc nhận dạng chuỗi ảnh trên là hoàn toàn dễ dàng, tuy nhiên đối với các hệ nhận dạng, chúng sẽ bị nhầm chữ “z” tại vị trí thứ 2 thành chữ “N”, chữ “g” tại vị trí thứ 6 sẽ bị nhầm thành số “8”. Bởi khi muốn nhận dạng một ký tự có phải là số 8 không, các hệ nhận dạng sẽ kiểm tra xem trên ký tự đó có hai vòng tròn ở trên và ở dưới dính vào nhau không, nếu có đặc điểm như thế, chúng sẽ nhận là số 8, mà chữ “g” ở hình trên, do đường thẳng gây nhiễu đã đi qua đuôi của chữ g tạo thành hai vòng tròn ở trên và dưới có dính vào nhau, nên chúng sẽ nhận thành số “8”, còn số “5” tại vị trí thứ 7 chúng sẽ nhận thành số 6
Hình 26b: Minh hoạ kết hợp các kiểu gây nhiễu
Với việc làm nhiễu và biến đổi chuỗi ảnh như trên, hệ nhận dạng sẽ không thể nhận dạng đúng được chữ “p” tại vị trí 3 và thứ 6, chúng sẽ nhận dạng nhầm thành chữ “D”, số “8” chúng sẽ nhận dạng thành chữ 2 chữ là chữ “E”và số “3”, còn chữ “o” sẽ nhận là số “8”. Do đó nếu hệ nhận dạng có thể phân tích được chuỗi ký tự và nhập chuỗi mà chúng phân tích vào ô xác nhận thì cũng không chính xác, vì vậy hệ thống ngăn chặn được việc đăng nhập tự động.
Chương 3: Triển khai thành phần
3.1. Cấu trúc của tập tin ảnh bitmap
Do chúng tôi dùng ảnh bitmap để triển khai chương trình vì vậy sau đây chúng tôi sẽ trình bày cấu trúc của ảnh bitmap.
Mỗi tập tin bitmap gồm tiêu đề chứa thông tin chung về tệp tin, thông tin bitmap chứa các thông tin về ảnh bitmap, một bảng màu và một mảng dữ liệu ảnh. Khuôn dạng được cho như sau :
Tiêu đề (header)
Thông tin ảnh (bitmap infor)
Bảng màu (palette) có thể có hoặc không
Dữ liệu ảnh (image data)
3.1.1. Tiêu đề ảnh
Gồm năm trường lưu các thông tin như kích thước tập tin, địa chỉ bắt đầu dữ liệu ảnh, và chữ ký của ảnh. Có thể mô tả thông tin về phần đầu của ảnh như sau :
typedef struct tagBITMAPFILEHEADER
{
UINT bfType;
DWORD bfSize;
UINT bfReserved1;
UINT bfReserved2;
DWORD bfOffBits;
}BITMAPFILEHEADER;
Dưới đây là giải thích chi tiết:
Tên trường
Kích thươc tính bằng Byte
Mô tả
bfType
2
Xác định kiểu của tệp tin. bfType sẽ luôn trả lại “19778”, đây là mã của 2 ký tự “BM”. Tất cả các tệp tin ảnh bitmap đều bắt đầu với 2 ký tự trên
bfSize
4
Xác định kích thước của tệp tin tính bằng byte
bfReserved1
2
Đây là vùng không gian dành riêng, chưa được dùng đến- được đặt bằng 0
bfReserved2
2
Đây là vùng không gian dành riêng, chưa được dùng đến- được đặt bằng 0
bfOffBits
4
Xác định offset từ phần đầu của tệp tin tới dữ liệu ảnh, thường là 1078
3.1.2. Thông tin ảnh
Có rất nhiều thông tin trong phần thông tin ảnh. Tuy nhiên chúng ta quan tâm đến độ rộng (width), độ cao (height), số bit cho điểm ảnh (bitcount).
typedef struct tagBITMAPINFOHEADER{
DWORD biSize;
LONG biWidth;
LONG biHeight;
WORD biPlanes;
WORD biBitCount;
DWORD biCompression;
DWORD biSizeImage;
LONG biXPelsPerMeter;
LONG biYPelsPerMeter;
DWORD biClrUsed;
DWORD biClrImportant;
} BITMAPINFOHEADER;
Dưới đây là giải thích chi tiết:
Tên trường
Kích thước tính bằng Byte
Mô tả
biSize
4
Kích thước của BITMAPINFOHEADER, ít nhất phải bằng 40
biWidth
4
Chiều rộng của ảnh tính bằng số điểm ảnh
biHeight
4
Chiều cao của ảnh, tính bằng số điểm ảnh
biPlanes
2
Số plane cho thiết bị đích, được đặt bằng 1
biBitCount
2
Số bit trên 1 điểm ảnh – 1, 4, 8, 24
biCompression
4
Kiểu nén, bằng 0 nếu ảnh không nén
biSizeImage
4
Kích thước của ảnh tính bằng byte - bằng 0 cho trường hợp ảnh không nén
biXPelsPerMeter
4
Độ phân giải được ưu tiên theo chiều ngang, tính bằng điểm ảnh trên mét
biYPelsperMeter
4
Độ phân giải được ưu tiên theo chiều dọc, tính bằng điểm ảnh trên mét
biClrUsed
4
Số lượng màu thực sự được sử dụng
biClrImportant
4
Số lượng màu cần thiết cho việc hiển thị, bằng 0 nếu tất cả các màu đều cần để hiển thị
Trong đó biBitCount xác định độ phân giải màu của tệp tin bitmap.
Nếu biBit
Các file đính kèm theo tài liệu này:
- Khoaluan.doc
- Bia_Loicamon_Tomtat.doc