P. 1
XuLyAnh&UngDungTheoDoiDoiTuongChuyenDong

XuLyAnh&UngDungTheoDoiDoiTuongChuyenDong

|Views: 196|Likes:
Published by Phuong Tran

More info:

Published by: Phuong Tran on Sep 04, 2011
Copyright:Attribution Non-commercial

Availability:

Read on Scribd mobile: iPhone, iPad and Android.
download as PDF, TXT or read online from Scribd
See more
See less

11/19/2012

pdf

text

original

ĐẠI HỌC QUỐC GIA HÀ NỘI TRƯỜNG ĐẠI HỌC CÔNG NGHỆ

Lê Anh Vũ

XỬ LÝ ẢNH VÀ ỨNG DỤNG THEO DÕI ĐỐI TƯỢNG CHUYỂN ĐỘNG

KHÓA LUẬN TỐT NGHIỆP ĐẠI HỌC CHÍNH QUY Ngành : Công Nghệ Điện Tử - Viễn Thông

HÀ NỘI 2005

ĐẠI HỌC QUỐC GIA HÀ NỘI TRƯỜNG ĐẠI HỌC CÔNG NGHỆ

Lê Anh Vũ

XỬ LÝ ẢNH VÀ ỨNG DỤNG THEO DÕI ĐỐI TƯỢNG CHUYỂN ĐỘNG

KHÓA LUẬN TỐT NGHIỆP ĐẠI HỌC CHÍNH QUY Ngành : Công Nghệ Điện Tử - Viễn Thông Cán bộ hướng dẫn : Nguyễn Vinh Quang

HÀ NỘI 2005

Lời cảm ơn

Để hoàn thành được khóa luận này đó là sự giúp đỡ nhiệt tình và hết sức tạo điều kiện của các thầy cô và nhà trường cùng các bạn trong lớp , Sự tận tình và cảm thông của gia đình,anh em. Em xin chân thành cảm ơn thầy Nguyễn Vinh Quang, người đã hưỡng dẫn em làm khóa luận này, thầy đã nhiệt tình giúp đỡ em trong suốt quá trình làm khóa luận về cả vật chất lẫn tinh thần.
Em xin cảm ơn Nhà Trường và đặc biệt là các thầy cô của khoa Điện Tử thuộc Phòng Thí Nghiệm ROBOTIC của Trường, những người mà hàng ngày vẫn tạo điều kiện và bảo ban em.

Cảm ơn các bạn lớp K46DC, nhưng người luôn sát cánh và chia sẻ cùng mình!
Hà Nội, ngày 05/06/2005

.4.4:Làm trơn hình ảnh nhị phân………………………………………….1:Thu nhận ảnh…………………………………………………………….3:Quyết định……………………………………………………………….11 3.17 3.4.1:Phương pháp tiền xử lý trong miền không gian……………………. lọc tuyến tính……………….31 Chương 3:Minh họa thuật toán và chương trình………………………….1:Tích chập……………………………………………………………….2.2:Lưu ảnh………………………………………………………………….4:Làm trơn ảnh…………………………………………………………...2:Phương pháp lọc trung vị…………………………………………….…8 3...2:Kỹ thuật lọc số………………………………………………………….20 3.2 Chương 1: Lý Thuyết xử lý ảnh …………………………………………………2 1.2:Phân tích ảnh…………………………………………………………….1:Khái niệm pixel và pixil lân cận…………………………………………8 3.2:Phương pháp tiền xử lý trong miền tần số………………………….4.7 Chương 3: Phân tích ảnh……………………………………………………….52 ...22 3..3 2.5:Phát hiện biên…………………………………………………………….3 2.3.19 3..1:Thu nhận ảnh và số hóa…………………………………………………2 1.8 3..26 Chương 1: Ngôn ngữ lập trình…………………………………………….1 Phần 1: LÝ THUYẾT XỬ LÝ ẢNH ……………………………………………..34 Tài liệu tham khảo:………………………………………………………………….2...16 3.. 11 3.1:Lấy trung bình các điểm ảnh lân cận.Mục lục Mở đầu…………………………………………………………………………….19 3.28 Chương 2:Điều khiển công LPT trên Win200/NT/XP…………………….18 3.2:Một số công cụ trợ giúp xử lý ảnh………………………………………8 3..2 1.2.6:Lập ngưỡng………………………………………………………………25 Phần 2: PHẦN THỰC NGHIỆM:……………………………………………….4.3:Biến đổi Fourier………………………………………………………..…18 3.3:Trung bình hóa hình ảnh……………………………………………....3.3:Tiền xử lý…………………………………………………………………16 3.3 Chương 2: Thu nhận hình ảnh…………………………………………… ….

Khóa luận được chia làm hai phần chính.TÓM TẮT NỘI DUNG KHÓA LUẬN: Nội dung của khóa luận là ứng dụng lý thuyết của xử lý ảnh số qua thiết bị thu ảnh . bao gồm lý thuyết về Xử lý ảnh. Phần 3 là phần chính . . các phưong pháp tiền xử lý : lọc nhiễu.Thu nhận hình ảnh và Phân tích ảnh. -Ở phần này. phát hiện biên. ta sẽ tìm hiểu các khái niệm cơ bản của xử lý ảnh số. ở đây là web camera để điều khiển một hệ cơ tự động theo dõi đối tượng chuyển động. phần lý thuyết và phần thực nghiệm : -Trong phần lý thuyết . giới thiệu các khái niệm về xử lý ảnh và ứng dụng các thuật toán về xử lý ảnh như là công cụ toán học tích chập. -Phần thực hành gồm 3 phần: Phần 1 tìm hiểu ngôn ngữ lập trình và thư viện AVICap của Microsoft. bao gồm thuật toán và chương trình chính điều khiển. phân ngưỡng ảnh…. Phần 2 sẽ giới thiệu về cách giao tiếp và điều khiển công LPT trên VC++.

Nhưng bằng cách mã hóa số và khôi phục ảnh (là những vấn đề của xử lý ảnh ) thì việc trên có thể thực hiện chỉ với băng tần 100 nghìn bit/s. phân tích ảnh và quyết định. xử lý ảnh số đã được dùng để phát hiện và nhận dạng khối u .. Việc mã hóa thẳng các chương trình video chất lượn quảng bá cần đến 100 triệu bit/s. nhận dạng đường biên mạch máu từ những ảnh chụp mạch bằng tia X. Mô hình sản phẩm theo dõi đối tượng dùng camera . Trong truyền thông video như hội nghị video.. Như trong y học. Đó là các vấn đề nhận dạng các đối tượng ngoài môi trường. . dò đường. Còn trong lĩnh vực khoa học kỹ thuật. Từ việc nhận dạng có thể giải quyết rất nhiều bài toán như tránh vật cản. xử lý ảnh được dùng để cải thiện ảnh Ti vi.LỜI MỞ ĐẦU Trong mấy thập kỷ gần đây.. trong cuộc sống gia đình. Robot thông minh ngày nay không thể thiếu yếu tố xử lý ảnh. điện thoại video thì một vấn đề chính là cần có giải tần rộng. cải thiện ảnh X quang . xử lý ảnh đã và đang có những đóng góp quan trọng. Điều này không thể đáp ứng được. xử lý ảnh đã được nghiên cứu mạnh mẽ và đã có rất nhiều ứg dụng trong thực tế. đặc biệt là trong lĩnh vực Robot.Xử lý ảnh có thể được chia ra làm các quá trình sau: Thu nhận hình ảnh.

Tiếp theo là phát hiện các đặc tính như biên.1 ta thấy một hệ thống xử lý ảnh bao gồm thu nhận ảnh. Ảnh cũng có thể được thu qua các thiết bị khác như máy quét v.2 Phân tích ảnh Ở giai đoạn này ảnh được xử lý theo nhiều công đoạn nhỏ như: cải thiện ảnh. phân vùng. Các giai đoạn chính trong xử lý ảnh.PHẦN 1: LÝ THUYẾT XỬ LÝ ẢNH CHƯƠNG 1 : HỆ THỐNG XỬ LÝ ẢNH Một hệ thống xử lý ảnh điển hình được cho trên hình vẽ sau: Lưu trữ Lưu trữ Thiết bị thu nhận ảnh (Camera. khôi phục ảnh để làm nổi bật một số đặc tính chính của ảnh hay làm ảnh gần với trạng thái gốc.1. Sensor) Thu nhận ảnh Số hoá Phân tích ảnh Nhận dạng Hệ quyết định Hình 1. phân tích ảnh và cuối cùng là quyết định (tùy thuộc vào yêu cầu ứng dụng cụ thể mà đưa ra quyết định cho phù hợp) 1.. 1. số hóa ảnh. xử lý hay lưu trữ ảnh. . Nếu ảnh nhận được là tương tự nó phải được số hóa nhờ quá trình lấy mẫu và lượng tử hóa trước khi phân tích.1 Thu nhận ảnh và số hóa Việc thu nhận ảnh có thể thông qua camera. Từ hình vẽ 1.v . Các camera có thể hoặc là tương tự (loại camera ống kiểu CCIR) hoặc là số (loại camera kiểu CCD_ Charge Coupled Device).

màng mỏng này tạo thành một điện cực mà từ đó tạo ra tín hiệu điện của hình ảnh. sẽ là giai đoạn nhận dạng hay các quyết định khác. Camera Vidicon là một vỏ kính hình lăng trụ chứa một súng phóng electron ở đầu và một màn hình (faceplate) ở đầu kia.3 Quyết định Cuối cùng tùy theo mục đích của ứng dụng.. Mạch làm lệch làm cho dòng electron quết lên bề mặt trong của màn hình để “đọc” hình ảnh . CHƯƠNG 2: THU NHẬN HÌNH ẢNH 2. một số camera tube có độ phân giải cao hơn camera sensor mạch rắn. bền hơn. Tuy nhiên. bền hơn và tiêu thụ công suất thấp hơn. Dòng electron được hội tụ và làm lệch điện áp đặt vào các cuộn dây như trên hình vẽ 2. Lớp tạo thành bao gồm những quả cầu trở kháng có kích cỡ rất nhỏ. Một lớp nhạy sáng được phủ trên màng mỏng kim loại.1. Bề mặt bên trong của màn hình được phủ một màng mỏng kim loại trong suốt. trở kháng của những quả cầu này tỷ lệ nghịch với cường độ sáng của nó.1 Thu nhận ảnh Để thu nhận ảnh người ta thường dùng các camera truyền hình. Phía sau lớp nhạy sáng đó có một lưới tích điện dương để giảm tốc các . Camera sensor mạch rắn có một số ưu điểm so với camera tube như nhẹ hơn.1. nhỏ hơn. các camera gồm tube hoặc sensor mạch rắn và các thiết bị điện tử đi kèm. Một trong số những loại được sử dụng phổ biến của camera tivi là Vidicon.

và do đó tạo thành một dòng điện chảy trong lớp kim loại và ở phía ngoài của một trong các chân tube. dòng electron phủ một lớp electron lên bề mặt bên trong của màn hình để cân bằng với điện tích dương trên lớp kim loại. lớp nhày sáng trở th ành một tụ điện với điện tích âm trên bề mặt phía trong và điện tích dương ở bề mặt đối diện. Khi dòng electron quét màn hình lần thứ hai nó thay thế các điện tích bị mất. Vì lượng điện tích chuyển động tự do tỷ l ệ với ánh sáng trong một vùng cục bộ bất kỳ của màn hình. Nghĩa là. Ở chế độ hoạt động bình thường. sự tập trung của c ác điện tích electron là cao trong các vùng tối và thấp hơn trong các vùng sáng. Dòng này tỷ lệ với số electron được thay thế và do đó tỷ l ệ với cường độ sáng tại vị trí cụ thể của dòng quét. Khi không có ánh sáng. điện áp dương được đặt vào lớp kim loại của màn hình.electron được phát ra từ súng phóng electron sao cho khi các electron này tới bề mặt đích về cơ bản vận tốc là bằng không. trở kháng của nó giảm và el ectron được phép chuyển động tự do và trung hòa với điện tích dương. lớp nhạy sáng đóng vai trò như chất điện môi. Sự thay đổi này khi dòng electron quét sẽ tạo ra một tín hiệu hình ảnh tỷ lệ với cường độ của ảnh đầu vào. Khi ánh sáng va vào màn hình. Khi chùm electron quét bề mặt của màn hình. hiệu ứng này t ạo ra một hình ảnh trên màn hình giống với ảnh chiếu trên màn hình của tube. Cuộn hội tụ dòng electron: Lớp nhạy sáng .

Trường hợp đầu tiên của mỗi khung quét các dòng lẻ (là các đường chấm chấm trong hình 2.1. Nếu các dòng được quét một cách tuần tự và kết quả được hiển thị lên một màn hình TV.2 Mẫu quét dòng electron: Hình 2. Các . Các thiết bị CCD gồm hai loại: Sensor quét dòng và sensor khối. và máy móc điện tử).Lưới Các chân tube Dòng electron Súng phóng electron Màn hình Lớp phủ kim loại trong suốt Cuộn làm lệch dòng electron Hình 2. Sơ đồ quết này được gọi chuẩn là RETMA (Radio-Electronics Television Manufacturers Association ).Sơ đồ một vidicon Hình 2. mỗi một vết quét hoàn chỉnh (gọi là một khung) gồm 525 dòng trong đó có 480 dòng chứa thông tin về hình ảnh.Dòng electron quét toàn bộ màn hình 30 lần mỗi giây. Có thể khắc phục hiện tượng này bằng cách sử dụng cơ cấu quét mà trong đó mỗi khung được chia ra thành hai trường mành xen kẽ nhau. hình ảnh sẽ nhấp nháy rõ rệt.2 minh họa một chuẩn quét. Hiệp hội các hãng chế tạo Radio. nhưng về cơ bản nguyên lý hoạt độn4g của các mạch này là giống nhau. mỗi trường gồm 2625 dòng và được quét 60 lần trong một giây hay tốc độ khung tăng lên gấp đôi.2) trong khi đó mành thứ hai quét các dòng chẵn. Các chuẩn khác có tốc độ dòng trên mỗi mành cao hơn . Thành phần cơ bản của Sensor CCD quét dòng là một hàng phân tử ảnh silic gọi là photosites. Tivi.

Nội dung của các photosite lẻ được chốt lần lượt vào các thanh ghi vận chuyển dọc và sau đó lại được chốt vào các thanh ghi . Cổng . Thanh ghi truyền 21 Lối ra Hình 2. Thanh ghi vận chuyển Cổng Cổng Lối Ra Bộ khuếch đại Các thanh N Photosites Ghi điều khiển .photo hình ảnh cho qua một cấu trúc cổng đa tinh thể trong suốt và được hấp thụ trong tinh thể silic. hai cổng truyền được sử dụng để chốt lại nội dung của các phần tử hình ảnh vào các thanh ghi vận chuyển và một cổng nối ra được sử dụng để chốt nội dung của các thanh ghi vận chuyển vào bộ khuyếch đại. Các quang điện tử tạo ra được tập hợp vào các photosite. lối ra của bộ khuyếch đại này là một tín hiệu điện áp tỷ lệ với các nội dung của hàng photosites. Một sensor quét dòng điển hình gồm một hàng các phân tử ảnh photosite. . do đó tạo nên một cặp lỗ electron. ngoại trừ các photosite được sắp xếp theo dạng ma trận và có một tổ hợp thanh ghi vận chuyển cổng giữa các cột photosite như trong hình 2.Sensor quét dòng CCD Các mảng khối ghép diện tích giống các sensor quét dòng. .4. lượng điện tích được tập hợp trong mỗi photosite tỷ lệ với cường độ chiếu sáng tại điểm đó.3.

Các sensor quét dòng có độ phân giải thấp 32x3. y biểu thị toạ độ không gian (ví dụ mặt phẳng ảnh) và giá trị f tại điểm (x.y) bất kỳ được cho bởi giá trị (cường độ sáng) của f tại điểm đó. Quy ước toạ độ cho biểu diễn hình ảnh Giá trị của điểm ảnh (x. . Thực hiện tương tự với các photosite chẵn để hoàn thành trường thứ hai của khung TV. Sự chuyển động của một đối tượng theo hướng vuông góc với sensor tạo ra hình ảnh hai chiều. Cơ cấu quét này được lặp lại 30 lần mỗi giây. Các camera quét dòng chỉ cho ra một dòng hình ảnh của hình ảnh lối vào. trung bình 256x256 và cao 480 phân tử ảnh và các sensor thí nghiệm CCD có khả năng đạt được độ phân giải khoảng 1024x1024 hay cao hơn. Hình 2.: Gốc hình ảnh y f(x.y) trong đó x.5 minh hoạ một điểm ảnh và quy ước toạ độ của nó. Hình 2.y) phải được số hoá cả về không gian lẫn biên độ (cường độ). Nội dung của các thanh ghi vận chuyển ngang này được dẫn vào bộ khuyếch đại. Ở đây.y) được coi như là việc lấy mấu hình ảnh. hàm ảnh (x.vận chuyển ngang. trong khi đó việc số hoá biên độ được coi là lượng tử hoá cường độ cho những hình ảnh đơn sắc và phản ảnh bản chất của các ảnh này là biến thiên từ đen tới trắng theo các mức xám khác nhau.y) bất kỳ tỷ lệ với toạ độ (cường độ sang) của hình ảnh tại điểm đó . lối ra của bộ khuyếch đại là một dòng lẻ hình ảnh. ta ký hiệu ảnh lối ra hai chiều của camera hay thiết bị cho ảnh khác là f(x.5.y) • x Để máy tính có thể xử lý. Những thiết bị này đặc biệt phù hợp cho các ứng dụng mà các đối tượng chuyển động qua sensor (như trong các băng truyền) . Hai thuật ngữ cường độ sang và mức xám có thể dung hoán chuyển cho nhau. Việc số hoá các toạ độ không gian (x.

0 ) f ( N − 1..... DE..v........ M-1 Mỗi phần tử trong mảng được gọi là một phần tử ảnh hay pixel... N-1 y= 0.. • 2 byte tiếp theo: chứa độ dài mẫu tin.. m − 1)] f (1.. Nhiều dãy giống nhau được lưu trong một byte..... 2. ở đây mỗi mẫu cũng được lượng tử hoá về biên độ. Để lưu trữ ảnh trên máy tính. dữ liệu ảnh (image data)........Giả sử một hình ảnh liên tục được lấy mẫu đồng nhất cho một mảng N hang và M cột. 2..0) f (o... Từ mảng ta thấy pixel tại gốc của ảnh được biểu thị là f(0..0 ) f (1.. Định dạng này được đưa ra để khắc phục những vấn đề mà các định dạng ảnh khác gặp phải khi số màu trong ảnh tăng lên... M − 1) .....1)...2 Lưu ảnh..1)........0). và bảng màu mở rộng. Định dạng tổng quát của ảnh GIF được cho trên hình vẽ 2.1).6 .. có thể được viết như sau: F(x. • 4 byte tiếp theo: mô tả kích cỡ pixel • 2 byte tiếp theo: cho biết số pixel trên một dòng ảnh • 2 byte cuối: cho biết số dòng ảnh trong ảnh.... M và số mức cường độ rời rạc của mỗi pixel đã lượng tử hoá là luỹ thừa nguyên của 2...... Định dạng ảnh IMG dung cho ảnh đen trắng............. PCX.. Thông thường N... Đó là độ dài của dãy các byte kề liền nhau mà dãy này sẽ được lặp lại một số lần nào đó... Định dạng này cũng gồm 3 phần: IFH. 1. 1..... Giá trị của 6 byte này được viết là 0x0001 0x0008 0x0001.y) = [ f (0. f (N − 1. Tệp PCX gồm 3 phần : đầu tệp(header). Định dạng ảnh GIF (Graphics Interchange Format).....1) ở đây các biến rời rạc:x=0. 2 ….... Định dạng ảnh TIFF được thiết kế để làm nhẹ bớt các vấn đề liên quan đến việc mở rộng tệp ảnh cố định.. Mảng này được gọi là ảnh số... …... IFD. một số định dạng ảnh đã được nghiên cứu như IMG. GIF. pixel bên phẩi là f(0. M − 1) (2. Định dạng ảnh PCX là một trong những định dạng ảnh cổ điển nhất.. Định dạng này sử dụng phương pháp mã loại dài RLE (Run-Length-Encoded) để nén dữ liệu ảnh... Quá trình nén và giải nén được thực hiện trên từng dòng ảnh.1)..... Số lần lặp lại này sẽ được lưu trong byte đếm.. Đây là một cách lưu trữ hình ảnh dưới dạng nén.. TIFF..... f (0. f ( N − 1..... f (1. Phần đầu của ảnh IMG có 16 byte chứa các thông tin: • 6 byte đầu: dung để đánh dấu định dạng ảnh IMG... v..

1 Khái niệm pixel và pixel lân cận Pixel là phân tử nhỏ nhất cấu tạo nên hình ảnh. y-1) P2 (x-1. y+1) P8(x+1. y+1) Tập các pixel này gọi là lân cận của p và ký hiệu là N4(p). Hình 3.1 Pixel P và các lân cận của P P1 ̣(x-1.: GIF note GIF header Global Palette Header image (_10 byte) Palette of image 1 (nếu có) Data of image 1 ‘’ Ký tự liên tiếp ………………………. y-1) P6(x+1. y+1) . y+1) Một pixel p tại các toạ độ ̣(x. y+1) P5 (x. y) có ô pixel lân cận theo chiều dọc và chiều ngang. y-1) P4 ̣(x.y) và màu xác định. y-1) P3(x-1. như hình vẽ 3. y) ở mép của màn hình thì sẽ có một số pixel lân cận của p nằm ở ngoài hình ảnh. y+1) P8 (x+1. y) P5(x. và toạ độ tương ứng của các pixel này . Mỗi pixel lân cận cách (x. y) P7 (x+1. xung quanh p còn có 4 pixel chéo góc có các toạ độ tương ứng là: P1(x-1. y) P6(x+1.6 Định dạng tổng quát GIF của một hình ảnh.. ‘’ GIF terminator CHƯƠNG 3: PHÂN TÍCH ẢNH 3. y) P3 (x-1. P7(x+1. y-1) P6 (x+1.1 là: P2(x-1. y) P (x. y-1) . y) một đơn vị và nếu (x. Mỗi pixel có một toạ độ ̣(x. Ngoài 4 pixel lân cận của p theo chiều dọc và chiêu ngang.Hình 2.

Tập hợp này cũng sẽ có một số pixel ở bên ngoài hình ảnh nếu (x.n) ⊗ x(m. 3.n) .1) ◊ Trường hợp rời rạc: y(m. n − n')x(m' . y) nằm ở mép của hình ảnh.Bốn pixel này cùng với 4 pixel ở trên tạo thành 8 pixel lân cận cuả p và được ký hiệu là N8 (p) . n’) h (m’. y − y') f (x' .2) n’ x (m’.y) ⊗ f(x. n’) B A C m’ m n’ Xoay180o C h(m-m’.Tập các pixel này được ký hiệu là NḌ(p).1 Tích chập Toán tử tích chập được định nghĩa như sau: ◊ Trường hợp liên tục: g(x.y) = ∫ ∫ h(x − x' . y')dx' dy' −∞ −∞ ∞ ∞ h(x-x`.2 Một số công cụ trợ giúp xử lý ảnh 3.y`) dx` dy` (3.y) = h(x.n) = ∑ ∑ h(m − m' . n-n’) n A m’ a) Đáp ứng xung b) Tín hiệu ra ở vị trí (m.2.y-y`) f(x`. n') −∞ −∞ ∞ ∞ (3.n) = h(m.

-n) e) y(1. N1+N2 -1).2 Một biểu diễn của toán tử tích chập Ví dụ: Cho các ma trận: + Ma trận tín hiệu : ⎡1 ⎢2 ⎢ ⎢ ⎣ 4 5 1⎤ 3⎥ ⎥ ⎥ ⎦ + Ma trận đáp ứng xung: ⎡1 ⎢1 ⎢ ⎢ ⎣ 1 −1 ⎤ ⎥ ⎥ ⎥ ⎦ Ma trận tích chập của x và h là một ma trận 4x3.0) = -2+3=1 .Hình 3. Quá trình nhân chập của h và x được minh hoạ trong hình 3.n) -1 1 1 1 b) h(m.-n) 1 5 5 1 3 10 5 2 2 3 -2 -3 f) y(m.3 sau: 1 4 1 2 5 3 n 1 1 1 4 n -1 1 1 1 a) x(m.n) -2 5 0 0 c) h(-m.n) d) h(1-m. Nói chung chập của hai ma trận số (M1xN1) và (M2xN2) là một ma trận cỡ (M1+M2.

y) ⊗ I(x.3 . đặc biệt là tính chất của nó có liên quan đến biến đổi Fourier: Biến đổi Fourier của một tích chập bằng tích đơn giản các biến đổi Fourier của tín hiệu đó: F[H (x.y) gọi là ảnh đối tượng. Để sử dụng thuật toán chỉ cần thay đổi hai thông số:ma trận biểu diễn ảnh số cần xử lý và ma trận biểu diễn nhân chập. R ow:=j+l+Lc If(Col<> 0 and (Col<=N) then . ImageOut: ảnh H: nhân chập N: kích thước ảnh W.y) được gọi là nhân chập hay nhân cuộn hay mặt nạ : I(x. F[I(x.y)] = F [H (x.3) Trong kỹ thuật H(x. Ví dụ về toán tử nhân chập Tích chập là một khái niệm rất quan trọng trong xử lý ảnh.Hình 3. Nhân chập (ImageIn. kích thước nhân chập) { Vào: ImageIn Nhân chập Ra: ImageOut} Begin For i = 1 to N do For i = 1 to N do Begin Sum = 0 Le:= (w+1) div2: For k:=1 to w do For k:=1 to w do Begin Col:=1-k+Lc.y)] ̣(3.y) . Thuật toán tổng quát để tính nhân chập dùng cho mọi trường hợp.

If(Row <> 0 and (Row <=N) then Sum:=Sum+ImageIn [Col. Về mặt tần số. nhiễu ứng với các thành phần tần số cao trong ảnh.2 Kỹ thuật lọc số Chất lượng hình ảnh kém do rất nhiều nguyên nhân như do nhiễm điện tử của máy thu hay chất lượng bộ số hóa kém.2. Như vậy để xử lý nhiễu ta có thể lọc các thành phần tần số cao. Nhiễu ảnh số được xem như là sự dịch chuyển nhanh của tín hiệu thu nhận trên một khoảng cách ngắn. Tùy theo cách tổ hợp điểm đang xét với các điểm lân cận mà ta có kỹ thuật lọc tuyến tính hay kỹ thuật lọc phi tuyến.2. 3. End. Row ] * H [k. các pixel lân cận có thể có cùng hoặc gần cùng một số đặc tính.3 Biến đổi Fourier 3.j] = Sum End. ImageOut [i. Điểm ảnh chịu tác động của biến đổi là điểm ở tâm của mặt nạ.2. Kỹ thuật lọc này dùng một mặt nạ và di chuyển khắp ảnh gốc. 3.l] End.3. Việc lọc dựa vào tính dư thừa thông tin không gian . Các kỹ thuật lọc này được trình bày kỹ trong phần làm trơn ảnh.1 Khái niệm và công thức Biến đổi Fourier cho một tín hiệu có thể biểu diễn như sau: FT x(t) Miền thời gian X(n ) X(f) Miền tần số Dạng phức X(z) .

Cho một hàm f(x) liên tục.4) Biến đổi Fourier ngược của F(u) cho f(x) đ ược định nghĩa như sau: ƒ(x) = ∫ ∞ −∞ ∫ ∞ −∞ F(u)e-2jπ ux du (3.5) b) Không gian hai chiều Cho f(x. ký hiệu F(u) .v) = ∫ ∫ ∞ ∞ −∞ −∞ f(x.y) là hàm biểu diễn ảnh liên tục trong không gian hai chiều. ∫ ∞ −∞ ƒ(x)e-2jπ ux dx (3.v biểu diễn tần số không gian -Biến đổi Fourier ngược f(u. a)Không gian một chiều.v) = ∫ ∫ ∞ ∞ −∞ −∞ F(x.Biến đổi Fourier thuận cho tín hiệu một chiều gồm một cặp biến đổi -Biến đổi Fourier thuận: chuyển sự biểu diễn từ không gian thực sang không gian tần số (phổ và pha) . Các thành phần tần số n ày đ ược gọi là các biểu diễn trong không gian Fourier của tín hiệu. Biến đổi Fourier của f(x).y) e-2jπ (ux+vy) dxdv (3.6) U.Biến đổi Fourier ngược: Chuyển đổi sự biểu diễn của đối tượng từ không gian Fourier sang không gian thực.6) . được định ngh ĩa l à: F(u) = Trong đ ó: F(x) : biểu diễn biên độ tín hiệu e-2jπ ux: biểu diễn pha. cặp biến đổi Fourier được định nghĩa như sau: -Biến đổi Fourier thuận: F(u. .y) e-2jπ (ux+vy) dxdy (3. u biểu diễn tần số không gian .

1.…. người ta biến đổi bởi một chuỗi trực giao các hàm cơ sở.….... Với các hàm liên tục.….1..1. 1. n=0. Hơn nữa khai triển DFT và DFT đơn vị của một chuỗi và biến đổi ngược lại của nó có tính chu kỳ và chu kỳ N.. Biến đổi Fourier DFT t ính các giá trị của biến đ ổi Fourier cho một t ập các giá trị trong không gian tần số được cách đều. N-1 (3. b) DFT cho tín hiệu hai chiều (ảnh số) DFT hai chiều của một ảnh MxN:{u(m..7) với WN = e-j2π/N và biến đổi ngược u(n) = 1 N ∑ v (k)WN-kn k =0 N −1 với k=0.10) Các DFT và DFT đơn vị có tính đối xứng.N-1 (3.2 Biến đôỉ Fourier rời rạc_DFT Biến đổi DFT được phát triển dựa trên bi ến đổi Fourier cho ảnh số.2. tích phân được thay bằng tổng.N} được định nghĩa bởi: V(k) = ∑ n =0 N −1 u(v) WknN v ới k=0. Khai triển Fourier rời rạc DFT cho một dãy {u(n). Ở đây.3.N-1 (3. a) DFT cho tín hiệu một chiều Với tín hiệu một chiều.9) với k=0.1.. khai triển chuỗi trực giao sẽ cung cấp chuỗi các hệ số ùng trong nhiều quá trình khác nhau hay trong phân tích hàm.3.N-1 (3....8) Thực tế trong xử lý ảnh người ta hay dung DFT đơn vị: v(k)= u(n)= 1 1 ∑ N ∑ N n =0 N −1 n =0 N −1 u(k)WNkn u(k)WN-kn với k=0.n)} là một biến đổi tách được và được định nghĩa: .

DFT của cuộn chập hai chiều của hai ma trận bằng tích DFT của chúng: . Định lý chập cuộn hai chiều.11) Và biến đổi ngược: 1 N N −1 N −1 V(k.n)WN(km +ln) v(k.l) = (3.n≤ N-1 (3.l) WN-km WN-ln với 0 ≤m.V(k.l)WN-(km +ln) với 0 ≤m.12) Cặp DFT đơn vị hai chiều được định nghĩa: V(k. Chỉ biến đổi Fourier biểu diễn ảnh trong không gian mới theo các hàm sine và cosine.n) = 1 N m =0 l =0 ∑∑ N −1 N −1 Với 0 ≤m.l) WN-km WN-ln với 0 ≤m.3.l) = 1 N 1 N m =0 n =0 ∑∑ 1 N N −1 N −1 u(m.2.13) và (3.k≤ N-1 m =0 n =0 ∑∑ N −1 N −1 v(k.16) Ở đây.l) = m =0 n =0 ∑∑ N −1 N −1 u(m.n) = (3.n≤ N-1 (3.n) WNkm WNln với 0 ≤1.3.n) WNkm WNln với 0 ≤1.n≤ N-1 m =0 0 ∑∑ N −1 u(m.l) = m =0 n =0 ∑∑ v(k.13) U(m. 3.14) Viết lại các công thức (3.n≤ N-1 (3. Ta có: WN-(km +ln) =e-j2π(km+ln)/N =cos [2π(km+ln)/N] -jsin [2π(km+ln)/N] Như vậy các hàm cơ sở trong ma trận cơ sở của biến đổi Fourier là các hàm cosine và hàm sine. WN(km +ln) là ma trận ảnh cơ sở.15) u(m.14) ta có: V(k.k≤ N-1 (3.

u(m,n) =

m =0 l =0

∑∑

N −1 N −1

h(m-m’, n-n’)c u1(m’,n’)

với 0 ≤m,n≤ N-1

(3.17)

với h(m,n), u1(m,n) là ma trận NxN và h(m,n)c =h(m mod N, n mod N) 3.2.3.4. Thuật toán biến đổi Fourier nhanh. - Trường hợp một chiều Từ công thức v(k) =
1 N


n =0

N −1

u(n) WNkn

với k= 0,1,…., N-1 ta thấy với mỗi giá

trị k ta cần N phép tính nhân và N phép cộng. Nên để tính N giá trị của v(k) ta phải tính N2 phép tính. Để khắc phục điều này người ta sử dụng thuật toán biến đổi Fourier nhanh FFT chỉ cần N.log2N phép tính. Thuật toán Fourier nhanh được tóm tắt như sau:

-Giả sử N=2n -Giả sử WN là nghiệm thứ N của đơn vị WN =e-2jπ/N và M=N/2 ta có:
1 2M
2 M −1

v(k) =


n =0

u(n)W2Mnk

(3.18)

- Khai triển công thức trên ta được

v(k) = (

1 M

M −1


n =0

u(2n) W2M2nk +

1 ∑ u(2n+1) W2M(2n+1)k)/2 M

(3.19)

vì W2M2nk =W2Mnk, do đó: v(k) =
1 [uchẵn (n)+ulẻ (n)] 2

(3.20)

v(k) với k=[0,M-1] là một DFT trên M =N/2. Thực chất của thuật toán FFT là dung nguyên tắc chia đôi và tính chu kỳ để tính DFT. Với k=[0,M-1] dung công thức (3.19). Với k=[M,M-1] dung phép trừ trong công thức (3.19) có thể dung thuật toán này để tính DFT ngược. -Trường hợp hai chiều:

Do DFT hai chiều là tách được nên từ công thức (3.14) ta có:

V(k,l) =

1 N

m =0

N −1

WNkn


n =0

N −1

u(m,n) WNln

(3.21)

Từ công thức (3.21) , cách tính DFT hai chiều như sau: -Tính DFT 1 chiều với mỗi giá trị của X (theo cột) -Tính DFT 1 chiều theo hướng ngược lại (theo hàng) với giá trị thu được ở trên.

3.3 Tiền xử lý
Có hai phương pháp cơ bản được sử dụng trong tiền xử lý ảnh. Phương pháp thứ nhất dựa vào các kỹ thuật tiền xử lý trong miền không gian và phương pháp thứ hai sử dụng các khái niệm trong miền tần số thông qua biến đổi Fourier.

3.3.1 Phương pháp tiền xử lý trong miền không gian. Thuật ngữ miền không gian ở đây muốn nói đến số lượng pixel tạo nên một hình ảnh. Các phương pháp tiền xử lý trong miền không gian là các thủ tục tác động trực tiếp lên các pixel tạo lên hình ảnh đó. Các hàm tiền xử lý trong miền không gian có thể được viết như sau:

g(x,y) =h[f(x.y)]

(3.22)

Ở đây f(x,y) là hàm điểm ảnh chưa được xử lý. g(x,y) là hàm điểm ảnh đã được xử lý. h là toán tử áp lên f. Dạng đơn giản nhất của h là lân cận có kúch tghước1x1, khi đó g chỉ phụ thuộc vào giá trị của f tại (x,y) và h trở thành hàn ánh xạ cường độ sáng điểm ảnh.

Một trong những kỹ thuật được sử dụng rộng rãi nhất là sử dụng mặt nạ nhân chập. Trên hình 3.4 minh hoạ một mặt nạ là một mảng 2 chiều có kích thước 3x3, các hệ số của mặt nạ được chọn để phát hiện một thuộc tính cho trước trong một hình ảnh.

Hình 3.4. Một lân cận kích thước 3x3 quanh điểm (x,y) y (x,y)

• x Để hiểu rõ về mặt nạ nhân chập ta xét một ví dụ cụ thể sau. Giả sử chúng ta có một hình ảnh có cường độ không đổi chứa một số điểm ảnh tách rời nhau, cường độ của các điểm ảnh này khác với nền. Các điểm ảnh này có thể được phát hiện bằng một mặt nạ nhân chập có kích thước 3x3 với các hệ số đã chọn trên hình 3.5 Hình 3.5. Mặt nạ dung để xác định các điểm ảnh Tách biệt trên một nền không đổi

-1 -1 -1

-1 8 -1

-1 -1 -1

Thủ tục phát hiện điểm ảnh như sau: Cho tâm của mặt nạ chuyển động xung quanh hình ảnh. Tại mỗi vị trí pixel trong hình ảnh, ta nhân mỗi pixel nằm trong vùng mặt nạ tương ứng ; Nghĩa là pixel ở tâm của mặt nạ được nhân với 8, còn 8 pixel lân cận được nhân với –1. Sau đó cộng kết quả của 9 phép nhân này lại. Nếu tất cả các pixel trong mặt nạ có cùng giá trị (tức nền không đổi), thì tổng sẽ bằng 0. Ngược lại nếu tâm của mặt nạ trùng với một trong các điểm ảnh cần xác định, thì tổng sẽ

Ta có thể khái quát hoá một hàm tiền xử lý cho một mặt nạ 3x3 như sau: h[f(x.y+1) W9 (x+1. f(x). Mặt nạ tổng quát kích thước 3x3 trình bày các hệ số và vị trí pixel ảnh tương ứng.y) như hình 3. w2.…. tổng cũng sẽ khác 0.y)]= w1f(x-1.2 Phương pháp tiền xử lý trong miền tần số.3. y-1) W7 (x+1. Nếu điểm ảnh cần xác định không nằm đúng tâm của mặt nạ.y-1)+w8f(x+1. 1. y-1) +w3f(x-1. y+1) +w4f(x. y+1) (3. Khái niệm “tần số” thường được sử dụng trong giải thích biến đổi Fourier và suy ra từ bản chất của biến đổi Fourier là tổ hợp của các hàm sin phức. W1 (x-1.y) W5 (x.y+1) +w7f(x+1.w9 và 8 điểm ảnh lân cận của điểm ảnh (x.khác 0.y-1) W4 (x. x=0.6. y+1) hình 3. Phương pháp naỳ đóng vai trò rất quan trọng trong lĩnh các vực như phân tích chuyển động của một vật và miêu tả vật. Biến đổi Fourier thuận của hàm f(x) là: .y) W8 (x+1. Xét một mặt nạ có các hệ số w1. y-1) +w5f(x. Những đáp ứng yếu hơn này có thể loại bỏ bằng cách so sánh tổng với một ngưỡng.y)+w6f(x. Xét các hàm rời rạc của một biến.y+1) W6 (x.23) Hình 3.y) +w9f(x+1.. y) W3 (x-1. …. N-1. Thuật ngữ miền tần số ở đây có nghĩa là tổng số pixel phức được tạo ra từ việc lấy biến đổi Fourier hình ảnh . nhưng giá trị biên độ của đáp ứng sẽ yếu hơn.6. y-1) W2 (x-1.

cải thiện ảnh và khôi phục ảnh. Cặp biến đổi Fourier hai chiều của hình ảnh NxN được định nghĩa như sau: F(u. 2. 1. Biến đổi Fourier một chiều cũng là một công cụ rất mạnh trong việc phát hiện chuyển động của vật.F(u) = 1 N ∑ x =0 N −1 f(x)e-2jπux / N (3.N-1.v=0.2. Tuy vẫn còn hạn chế về mặt tính toán nhưng biến đổi Fourier rời rạc có rất nhiều ứng dụng trong các lĩnh vực tái tạo ảnh.v)ej2π (ux+vy)/N (3.. sau đó tính biến đổi Fourier các phần tử của mảng đó. Bằng cách coi biên của vật như mảng một chiều các điểm.25) Nếu tính trực tiếp từ các phương trình (3. Biến đỏi Fourier ngược cho lại f(x) được định nghĩa như sau: f(x) = ∑ F (u ) e2jπux / N u =0 N −1 (3. 2.y) = 1 N ∑ ∑ u =0 v =0 N −1 N −1 F(u..y=0. việc tính toán có thể đạt tới tốc độ ánh sáng nhờ sử dụng các thiết bị quang học .. . .….N-1..log2 N phép tính. Sử dụng thuật toán biến đổi Fourier nhanh cho phép giảm đáng kể số lượng phép tính xuống còn N. từ các giá trị F(u) thu được có thể biết được dạng biên của vật. ở đây N được giả sử là một số nguyên mũ 2.25) với u=x=0. 1.1.N-1 thì phải thực hiện khoảng N2 phép cộng và phép nhân.27) với x.24) với u = 0. N-1 và f(x. 2.v) = 1 N ∑ ∑ x =0 y =0 N −1 N −1 f(x. hai chiều..26) với u..4 Làm trơn ảnh. Trong phương trình này j=√-1 và u gọi là biến tần số.1.y)e-j2π (ux+vy)/N (3.24) và (3.... 3. Đối với biến đổi Fourier liên tục.

Các giá trị này được sắp xếp như . trước tiên phải sắp xếp các giá trị của pixel và các lân cận của nó. Ví dụ: trong lân cận 3x3 điểm giữa là giá trị lớn nhất thứ 5.y) .y) và P là tổng số điểm trong lân cận.y nằm trong f(x. Nói cách khác.28) với mọi x.2. S là tập hợp tọa độ các điểm trong lân cận (x.20.4.3. ảnh đã được làm nhẵn có được bằng cách sử dụng phương trình: G(x.m) (3.20.Lọc tuyến tính.y). Để thực hiện lọc điểm giữa trong một lân cận của một điểm ảnh. thủ tục sẽ tạo ra một hình ảnh đã làm trơn g(x. xác định điểm giữa và gán giá trị này cho pixel.m )∈S f(n. Phương pháp lọc điểm giữa (lọc trung vị)_ Lọc phi tuyến. 3.100).y). Lấy trung bình các điểm ảnh lân cận là một kỹ thuật miền không gian đơn giản để làm trơn ảnh.20.y) gồm cả (x.15. Sự mờ này có thể làm giảm đáng kể nhờ việc sử dụng bộ lọc điểm giữa ở đây chúng ta sẽ thay cường độ của mỗi điểm ảnh bằng độ lớn cường độ của điểm giữa trong một lân cận xác định trước của điểm ảnh đó thay vì lấy trung bình các điểm ảnh.1 Lấy trung bình các điểm ảnh lân cận. trong lân cận 5x5 điểm giữa là giá trị lớn nhất thứ 13v. ta nhóm các giá trị bằng nhau như :giả sử một lân cận 3x3 có các giá trị (10.20. Một trong những khó khăn chủ yếu của phương pháp lấy trung bình các điểm ảnh lân cận là nó làm mờ biên của hình ảnh và các chi tiết sắc nét khác.y) = 1 ∑ p (n . Cho một hình ành f(x.20.4.25.v…Khi trong lân cận có nhiều giá trị giống nhau.y) .y) của ảnh này có được bằng cách lấy trung bình các giá trị cường độ các điểm ảnh của f nằm trong một lân cận xác trước định của (x. cường độ tại mỗi điểm (x.

20.…K . Độ lệch chuẩn tại bất kỳ điểm nào trong hình ảnh trung bình được cho bởi: σ g (x.y) (3.y) (3. 3.y). Mục tiêu của phương pháp trung bình hoá là tạo ra một hình ảnh tốt hơn bằng cách cộng các hình ảnh nhiễu cho trước gi(x.3 Trung bình hoá hình ảnh Xét một hình ảnh nhiễu g(x.y) được tạo ra bằng cách lấy trung bình K hình ảnh nhiễu khác nhau.20.y tức là: G(x.y) = 1 K σ n (x.20. Nếu nhiễu thoả mãn các ràng buộc nêu trên.33) .y) (3. i=1. và σ (x.y)} = f(x.sau(10. tức làm loại bỏ các điểm nhọn cường độ xuất hiện trong các mặt nạ lọc.25.y).30) do đó ta có: E { g (x.32) ở đây E { g (x.y) vào hình ảnh f()x.y) g K n (3.100) và các điểm giữa của lân cận này là 20 Như vậy thực chất của việc lọc điểm giữa là ép các điểm có cường độ khác biệt giống các lân cận của nó hơn.15.y) Và : 2 1 2 (x.y) là các biến của g và g n n tại toạ độ (x.20.y). bài toán sẽ là đơn giản và hình ảnh g(x.4.29) ở đây giả sử nhiễu là không tương quan và có giá trị trung bình bằng 0.y) = σ (x.2.y) +n(x.y) tạo ra do cộng nhiễu n(x.y) = f(x.y) = 1 K ∑ i =1 K g(x.y)} là giá trị mong đợi của g .31) σ (3. σ 2 2 (x. g (x.

bổ xung các lỗ nhỏ 2. Vì hình ảnh nhị phân có hai giá trị nhiễu trong trường hợp này tạo ra các hiệu ứng như biên mấp mô. Do đó nếu Bi =1.3. Loại bỏ các điểm 1 biệt lập 4.34) được áp dụng đồng thời cho tất cả các pixel. thiếu góc và các điểm bị tách ra. lân cận này cho một mặt nạ kích thước 3x3 như hình 3.7.34) ở đây “. Ý tưởng cơ bản là kiểm tra một hàm BOOL đối với lân cận tâm tại pixel p và gán p là 1 hoặc 0 phụ thuộc vào sự sắp xếp về mặt không gian và giá trị của các pixel lân cận. Theo qui ước.g. ngược lại p được gán là 0. p được gán là 1. Hình 3.4.7. loại bỏ các biếu nhỏ dọc các cạnh 5. các lỗ nhỏ. Các lân cận của p sử dụng để làm nhẵn ảnh a d f nhị phân điểm tối là một và điểm sang là 0 Làm nhẵn ảnh nhị phân được tiến hành theo các bước sau: 1. pixel trong mặt nạ được gán là 1 và pixel trắng được gán là 0. bổ xung các khấc trong các cạnh 3. bổ xung các góc thiếu Hai quá trình làm nhẵn đầu tiên được thực hiện bằng cách dung biểu thức Bool sau: b p g c e h Bi =p+b.(d+e) +d.4 Làm trơn hình ảnh nhị phân Trong ảnh nhị phân điểm đen được quy định là 1 và điểm trắng được quy định là 0. Bước 3. Phương trình (3.e(b+g) (3. trong đó giá trị tiếp theo của mỗi vị trí pixel được xác định trước khi các pixel khác đã bị thay đổi.” Và “+” lần lượt là ký hiệu của AND và OR. Do hạn chế về thời gian xử lý nên việc phân tích chỉ giới hạn trong 8 lân cận của p.4 được thực hiện tương tự bằng cách đánh giá biểu thức Bool sau: .

(a + b + c + e + h) +p (3.37) (3.g. (b + a + c + d + f ) +p Và B= p (b.g) . (3. và trái dưới được bố sung bằng các biểu thức: B= p (a.36) ở đây dấu gạch trên cho biết phần bù logic. các điểm thiếu góc phải dưới trái trên.b.f.9(b) Ảnh sau khi áp dụng B1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 (3.d) .h) . ( f + g + c + e + h) +p B= p (e.e) .9(a) Hình ảnh gốc 3. Và p=1 nếu B2 =0.c.B2 =p{(a+b+c). ( g + a + h + d + f ) +p Bốn biểu thức này thực hiện bước 5 của thủ tục làm trơn ảnh: Ví dụ 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 3. (e+g+h)+(b+c+e). Tương tự.35) Các điểm thiếu ở góc phải trên được bổ xung bằng biểu thức sau: B= p (d.38) 1 1 .39) (3.(d+f+g)} đồng thời cho tất cả các pixel .

10. Quá trình phát hiện biên bằng phương pháp lấy đạo hàm .9 (d) Ảnh cuối cùng sau bước 5 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 x 3.5.10. được coi là bước xử lý khởi đầu cho rất nhiều bài toán phát hiện vật.x 1 1 1 1 1 1 1 1 1 1 x 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 x 1 1 1 x 3.9 (c) Ảnh sau khi áp dụng B2 3. Về cơ bản ý tưởng phát hiện biên của vật là tính đạo hàm cục bộ được minh hoạ trên hình 1. ảnh Tiết diện của đường nằm ngang Đạo hàm bậc nhất Đạo hàm bậc hai (a) (b) Hình 3.5 Phát hiện biên Phát hiện biên đóng vai trò quan trọng trong nhìn thấy máy.1 Nguyên tắc. 3.

y).y) –f(x-1.y) tại vị trí (x.40) G cho biết hướng tốc độ thay đổi cực đại của f tại vị trí (x.41) Lấy xấp xỉ.y) được định nghĩa như vectơ hai chiều : ⎡ ⎤ ⎢ ⎥ ⎢ ⎥ ⎢ δf ⎥ ⎡Gx ⎤ G{f(x.y)]. y) δx δf = f(x. nghiã là: Gx = và: Gx = δf = f(x.y) –f(x.43) (3. Tuy nhiên.y)} = ⎢ ⎥ = ⎢ ⎥ ⎣Gy ⎦ ⎢ δx ⎥ ⎢ δf ⎥ ⎢ ⎥ ⎣ δy ⎦ (3.y-1) δx (3.42) (3. Một trong các phương pháp đó là sử dụng các vi phân bậc nhất giữa các pixel liền kề nhau.44) . ta có: G[f(x.a) Vật sang trên nền đen b) Vật sang trên nền sang Toán tử độ dốc: Độ dốc của một hình ảnh f(x.y)] = |Gx| + |Gy| Việc lấy xấp xỉ dễ thực hiện với phần cứng: Từ phương trình (3.y)] = [Gx2 +Gy2]⅟2 = ⎢⎜ ⎟ ⎣⎝ δx ⎠ ⎛ δf ⎞⎤ ⎜ ⎟⎥ ⎜ δy ⎟ ⎝ ⎠⎦ (3. Có một số cách để tính các đạo hàm bậc nhất này trong hình ảnh số.41) việc tính toán độ dốc dựa vào các đạo hàm bậc nhất δf δx và δf δy . trong phát hiện biên chỉ quan tâm đến giá trị biên độ của véctơ và được gọi là độ dốc và được ký hiệu là : G[f(x. ở đây: ⎡⎛ δf ⎞ G[f(x.

Hai mặt nạ này thường được gọi là các toán tử Sobel. y + 1)] − [ f (x − 1. y − 1) + f (x + 1. Một lân cận 3x3 cảu (x. y + 1)] δx (3. do đó làm giảm độ dốc giảm nhạy đối với nhiễu.y) = (3.y sẽ thu được độ dốc của tất cả các điểm trong ảnh.11(b) Mặt nạ để tính Gx nạ để tính Việc tính toán độ dốc trên vùng 3x3 có ưu điểm hơn so với dung các phương trình (3.y) Gy 3.11b và Gy được tính theo mặt nạ hình 3. y − 1) + 2 f (x − 1. y − 1) + 2 f (x.11 (c) Mặt = (c + 2e + 1) − (a + 2d + g ) .y) e h i -1 0 1 -2 0 2 -1 0 1 -1 -2 -1 3.48) .11(a) Lân cận 3x3 của (x. y )] (3. Gy được tính như sau: Gx= δf = δx [ f (x + 1.46) ở đây các lân cận của (x. Các đáp ứng cảu hai mặt nạ này tại điểm (x. y ) + f (x + 1.y) dung các chữ cái này được trình bày trên hình 3.11 c.y) bằng độ dốc của ảnh lối vào tại điểm đó nghĩa là: G(x. y − 1) + 2 f (x + 1.y ) dựa vào tính toán độ dốc. Bằng cách di chuyển các mặt nạ này khắp hình ảnh f(x.45) Và : Gx= δf = [ f (x − 1.38) để có được sự xấp xỉ độ dốc tại điểm đó. Gx. Dựa {vào phương pháp mặt nạ ta có thể tính Gx theo mặt nạ hình 3.y bất kỳ được kết hợp nhờ hai phương trình (3. y − 1)] = ( g + 2h + i ) − (a + 2b + c ) (3.Đối với lân cận kích thước 3x3 tâm tại (x. y − 1) 0 0 0 1 2 1 3.y) = G [ f (x.47) Phương pháp khác tạo ảnh nhị phân bằng cách dùng quan hệ sau: ⎧1 ⎪ ⎨ ⎪0 ⎩ G(x. y + 1) + f (x + 1.40) là tăng giá trị trung bình.11a a d g b c (x. y + 1) + 2 f (x. y ) + f (x + 1.y).f (x − 1. Có nhiều phương pháp tạo ra ảnh lối ra g(x.37 và (3. Phương pháp đơn giản nhất cho giá trị g tại (x.39) và (3.y) được biểu diễn bởi các chữ cái từ a đến i.

y) >T được gọi là một điểm của vật: ngược lại nó là một điểm của nền. Laplacian được định nghĩa như sau: L [ f (x.y) [T 1 .y) bất kỳ có f(x.46) Laplician sẽ bằng 0 trong các vùng không đổi và trên phần dốc của mép. nhất là trong các ứng dụng đòi hỏi năng suất dữ liệu cao.y) (3. Do đó toán tử này thường được coi như bộ phát hiện việc thiết lập pixel cho trước là ở trên mặt nạ đen hay trắng của mép. Giả sử biểu đồ cường độ được trình bày trong hình 3. Thực hiện phương trình (3.13b. Loại ngưỡng đa mức này nói chung là độ tin cậy kém hơn . Vì là đạo hàm bậc hai nên nó không nhạy với nhiễu. các pixel nền và vật này có các cường độ được nhóm thành hai mode trội chủ yếu.49) Với các ảnh số. y )] = δ2f δ2f + δx 2 δy 2 (3.44) có thể được xem như là một thủ tục lấy ra những pixel được đặc trưng bởi sự chuyển dịch đáng kể về cường độ sáng. Trong trường hợp này chỉ các pixel mép mà độ dốc của chúng lớn hơn T mới được coi là quan trọng .13a tương ứng với một hình ảnh f(x. một điểm (x.y) [T 2 < T1 vào một lớp đối tượng. Mặt nạ để tính Laplician 0 1 0 1 4 1 0 1 0 Laplician phản ứng với những sự dịch chuyển về cường độ. Do đó. Cách để phân chia các vật thành hai mode là chọn một ngưỡng T và so sánh cường độ của vật với ngưỡng đó. ta cũng dung phương pháp cơ bản trên. Toán tử Laplacian. Do đó sử dụng phương trình (3. y + 1) + f (x.12. Trong trường hợp này biểu đồ hình ảnh được đặc trưng bởi 3 mode trội (ví dụ hai vật sang trên một nền tối). Ở đây.y) tạo thành các vật sáng trên nền đen.6 Lập ngưỡng Phân ngưỡng là một trong những kỹ thuật chủ yếu được sử dụng tỷong các hệ thống nhìn trong công nghiệp để phát hiện vật. các điểm có f(x.: Laplacian là một toán tử đạo hàm bậc hai được định nghĩa như sau: L [ f (x. y ) + f (x. Trong hợp tổng quát hơn được trình bày trong hình 3.y) > T2 cho một lớp đối tượng khác và thuộc nền nếu f(x. y ) + f (x − 1. phân các điểm có T1 < f(x.46) có thể dựa vào mặt nạ như trong hình 3. y )] = [ f (x + 1.ở đây T là ngưỡng không âm. 3.10 Hình 3. y − 1)] -4f (x. toán tử này ít khi được sử dụng một mình để phát hiện biên.

y) = Do đó bằng cách kiểm tra g(x.50) G(x. y )] ở đây f(x. y. Một ngưỡng (b) Nhiều ngưỡng Dựa vào các khái niệm ở trên ta có thể xem lập ngưỡng như là một phép toán như sau: T= T [x. còn pixel có giá trị không ứng với nền. y ) f (x.loại ngưỡng đơn mức do sự khó khăn trong việc thiết lập ngưỡng đa mức để tách hiệu quả các vùng mong muốn.y) p(x. . nhất là khi số mode biểu đồ tương ứng là lớn.y) ta thấy các pixel có giá trị 1 (hoặc mức cường độ quy ước khác) tương ứng với vật.y) là cường độ của điểm (x.y) biểu thị một vài thuộc tính cục bộ của điểm này.y) > T 0 if f(x.y) đã lấy ngưỡng được định nghĩa như sau: 1 if f(x.y) Một ảnh g(x.y) ≤ T (3. Lược đồ cường độ (a). Ví dụ như cường độ trung bình của lân cận có tâm tại (x. p(x. T T1 T2 Hình 3.13.

1: Mô hình thực nghiệm : camera và mạch đk motơ bước. PHẦN 2:PHẦN THỰC NGHIỆM Hình P2. chương trình cũng chỉ cho phép điều khiển camera bám theo một vật chuyển .y). • TÓM TẮT MÔ HÌNH SẢN PHẨM WEBCAM TỰ ĐỘNG THEO DÕI ĐỐI TƯỢNG DI CHUYỂN: Như là một phần của đề tài. Nếu T phụ thuộc cả f(x.y). ngưỡng cục bộ hay đa ngưỡng (hình 3. Ngoài ra nếu T phụ thuộc vào các tọa độ x và y.Với mục tiêu minh hoạ cho đề tài nên các phần cứng và chương trình đã được đơn giản hoá …như là camera chỉ bám vật theo hai chiều trái và phải.10b).y) và p(x. tôi đã cho thực hành cho camera theo dõi vật dựa trên phần cứng đơn giản. nó được gọi là ngưỡng .Khi T chỉ phụ thuộc vào f(x.10a). ngưỡng được gọi là toàn cục hay ngưỡng đơn (hình 3.

1 Tạo một số cửa sổ hiện ảnh.2: Sơ đồ khối mô hình thưc nghiệm CHƯƠNG 1: NGÔN NGỮ LẬP TRÌNH 1.Tuy nhiên ở phần lý thuyết sau đây tôi sẽ cố gắng trình bày những gì tốt nhất của đề tài thực sự có thể làm được.1 Giới thiệu Hiện nay có rất nhiều ngôn ngữ lập trình mới và mạnh. 1. Ngôn ngữ lập trình Visual C++ là một trong những ngôn ngữ như vậy. Các ngôn ngữ lập trình trên Window vừa có khả năng như các ngôn ngữ chạy trong DOS vừa có khả năng cung cấp một giao diện trực quan giúp người sử dụng giao tiếp với ứng dụng một cách dễ dàng.Nền tảng cho chương trình ở đây là thư viện mã mở của Microsoft: AVICap và được triển khai trên nền của ngôn ngữ lập trình Visual C++ vesion 6.2.động duy nhất.0. Để tạo một cửa sổ ta dùng hàm “capCreateCaptureWindow” Ví dụ: HWndc = capCreateCaptureWindow ( .2 Một số hàm và thủ tục xử lý ảnh 1. webcam USB camera LPT port PC Môtơ Bước Hình P2. Trong luận văn sẽ sử dụng ngôn ngữ này.

CapStatus. // tên cửa sổ 0. 0. Ví dụ: fOK = SendMessage (hWndc. 120. WM_CAP_DRIVER_CONNECT. Mỗi cửa sổ hiện ảnh có thể cung cấp 3 hộp thoại khác nhau dùng để điều khiển các khía cạnh của quá trình số hóa hình ảnh và hiện ảnh. Thiết lập trạng thái của cửa sổ hiện ảnh.uiImageWidth.4. // tên cửa sổ WS_CHILD | WS_VISIBLE. 0L). 1. Trước khi hiển thị mỗi hộp thoại cần gọi macro “capDriverGetCaps” và kiểm tra cấu trúc CAPDRIVERCAPS khai báo xem cửa sổ hiện ảnh có hiện thị hộp thoại hay không. CapDriverGetCaps (hWndC. 1. 0. .uiImageHeight. Ví dụ: CAPSTATUS CapStatus.2. sizeof (CAPSTATUS) ). Hiển thị các hộp thoại để thiết lập các thông số của hình ảnh. Để thiết lập kích thước của cửa sổ hiện ảnh cho tất cả các chiều hình ảnh nhận được từ macro “capGetStatus” trong cấu trúc CAPSTATUS ta sử dụng hàm “SetWindowPos”. (int) nID/ * child ID */). SWP_NOZORDER |SWP_NOMOVE). // vị trí và kích thước của cửa sổ (HWND) hwndParent.2. 0. // hiện thị hộp thoại khuôn dạng hình ảnh.fHasDlgVideoSource) CapĐlgVideoSource (hWndC). 160. CapStatus. &CapStatus.3.2. sizeof (CAPDRIVERCAPS) ). 1. & CapDrvCaps. NULL.2 Kết nối với thiết bị thu ảnh. CapGetStatus (hWndC. // hiện thị hộp thoại nguồn hình ảnh. If (CapDriverCaps. 0. Ví dụ: CAPDRIVERCAPS CapDriverCaps. CapDriverDisconnect(hWndC). SetWindowPos (hWndC. Để kết nối và dừng kết nối cửa sổ hiện ảnh với thiết bị thu ảnh dùng macro “capDriverDisconnect”.(LPSTR) “My Capture Window”.

DWORD dwSize.fHasDlgVideoFormat) { CapĐlgVideoFormat (hWndC).fHasDlgVideoDisplay) CapDgVideoDisplay (hWndC). Vì các khuôn dạng hình ảnh ứng với thiết bị riêng nên trong ứng dụng cần kiểm tra giá trị trả về để xác định khuôn dạng có được chấp nhận hay không. &CapStatus. // Có các kích thước hình ảnh mới không? CapGetStatus (hWndC. Marco “capGetVideoFormatSize” để xác định kích cỡ bộ đệm và hàm “capGetVideoFormat” để xác định khuôn dạng hình ảnh hiện tại .6. If (CapDriverCaps. TRUE). DwSize =capGetVideoFormatSize (hwndC). Thay đổi thiết lập cho hình ảnh hiện. } // hiển thị hộp thoại hiển thị hình ảnh.2. 66).7. sizeof (CAPSTATUS)).2. // Ngừng duyệt 1. Ví dụ: LPBITMAPINFO lpbi. lpbi= GlobalAllocPtr (GHND. dwSize). Các ứng dụng có sử dụng marco “capSetVideoFormat” (hoặc thông báo WM CAP SET VIDEOFORMAT) để gửi cấu trúc tiêu đề BITMAPINFO tới các cửa sổ bắt ảnh. Vì chiều dài của cấu trúc là thay đổi.5. // bắt đầu duyệt // Duyệt capPreview (hWndC. 1. nên trong các ứng dụng luôn luôn cần phải xác định kích cỡ và cấp phát bộ nhớ cho cấu trúc trước khi tìm kiếm khuôn dạng hình ảnh. FALSE). capGetVideoFormat (hwndC. Ví dụ: CapPreviewRate (hWndC. . lpbi. Cấu trúc BITMAPINFO có chiều dài thay đổi để cung cấp các khuôn dạng dữ liệu nén chuẩn. 1. // tốc độ hiển thị tính bằng ms CapPreview (hWndC.If (CapDriverCaps.2. dwSize). Lấy và thiết lập khuôn dạng hình ảnh. Duyệt trước hình ảnh Để thiết lập tốc độ hiển thị khung cho mode duyệt trước ta sử dụng macro “capPreviewRate” và sử dụng macro “capPreview” để thay thế cửa sổ hiện ảnh trong mode duyệt trước. // nếu có báo cho cửa sổ tra về sự thay đổi kích thước.

WORD wError. 1. (int) 0). CapCaptureGetSetup (hwndC. WORD wDriverCount = 0. char achDeviceVersion [100]. lỗi và trạng thái. Đăng ký hàm callback lỗi sử dụng macro “capSetCallbackOnError”. CapSetCallbackOnStatus (ghWndCap. Thêm các hàm Callback cho một ứng dụng. fpStatusCallback). sizeof (CAPTUREPARMS)). WS_CHILD | WS_VISIBLE. 0.2. Ví dụ: Case WM_CREATE: { char achDeviceName [80]. fpErrorCallback). Một ứng dụng có thể đăng ký hàm gọi lại với cửa sổ hiện ảnh để nó thông báo ứng dụng trong các tình huống sau: • • • • Thay đổi trạng thái Có lỗi xảy ra Các bộ đệm âm thanh và khung hình ảnh có thể sử dụng ứng dụng đang thực thi Ví dụ tạo một cửa sổ hình ảnh và đăng ký các hàm Callback khung. WORD wIndex.0.8. &CaptureParms. . CapCaptureSetup (hWndC. CaptureParms. (HWND) hWnd. sizeof (CAPTUREPARMS)). char achBuffer [100]. & CaptureParms. 120. chuỗi hình ảnh. Ví dụ cũng đưa vào một câu lệnh đơn giản để ngăn chặn hàm Callback. // taọ cửa sổ hiện hình ảnh sử dụng macro “capCreateCaptureWIndow”.Để thay đổi tốc độ hiện hình ảnh từ giá trị mặc định ta sử dụng các macro “capPreviewGetSetup” và “capCaptureSetSetup” Ví dụ: CAPTUREPARMS CaptureParms. HMENU hMenu.dwRequestMicroSecPerDFrame = (DWORD) (1. Float FramesPerSec = 10. GhWndCap = capCreateCaptureWindow ((LPSTR) “CaptureWindow”.0e6/ FramesPerSec).160. CapSetCallbackOnError (ghWndCap. 0. // Đăng ký hàm Callback trạng thái sử dụng macro “capSetCallbackOnStatus”.

CapSetCallbackOnFrame (ghWndCap. lập tức sẽ xuất hiện thông báo lỗi như sau : "The exception privileged instruction occurred in the application at location . Là một biện pháp bảo mật hệ thống .} CHƯƠNG 2: ĐIỀU KHIỂN CỔNG LPT TRÊN WINDOWS NT/2000/XP 2. Win2000 hay là WinXP. fpFrameCallback). Tương tự với các hàm callback khác.. mọi điểu tưởng như đơn giản đó không còn nữa. Windows sắp xếp tất cả các chương trình thành hai loại . Break.. ta có thể nghĩ rằng “Mình đã mắc lỗi ở đâu đó trong chương trinh ?” nhưng rõ ràng chương trình chạy tốt trên Win98 …vậy thì lỗi là do đâu ?Câu trả lời sẽ được giải đáp ở ngay sau đây. outportb() hay là _inport() và _outp() trên hệ điều hành như Win2000. //Kết nối vưói thiết bị thu ảnh.Nhưng khi làm việc với các hệ điều hành mới hơn như là WinNT4." Khi bắt đầu nhìn thấy thông báo trên. } case WM_CLOSE { // Để ngừng callback khung sử dụng macro “capSetCallbackOnFrame”. CapSetCallbackOnFrame (hWndC.Chúng ta có thể sử dụng các hàm Inportb() và Outportb() hay là _inp() và _outp() một cách trực tiếp và không mắc phải bất cứ vấn đề gì. Windows NT hạn chế một số đặc quyền của các loại ngôn ngữ lập trình khác chạy trên nó. Break.// Đăng ký hàm Callback trạng thái sử dụng macro “ capSerCallbackOnStatus”.1 Đặt vấn đề Viết chương trình giao tiếp với cổng song song của máy tính thật đơn giản với Dos và cả với Win95/98. Khi chúng ta cố gắng chạy một chương trình sử dụng các hàm thông thường như là inportb() . đó là mode người dùng (user mode) và mode nhân(kenel .. NULL).

Nó làm việc như nhau đối với tất cả các hệ điều hành Win98/2000/NT và XP. chạy trên mode ring3() (với mode người dùng) và mode ring() với mode nhân. 2.dll cho Win98/2000/NT/XP .Driver sẽ được tự động cài đặt và tùy chỉnh khi mà dll này được load tới.Lời giải đáp cho bài toán trên: Ở đây sẽ giới thiệu về inpout32. 7.Có thể dễ dàng sử dụng với VC++ và VB. nó sẽ cài đặt driver ở mức nhân và thông báo cho cổng song song biết driver đã được cài đặt. DLL này sẽ kiểm tra hệ điều hành đang được sử dụng . 5. nếu là 9X thì Dll se sử dụng các hàm _inp() và _outp() để đọc cổng song song. 3. Như vậy cách giải quyết ở đây là chúng ta bắt đầu vấn đề với việc viết một chương trình dưới kernel mode để đọc và viết dữ liệu qua cổng song song còn chương trình truyền dữ liệu tới đó sẽ là ở mode người sử dụng.Không yêu cầu các phần mềm khác hay là thiết bị khác phải được cài đặt 4. Mode người dùng bị hạn chế sử dụng các hàm liên quan đến IN.htm. 2.mode).Thực tế thì mã sử dụng không thể hiểu được đang chạy trên hệ điều hành gì? Dll này có thể sử dụng trên tất cả các phiên bản Windows như nhau . dll này có những đặc điểm sau: 1. còn nếu là WINNT hay 2000/XP .Các driver thiết bị có thể chạy ở mức nhân của hệ thống.3.Cách làm việc với inport32. 2. Cuối cùng là các giao tiếp sẽ bị chặn đứng bởi hệ điều hành khi ta cố gắng thực thi các lệnh đọc và viết thông qua cổng song song. Khi bắt đầu làm việc.Nó có thể điều khiển thiết bị ở mức nhân.Điều này không hẳn là dễ dàng nhưng chúng ta đã có sự hỗ trợ bởi các driver đã được cài đặt và tùy chỉnh.Không cần các hàm đặc biệt API . OUT …Nên khi mà hệ điều hành phát hiện chương trình ở mode người dùng đang cố gắng chạy các hàm đó.Có thể minh họa các ý trên như sau: Người dùng gọi các hàm inp32() hoặc out32() Kiểm tra phiên bản hệ điều hành Win9X WinNT .2.dll: Inpout32. chỉ cần hai hàm đó là Inp32 và Out32.Tài liệu sử dụng và mã nguồn miễn phí được cung cấp và hướng dẫn tại http://www.com/parport.Nhưng trong khi đó . 6. đối với các chương trình thực hiện ở mức nhân thì hệ điều hành không có cách nào để ngăn chặn được. Hệ điều hành sẽ lập tức dừng chương trình đó lại và đưa ra thông báo lỗi như ta thấy.dll có thể làm việc dưới tất cả các hệ điều hành mà không cần sửa đổi mã chương trình cần soạn thảo.lvr.

sử dụng thư Y viện API Cố gắng load tới driver này thành công ? Driver đọc hoặc ghi dữ liệu từ cổng Song Song sử dụng các hàm HAL N Cài đặt driver Kết thúc Có hai khối quan trọng của chương trình là: 1. Kernel mode driver Hwinterface. 3)’hwinterfaceDeviceControl’. nó tạo tới thiết bị một liên kết tượng trưng.c” là file nguồn chính.Sử dụng thư viện các hàm _inp() và _out() để truyền dữ liệu Y Kiểm tra hwinterface. viết/đọc cổng song song.sys Mã nguồn của Hwinterface. cho phép đọc và viết qua cổng song song nhờ các mã thông thường.cpp” có nhiệm vụ cài đặt driver cho mode kernel .Còn “inpout32drv.Bao gồm các chức năng sau : 1) ‘Driver Entry’: được gọi khi mà driver đã được load tới.Oversion. DLL Inpout32 mà ta đang xét.dll support là: .được gọi khi driver không còn được tham chiếu tới nữa. …Hai chức năng được inpout32. điều khiển thông qua DeviceIOControl API.cpp kiểm tra phiên bản hệ điều hành. DLL Inpout32 Các hàm trong thư viện DLL được độc lập cung cấp bởi hai file .cpp”. 2)’hwinterfaceUnload’.tại đó thì “hwinterfacedrv. đó là “inpout32drv. Driver dành cho thiết bị ở kernel mode dựa trên DLL trong mã nhị phân 2.cpp” và “osversion. dẫn tới đó.sys được định vị bởi thư mục “kernel_mode_drever_source”.sys driver kernel mode đã được load tới? N Cho phép dữ liệu được truyền nhờ driver.

dll CHƯƠNG 3: MINH HỌA THUẬT TOÁN VÀ CHƯƠNG TRÌNH . nhưng tốt hơn là nên sử dụng với VB) giống như là hwinterface. hàm này được gọi khi mà hàm ‘Opendriver ’ không thể thực thi trong ‘hwinterface’. ghi dữ liệu ra cổng song song. 2)’Closedriver’.khởi động dịch vụ hwinterface sử dụng Service Control Manager API. 3)’Opendriver’. còn có thể sử dụng hwinterface.điều khiển driver đóng hay mở. Các chức năng được cung cấp bởi Inpout32. được gọi trước khi gỡ bỏ driver ra.được gọi khi dll được load tới hay không load tới. 4)’inst’. 5)’Start’. * ngoài ra.1)’Inp32’.Khi dll này được load tới.giải nén ‘hwinterface.ocx ActiveX control (cho cả VB và VC++.dll là : 1)’DllMain’. 2)’Out32’. 6)’System Version’ kiểm tra phiên bản hệ điều hành.mở một driver trong hwinterface.nó sẽ kiểm tra phiên bản của hệ điều hành và load tới hwinterface.sys’ từ mã nhị phân tới thư mục ‘systemroot\driver’ để phục vụ. đọc dữ liệu từ cổng song song. trả lại giá trị tương ứng.sys nếu cần.

Kết hợp với lớp “inpout32drv. ta sử dụng capSetCallbackOnFrame macro.3. chúng ta hiển nhiên cần thu thập và phân tích các khung ảnh (frame) riêng rẽ đang được thu thập và xủ lý . tôi chọn một lớp ứng dụng của window đó là AVICap để thực hành bám đối tượng.2: Ảnh camera bắt được khi xử lý với một vật thể .1: Minh họa sản phẩm Hình P2. .cpp” để có thể điều khiển cổng song song cho chức năng điều khiển chuyển động của đế camera. Trong ứng dụng thử nghiệm này.3.cpp> Để có thể bám theo đối tượng từ dữ liệu nhận vào của một camera động. #include <inpout32drv.Hình P2.AVICap là một lớp ứng dụng của Window cung cấp các ứng dụng vô cùng thuận lợi cho việc viết các chưng trình giao tiếp đặc biệt là truy nhập các thiết bị video như là camera đã được sử dụng trong chưng trình demo này.Và để thu thập các frame này trước khi duyệt.

/* Số byte thực tế đã sử dụng Bytes actually used.291 0. Color Space Trước khi bắt đầu tiến trình với các frame ảnh. /*Các Cờ Flags. } #define VHDR_DONE 0x00000001 #define VHDR_PREPARED 0x00000002 #define VHDR_INQUEUE 0x00000004 #define VHDR_KEYFRAME 0x00000008 Mỗi một khung tiến trình gọi lại được kết hợp với cửa sổ chụp ảnh. /* Độ dài của bộ đệm Length of buffer.072 0.BOOL capSetCallbackOnFrame(HWND hwnd. LPVIDEOHDR lpVideoHdr).Các giá trị NULL dành cho các tham số bên trong nếu như vô hiệu hoá các giá trị được cài đặt tại hàm duyệt lại ngay trước đó.000 0.000 ][ 1 ] Ma trận kết qu này là c sở cho các phép biến đổi số học tuyến tính.Một cách tiếp cận rất đơn giản và chắc chắn đó là chia ra các thành phần của độ sáng .098 0. Chúng ta sẽ xét tất cả các khung để bắt đầu bám theo đối tượng.YUV là một không gian màu rất cần thiết mà chúng ta cần tìm hiểu. */ DWORD dwUser. FrameCallback fpProc).000 1. /* Con trỏ đệm Pointer to buffer.257 0. */ DWORD dwBytesUsed.063 ][ R ] [ U ] = [ -0.504 0.368 -0. tuy nhiên . */ DWORD dwReserved[4]. */ DWORD dwBufferLength. Đặc trưng màu mà chúng ta sẽ tìm hiểu ở chưng trình demo này là độ sáng.148 -0. giống như là phép biến đổi với hệ cơ sở bậc ba mới với các cơ sở thành phần là R = G = B . /* Thời gian bắt đầu nhận luồng frame nh Timefrom start of stream. typedef LRESULT (*FrameCallback)(HWND hWnd. */ DWORD dwTimeCaptured. DWORD dwFlags.500 ][ B ] [ 1 ] [ 0.000 0.Vậy nên. FrameCallback fpProc: Con trỏ chỉ tới hàm duyệt được gọi lại sau mỗi frame . Lớp LPVIDEOHDR được minh hoạ bởi: typedef struct videohdr_tag { LPBYTE lpData. HWND hwnd: (Handle to the capture window )Điều khiển các cửa sổ ảnh . mỗi một loại có cường độ và giới hạn khác nhau. quan trọng là chúng ta phải hiểu được sự khác nhau giữa các không gian màu được video số hoá . có một sự thay thế khác đó là sự phụ thuộc vào RGB24 là định dạng vào của một webcam tới YUV.439 0.500 ][ G ] [ V ] [ 0.Có nhiều không gian màu có thể được sử dụng. Mối quan hệ giữa RGB và YUV có thể minh hoạ bởi một mối quan hệ tuyến tính sau: [ Y ] [ 0. mà ở trong trường hợp này.439 -0.Việc chọn chính xác bảng màu sẽ làm đơn giản hoá những tính toán quan trọng và phức tạp. YUV không phi là định dạng có thể thu được từ một webcam. và chúng ta sẽ bám theo đối tượng dựa trên sự đánh giá về độ sáng .

y = i. ++i) { for (int j=0.Đặc trưng bám vật: Bây giờ chúng ta sẽ truy nhập trực tiếp đến độ sáng của mỗi điểm ảnh.x = pLeft..587*lpData[index+1] + 0. . } /* Luôn luôn bám theo bốn góc của đối tượng. i<nHeight..y = i. . /* Nếu độ sáng vượt quá giá trị ngưỡng cho phép*// if (Y > bThreshold) { /*Khởi tạo con trỏ */ if (init) { if (pLeft.114*lpData[index] + 0. Phải chắc chắn là đã sử dụng định dạng RGB24 cho lối vào của Webcam với đoạn mã sau đây: LRESULT CChildView::FrameCallbackProc(HWND hWnd.x = pBottom. /* Tính toán các thành phần màu */ Y = floor(0. LPVIDEOHDR lpVideoHdr) { .Thuật toán hình chữ nhật giữ và bám theo luôn luôn tại bốn điểm tương đối của vật tại mỗi khung ảnh nhận được(frame). một điểm cao nhất .x < j) { pRight. pRight.x = pRight.. */ else { pTop. pLeft. ++j) { /*Lấy. pBottom.x > j) { pLeft.299*lpData[index+2] + 0. for (int i=0.5).x = j.Có một thuật toán đơn giản có thể làm được điều là bám theo vật và xem vật như là đn giản chỉ là một đối tượng sáng . j<nWidth. một điểm thấp nhất .. } pBottom.x = j. } if (pRight.y = i. chỉ số bộ đệm thích hợp */ index = 3*(i*nWidth+j).x = j.Thuật toán đó sẽ được giới thiệu ngay sau đây và xin tạm gọi đó là “Thuật toán hình chữ nhật”.x = j. điểm trái nhất và điểm phải nhất nơi mà độ sáng vượt quá một giá trị ngưỡng xác định nào đó.

.y.y = pBottom. } } } } . Khung của hình chữ nhật sau đó được dễ dàng thay thế bởi một màu được định nghĩa tử trước.y = pRight. /* Trái */ lpData[index] = 0. /* Trên */ lpData[index] = 0.. /* G */ lpData[index+2] = 255. cái đó cho ta biết đâu là vị trí của vật sáng .y)*nWidth + i). iv> Và quan trọng nhất.x). /* B */ lpData[index+1] = 0. if (init) { /*Thay thế khung với các điểm màu được xác định trước. do tính thử nghiệm nên đề tài này sẽ sử dụng ngay thuật toán này để áp dụng) .x. ii> Nó không cho ta biết một chút thông tin gì về hình dạng của vật. iii> Nó không cho ta biết đâu là trọng tâm của vật.. /* B */ lpData[index+1] = 0. /* R */ } for (int i=pTop.pTop.y.x). /* R */ index = 3*((pBottom. /* G */ lpData[index+2] = 255. } Hình chữ nhật có thể được xây dung lên tử các điểm trên. i<=pBottom. ++i) { index = 3*((pTop. init = true. . nó không bao giờ có thể bám nếu có nhiều đối tượng chuyển động(Tuy nhiên . i<=pRight.y)*nWidth + i). /* B */ lpData[index+1] = 0.x. /* Dưới */ lpData[index] = 0. ++i) { index = 3*((i)*nWidth + pLeft. /* G */ lpData[index+2] = 255. /* R */ } } Thuật toán này rõ ràng còn chứa nhiều khuyết điểm: i> Nó chỉ cho biết vị trí của vật trên màn hình.y = i.. /* R */ index = 3*((i)*nWidth + pRight. /* Phải */ lpData[index] = 0. /* G */ lpData[index+2] = 255. */ for (int i=pLeft.y = pLeft. /* B */ lpData[index+1] = 0.

.3 :Ảnh camera bắt được nhiều vật Thuật toán này phát hiện theo đối tượng bằng cách nhận dạng các đoạn phần tử tạo nên đối tượng trên màn hình. /* --Biến sử dụng bởi thuật toán mới này.length = 0. std::list<QSEG> object.2.5).head. for (int j=0.Một thuật toán cải tiến hơn: Hình P3. BYTE Y.length == 0) { segment.114*lpData[index] + 0.587*lpData[index+1] + 0.Đối tượng được cấu trúc nên bởi các nhóm đoạn đó với nhau. -. Mỗi đoạn được tạo nên bởi tiêu đề và độ dài của mỗi đoạn đó.y = i.299*lpData[index+2] + 0. if (Y > bThreshold) { if (segment. int index. segment. for (int i=0.head. Y = floor(0. ++i) { segment. j<nWidth. ++j) { index = 3*(i*nWidth+j).x = j. i<nHeight.*/ QSEG segment.

head.push_back(segment). toạ độ của đối tượng trong ba chiều cũng có thể được xác định • Phần Chương Trình : // ChildView.head. lpData[index+1] = 0.length).begin(). ii> Nó có thể theo dõi được hình dáng của các đối tượng iii> Số lượng các điểm ảnh tạo nên đối tượng có thể dễ dàng tính toán được.*/ for (std::list<QSEG>::iterator i=object.y*nWidth + (*i). lpData[index+1] = 0. ++i) { index = 3*((*i).h" #include "ChildFrm. lpData[index+2] = 255. } } /* --Vẽ nên hình dáng của đối tượng với màu được định trước.h" #include "Tracker.h" #include "ChildView. lpData[index] = 255.} ++segment. lpData[index+2] = 255.x + (*i). } } if (segment.head.h" #include "MainFrm. index = 3*((*i).h" .end().head. lpData[index] = 255. i!=object.cpp : implementation of the CChildView class #include "stdafx.Với các mẫu thông tin và cách tính toán khong cách thích hợp.length.y*nWidth + (*i).x).length) { object. } Thuật toán mới này đã có những cải tiến tốt hơn sau: i> Nó có thể theo dõi nhiều đối tượng. -.

*LPQSEG. OnCaptureStop) END_MESSAGE_MAP() . OnDeviceName) ON_COMMAND(ID_CAPTURE_SOURCE. OnCaptureSource) ON_COMMAND(ID_CAPTURE_FORMAT. OnTrackBrightness) ON_COMMAND(ID_TRACK_STOP. OnCaptureFormat) ON_COMMAND(ID_CAPTURE_DISPLAY.#include "TrackDlg. DWORD CChildView::dwSegment = 0. OnCaptureDisplay) ON_WM_SIZE() ON_COMMAND_RANGE(ID_CAPTURE_100. DWORD CChildView::dwRectangle = 0.h> #include <list> #ifdef _DEBUG #define new DEBUG_NEW #endif typedef struct QSEG_ { POINT head. ID_CAPTURE_200. OnCaptureZoom) ON_COMMAND(ID_TRACK_BRIGHTNESS. // CChildView BYTE CChildView::bThreshold = 250. OnTrackStop) ON_COMMAND(ID_CAPTURE_STOP. UINT length.h" #include <math. CWnd) ON_WM_PAINT() ON_COMMAND(ID_DEVICE_REFRESH. OnDeviceRefresh) ON_COMMAND_RANGE(ID_DEVICE_NAME. ID_DEVICE_NAME+CVideoCapWnd::m_dwDeviceMax. CChildView::CChildView() { } CChildView::~CChildView() { } BEGIN_MESSAGE_MAP(CChildView. } QSEG.

lpszClass = AfxRegisterWndClass(CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS.Delete all entries before separator. } } while (miInfo.Find position of separator.cbSize = sizeof(MENUITEMINFO). .style &= ~WS_BORDER.fType != MFT_SEPARATOR) { mDev->DeleteMenu(0.*/ miInfo. cs.// CChildView message handlers BOOL CChildView::PreCreateWindow(CREATESTRUCT& cs) { if (!CWnd::PreCreateWindow(cs)) return FALSE.dwExStyle |= WS_EX_CLIENTEDGE. return TRUE. -. } void CChildView::OnPaint() { CPaintDC dc(this). IDC_ARROW). ::LoadCursor(NULL. &miInfo. MF_BYPOSITION). cs. // device context for painting // TODO: Add your message handler code here // Do not call CWnd::OnPaint() for painting messages } void CChildView::OnDeviceRefresh() { /* -.Get device menu. cs. miInfo. NULL).fType != MFT_SEPARATOR).*/ if (miInfo. -. do { /* -. --*/ CMenu *mDev = AfxGetMainWnd()->GetMenu()->GetSubMenu(3). mDev->GetMenuItemInfo(0. TRUE). /* -. MENUITEMINFO miInfo.fMask = MIIM_TYPE. reinterpret_cast<HBRUSH>(COLOR_WINDOW+1).

0).*/ if (m_theVideoCapWnd. -.DriverConnect(nID) == FALSE) { strErr.Retrieve device parameters.*/ if (m_theVideoCapWnd. } /* -.LoadString(IDS_ERR_CONNECT). strDevName).GetDriverDescription(i.LoadString(IDS_ERR_CAPWND).Want separate thread.CreateCaptureWindow(CString("").*/ .ID_DEVICE_NAME.Put device names before separator. -. WS_CHILD | WS_VISIBLE. /* -.*/ nID = nID .0. sizeof(CAPTUREPARMS)) == FALSE) { strErr. -. return.GetLength()) { mDev->InsertMenu(0.LoadString(IDS_ERR_GETSETUP). i<m_theVideoCapWnd. ++i) { m_theVideoCapWnd.Attempt to connect to driver. strDevName. MF_BYPOSITION. -./* -. if (m_theVideoCapWnd.0. this.m_dwDeviceMax. } /* -. CRect(0. strDevVer.*/ CString strDevName. if (strDevName. MessageBox(strErr). for (DWORD i=0. return.m_hWnd == NULL) { strErr.*/ CAPTUREPARMS capParms.CaptureGetSetup(&capParms.Get device index by subtracting the offset.Create the capture window if we haven't done do. MessageBox(strErr).0). return. } } } void CChildView::OnDeviceName(UINT nID) { /* -. if (m_theVideoCapWnd. strDevVer). CString strErr. MessageBox(strErr). -. ID_DEVICE_NAME+i. } } /* -.m_hWnd == NULL) { m_theVideoCapWnd. -.

0.Update device parameters.*/ CAPSTATUS capStat.Set preview rate.PreviewScale(TRUE) == FALSE) { strErr. capStat. sizeof(CAPTUREPARMS)) == FALSE) { strErr. return. return. sizeof(CAPSTATUS)) == FALSE) { strErr. return.*/ capParms. 0.GetStatus(&capStat.Start preview. SWP_NOMOVE). } /* -.*/ if (m_theVideoCapWnd.LoadString(IDS_ERR_PREVRATE). return.*/ if (m_theVideoCapWnd. MessageBox(strErr). SWP_NOMOVE | SWP_NOZORDER). GetParentFrame()->SetWindowPos(NULL. 0. return. /* -.LoadString(IDS_ERR_PREVSCALE).Do not abort when left mouse button is clicked. MessageBox(strErr).Do not abort when right mouse button is clicked. } /* -. -. capStat. .*/ capParms. -. /* -.Get current state of capture window.LoadString(IDS_ERR_SETSETUP).uiImageHeight.fAbortLeftMouse = FALSE. -.uiImageWidth. /* -. } /* -. } m_theVideoCapWnd. -.uiImageWidth.fYield = TRUE. MessageBox(strErr). -.PreviewRate(33) == FALSE) { strErr.SetWindowPos(NULL.CaptureSetSetup(&capParms. if (m_theVideoCapWnd.*/ if (m_theVideoCapWnd.Turn on scaling.LoadString(IDS_ERR_GETSTAT). -.Preview(TRUE) == FALSE) { strErr. /* -.LoadString(IDS_ERR_PREV). capStat. capStat.uiImageHeight. MessageBox(strErr). -.*/ if (m_theVideoCapWnd.capParms.fAbortRightMouse = FALSE. 0. MessageBox(strErr).

-. } } void CChildView::OnCaptureFormat() { CString strErr.DriverGetCaps(&capCap.} } void CChildView::OnCaptureSource() { CString strErr.LoadString(IDS_ERR_GETCAPS). } /* -. MessageBox(strErr).".LoadString(IDS_ERR_FORMAT).DlgVideoSource() == FALSE) { strErr.*/ if (capCap.*/ if (capCap. MessageBox(strErr). MessageBox(strErr). sizeof(CAPDRIVERCAPS)) == FALSE) { strErr. } /* -. -. /* -. if (m_theVideoCapWnd. .LoadString(IDS_ERR_GETCAPS). if (m_theVideoCapWnd.*/ CAPDRIVERCAPS capCap.Check if device supports video format dialog. sizeof(CAPDRIVERCAPS)) == FALSE) { strErr.Retrieve device capabilities.Retrieve device capabilities. return. } } else { strErr = "Device does not support video source dialog. /* -. -. -.*/ CAPDRIVERCAPS capCap.DriverGetCaps(&capCap.DlgVideoFormat() == FALSE) { strErr. return. MessageBox(strErr).Check if device supports video source dialog.LoadString(IDS_ERR_SOURCE).fHasDlgVideoFormat) { if (m_theVideoCapWnd.fHasDlgVideoSource) { if (m_theVideoCapWnd.

cx. m_theVideoCapWnd.m_hWnd != NULL) { CRect paRect. GetClientRect(&paRect). int cy) { CWnd::OnSize(nType. MessageBox(strErr). -.LoadString(IDS_ERR_DISPLAY). .". return.LoadString(IDS_ERR_GETCAPS). cy). -.GetClientRect(&cpRect).DriverGetCaps(&capCap.fHasDlgVideoDisplay) { if (m_theVideoCapWnd.".*/ if (capCap. } } void CChildView::OnCaptureDisplay() { CString strErr. if (m_theVideoCapWnd. } } void CChildView::OnSize(UINT nType. } /* -. } } else { strErr = "Device does not support video format dialog. cpRect. } } else { strErr = "Device does not support video display dialog.DlgVideoDisplay() == FALSE) { strErr.Centralize the video capture window. -.*/ if (m_theVideoCapWnd. /* -. MessageBox(strErr). MessageBox(strErr).MessageBox(strErr). int cx. // TODO: Add your message handler code here /* -.Retrieve device capabilities.*/ CAPDRIVERCAPS capCap. MessageBox(strErr). sizeof(CAPDRIVERCAPS)) == FALSE) { strErr.Check if device supports video display dialog.

LoadString(IDS_ERR_GETSTAT).*/ GetParentFrame()->SetWindowPos(NULL. 0. SWP_NOMOVE).Width().uiImageWidth. 0. 200.Height(). paRect. SWP_NOMOVE | SWP_NOZORDER). 0. nWidth. nWidth. 0.uiImageWidth * nZoom. 0. . } else { /* -. 200.GetStatus(&capStat. 0. MessageBox(strErr).ID_CAPTURE_100 + 1. GetParentFrame()).Get current state of capture window. strErr. CAPSTATUS capStat.GetStatus(&capStat. sizeof(CAPSTATUS))) { UINT nWidth = capStat. UINT nHeight = capStat.m_hWnd != NULL) { /* -. } } void CChildView::OnCaptureZoom(UINT nID) { if (m_theVideoCapWnd.*/ CAPSTATUS capStat. nHeight. 0. paRect. SWP_NOMOVE | SWP_NOZORDER).SetWindowPos(NULL. theVideoCapWnd. if (theVideoCapWnd. } } } LRESULT CChildView::FrameCallbackProc(HWND hWnd. -. sizeof(CAPSTATUS))) { UINT nZoom = nID . m_theVideoCapWnd. nHeight. UINT nHeight = capStat.Resize the child window. if (m_theVideoCapWnd.uiImageHeight. GetParentFrame()->SetWindowPos(NULL.m_theVideoCapWnd. } else { CString strErr. UINT nWidth = capStat. pChild->MDIRestore(). CMDIChildWnd *pChild = DYNAMIC_DOWNCAST(CMDIChildWnd.Attach(hWnd).uiImageHeight * nZoom. LPVIDEOHDR lpVideoHdr) { CVideoCapWnd theVideoCapWnd. -.SetWindowPos(NULL. 0. SWP_NOMOVE).

y = pRight. init = true.x = pBottom.*/ if (init) { for (int i=pLeft. do something simple about it. ++j) { index = 3*(i*nWidth+j). .Variables used by simple tracking algorithm.x < j) { pRight.*/ POINT pTop. if (Y > bThreshold) { if (init) { if (pLeft.299*lpData[index+2] + 0. } } } } /* -.y and pBottom. pTop.x = j. j<nWidth. ++i) { for (int j=0. bool init = false.y -index = 3*((pTop. } if (pRight. pLeft. -.x. i<nHeight. ++i) { // -.x > j) { pLeft. int index.y)*nWidth + i). pBottom. } else { pTop.114*lpData[index] + 0. -.y = pLeft.x = j. i<=pRight. Y = floor(0.5).x = pLeft. pLeft. } pBottom.y = i. pBottom.x = pRight. for (int i=0. pRight.y = pBottom.For pTop.x. if (dwRectangle) { BYTE Y. pRight.x = j. /* -.y = i.LPBYTE lpData = lpVideoHdr->lpData. ASSERT(lpVideoHdr->dwBytesUsed == nWidth * nHeight * 3).y = i.y = i.x = j.587*lpData[index+1] + 0. lpData[index] = 0.Data regarding object being tracked stored.

lpData[index+1] = 0. for (int i=0. .y.y)*nWidth + i).x).x)/2. lpData[index+2] = 255. int index. if((pcenter. lpData[index+2] = 255. ++i) { // -.y + pBottom.176)>0) {TurnLeft(). ++j) { index = 3*(i*nWidth+j).} else {TurnRight(). lpData[index+2] = 255. ` } for (int i=pTop.y.*/ QSEG segment.x . /* -. lpData[index+1] = 0. index = 3*((i)*nWidth + pRight. } } /***********************************/ //control tracking object using motorstepper //calculate center object(capture size = 352 X 288(default)) pCenter. lpData[index+1] = 0. std::list<QSEG> object.x). index = 3*((pBottom. for (int j=0. lpData[index] = 0.delay(200).length = 0.x and pRight.For pLeft. i<nHeight. ++i) { segment. lpData[index] = 0.y)/2.x = (pRight.x -index = 3*((i)*nWidth + pLeft. pCenter.y = (pTop.} } else if (dwSegment) { BYTE Y. lpData[index] = 0.Variables used by the new tracking algorithm.delay(200). j<nWidth.x + pLeft.lpData[index+1] = 0. lpData[index+2] = 255. i<=pBottom. -.

if (dlg. .m_blRectangle == BST_CHECKED) { dwRectangle = 1.x + (*i).head. i!=object.end().head. return 0.x = j.begin().y = i. lpData[index] = 255. lpData[index+2] = 255. lpData[index+1] = 0. if (Y > bThreshold) { if (segment. lpData[index+1] = 0.x).length).5).head.head. dwSegment = 0. } void CChildView::OnTrackBrightness() { // TODO: Add your command handler code here CTrackDlg dlg. lpData[index] = 255. lpData[index+2] = 255.*/ for (std::list<QSEG>::iterator i=object. } } } theVideoCapWnd. } ++segment.114*lpData[index] + 0. if (dlg.length) { object.299*lpData[index+2] + 0. segment.y*nWidth + (*i). } } if (segment. ++i) { index = 3*((*i).push_back(segment).587*lpData[index+1] + 0.DoModal()) { bThreshold = atoi(dlg.m_strBrightness). } } /* -.length. index = 3*((*i). -.Detach().y*nWidth + (*i).head.head.length == 0) { segment. do something simple about it.Data regarding object being tracked stored.Y = floor(0.

} void CChildView::OnCaptureStop() { // TODO: Add your command handler code here m_theVideoCapWnd.m_blSegment == BST_CHECKED) { dwRectangle = 0. } } void CChildView::OnTrackStop() { // TODO: Add your command handler code here m_theVideoCapWnd. } . dwSegment = 1.SetCallbackOnFrame((FrameCallback)(NULL)). } else { dwRectangle = 0.} else if (dlg.DriverDisconnect(). } m_theVideoCapWnd. dwSegment = 0.SetCallbackOnFrame(FrameCallbackProc).

1991. 2003. ISBN 0-13-543398-3. 2. Prentice Hall. Ballard and C. Ngô Tiến Thành. 1982. Vernon. D. Brown. previously published by RandD Publications. 4. Khóa Luận Tốt Nghiệp Đại Học Công Nghệ .• Phần Tài liệu tham khảo. 1. Image Processing in C: Analyzing and Enhancing Digital Images. . D. Computer Vision. Machine Vision : Automated Visual Inspection and Robot Vision. previously published by PrenticeHalldaidb. 1994.Xác Định Tọa Độ Của Vật Chuyển Động Qua Cảm Biến Ảnh. 3. D. Phillips.

You're Reading a Free Preview

Download
scribd
/*********** DO NOT ALTER ANYTHING BELOW THIS LINE ! ************/ var s_code=s.t();if(s_code)document.write(s_code)//-->