nV
ăn
Lo
ng
Ứng dụng xử lý ảnh trong thực tế với thư viện OpenCV
Ứng dụng xử lý ảnh trong thực thế với thư
viện OpenCV C/C++
Nguyễn Văn Long
Ng
uy
ễ
[email protected]
Tác giả: Nguyễn Văn Long –
[email protected]
Page 1
Ứng dụng xử lý ảnh trong thực tế với thư viện OpenCV
ng
Mở đầu
Ng
uy
ễ
nV
ăn
Lo
Xử lý ảnh và thị giác máy là lĩnh v ực mà ngày nay được phát triển và ứng dụng rất rộng
rãi trong nhiều lĩnh vực khác nhau nhờ vào sự phát triển ngày càng mạnh mẽ của các hệ
thống máy tính, các thuật toán và công trình nghiên cứu khác nhau của nhiều nhà khoa
học trên thế giới.
Ở Việt Nam, các ứng dụng về xử ảnh đã bư ớc đầu được triển khai trên một số lĩnh vực
như lắp đặt hệ thống nhận dạng biển biển số xe ở các bãi đổ xe, hệ thống nhận dạng vân
tay chấm công ở các công sở … môn học xử lý ảnh ở các trường đại học được xem là
môn học bắt buộc ở một số ngành như công nghệ thông tin, điện tử viễn thông …Tuy
nhiên nhìn một cách khách quan thì số lượng các ứng dụng được triển khai trên thực tế là
quá ít ỏi, lĩnh vực này sẽ còn phát triển mạnh mẽ trong tương lai nếu như được quan tâm
một cách nghiêm túc.
Xuất phát từ thực tế rằng môn học xử lý ảnh ở các trường đại học là một môn học mang
nặng tính học thuật, khô khan, các vấn đề được mô tả dưới dạng toán học, sinh viên nắm
bắt môn học một cách chung chung mà không đi vào bản chất vấn đề, ứng dụng thực tiễn
của môn học, thêm vào đó số lượng tài liệu về chuyên ngành này bằng tiếng Việt là không
nhiều, bằng quá trình nghiên cứu nghiêm túc, kinh nghiệm thực tế tác giả đã cố gắng cho
ra đời cuốn sách Ứng dụng xử lý ảnh trong thưc tế với thư viện OpenCV.
Cuốn đề cập tới một số phần của lĩnh vực xử lý ảnh và thị giác máy, thông qua sự diễn
giải trực quan, không xa vào những công thức toán học trừu tượng, phức tạp nhưng vẫn
làm nổi bật nên được vấn đề, giúp người đọc có được cái nhìn tổng quát, hiểu được khái
niệm và hơn nữa biết được những vấn đề đó ứng dụng vào thực tế như thế nào. Các chủ
đề trong cuôn sách này đều đi kèm với một chương trình mô ph ỏng được viết bằng ngôn
ngữ C++ với sự giúp đỡ của thư viện OpenCV, một thư viện mã nguông mở được đánh
giá là mạnh mẽ về tốc độ xử lý đáp ứng được các ứng dụng trong thời gian thực.
Cuốn sách được chia thành bốn phần, phần đầu giới thiệu về thư viện OpenCV, phần thứ
hai nói về một số vấn đề chọn lọc thường gặp trong xử lý ảnh như không gian màu, các
bộ lọc, cách phát hiện đường thẳng đường tròn trong ảnh …, phần thứ ba nói về một số
thủ thuật để lập trình với thư viện MFC và phần cuối cùng nói về một số ứng dụng thực tế
như bài toán nhận dạng biển số xe …
Cuốn sách không chỉ là tài liệu tham khảo bổ ích trong quá trình học tập của các bạn sinh
viên, quá trình làm luận văn, đồ án … mà còn là công cụ tốt hỗ trợ cho việc triển khai các
ứng dụng thương mại của các kĩ sư, doanh nghi ệp và những người quan tâm tới lĩnh v ực.
Cuối cùng dù đã dành nhiều tâm huyết để hoàn thành cuốn sách nhưng chắc chắn cuốn
sách vẫn còn nhiều sai xót, tác giả mong được sự góp ý của bạn đọc. Xin gửi lời chúc tốt
tốt đẹp và lời cảm ơn sâu sắc tới độc giả
Tác giả: Nguyễn Văn Long –
[email protected]
Page 2
Ứng dụng xử lý ảnh trong thực tế với thư viện OpenCV
ng
Hướng dẫn sử dụng sách
Cuốn sách được viết dựa trên những nghiên cứu và quá trình làm việc thực tế của tác giả,
với mỗi vấn đề nêu trong sách bạn đọc có thể đọc qua để nắm bắt được ý tưởng chính, sau
đó có thể tìm thêm tài liệu để nâng cao hơn vấn đề và có thể thực hành dựa vào mẫu
chương trình, source code đi kèm.
Lo
Thư viện OpenCV được viết trong sách là bản OpenCV 2.4.3, đối với các bản OpenCV
khác thì bạn đọc có thể tùy chỉnh lại một chút tuy nhiên về bản chất của vấn đề là tương
đối giống nhau. Ngôn ngữ lập trình cho các ví dụ là C/C++, IDE sử dụng là Visual Studio
2010. Tuy nhiên đa số chương trình trong cuốn sách này đều được tách biệt phần xử lý
chính ra vào một file *.cpp nào đó nên ta có thể lấy nó để áp dụng vào các trình dịch
khác.
nV
ăn
Có 10 chủ đề chính bao quát một số khía cạnh của lĩnh vực xử lý ảnh được viết khá chi
tiết và giải thích đầy đủ, 3 project được tác giả mô tả chung chung hơn. Do đó bạn đọc
nếu chưa thực sự quen với thư viện OpenCV nên đọc theo thứ tự từ đầu tới cuối
Ng
uy
ễ
Trong cuốn sách có nhiều vấn đề liên quan tới kĩ thuật lập trình nhưng do phạm vi giới
hạn, tác giả chỉ có thể nói qua được một số khía cạnh, trên thực tế có nhiều cách khác
nhau để giải quyết cùng một công việc, với những vấn đề lập trình bạn đọc chưa rõ có thể
tham khảo thêm tài ở các nguồn khác nhau hoặc giải quyết theo hướng mà bạn đọc cảm
thấy là thỏa đáng nhất
Tác giả: Nguyễn Văn Long –
[email protected]
Page 3
Ứng dụng xử lý ảnh trong thực tế với thư viện OpenCV
ng
Mục Lục
1. Giới thiệu về thư viện OpenCV
2. Phiên bản OpenCV 1 hay OpenCV 2
3. Hướng dẫn sử dụng OpenCV trên Window
Chương II. Các phép xử lý đơn giản trong OpenCV
Lo
Chương I. Làm quen với thư viện OpenCV
nV
ăn
1. Chương trình đ ầu tiên
2. Không gian màu, chuyển đổi không gian màu
3. Điều chỉnh độ sang, độ tương phản
4. Ảnh nhị phân, nhị phân hóa với ngưỡng động
5. Histogram, cân bằng histogram
6. Phóng to, thu nhỏ, xoay ảnh
7. Lọc số trong ảnh
8. Các phép toán hình thái học trong ảnh
9. Tìm biên ảnh với bộ lọc Canny
10. Chuyển đổi Hough, Phát hiện đường thẳng, đường tròn trong ảnh
5
5
6
12
13
17
19
23
27
30
37
43
46
Chương III. Lập trình xử lý ảnh với giao diện MFC
Giới thiệu về MFC
Khởi tạo project MFC
Làm việc với các điều khiển (Control)
Chuyển đổi các kiểu dữ liệu trong MFC
Chương trình tải ảnh và hiển thị ảnh lên giao diện MFC
uy
ễ
1.
2.
3.
4.
5.
51
51
54
59
61
Chương IV. Một số ứng dụng trong thực tế
Ng
1. My Photo Editor, phần mềm chỉnh sửa ảnh đơn giản
2. Nhận dạng biển số xe
3. MyCam, một số hiệu ứng ảnh trong video
Tác giả: Nguyễn Văn Long –
[email protected]
64
73
90
Page 4
Ứng dụng xử lý ảnh trong thực tế với thư viện OpenCV
Chương I. Làm quen với thư viện OpenCV
ng
1. Giới thiệu về thư viện OpenCV
Lo
OpenCV (Open Source Computer Vision) là một thư viện mã nguồn mở về thị giác máy
với hơn 500 hàm và hơn 2500 các thuật toán đã đư ợc tối ưu về xử lý ảnh, và các vấn đề
liên quan tới thị giác máy. OpenCV được thiết kế một cách tối ưu, sử dụng tối đa sức
mạnh của các dòng chip đa lõi… đ ể thực hiện các phép tính toán trong thời gian thực,
nghĩa là tốc độ đáp ứng của nó có thể đủ nhanh cho các ứng dụng thông thường. OpenCV
là thư viện được thiết kế để chạy trên nhiều nền tảng khác nhau (cross-patform), nghĩa là
nó có thể chạy trên hệ điều hành Window, Linux, Mac, iOS … Việc sử dụng thư viện
OpenCV tuân theo các quy định về sử dụng phần mềm mã nguồn mở BSD do đó bạn có
thể sử dụng thư viện này một cách miễn phí cho cả mục đích phi thương mại lẫn thương
mại.
nV
ăn
Dự án về OpenCV được khởi động từ những năm 1999, đến năm 2000 nó được giới thiệu
trong một hội nghị của IEEE về các vấn đề trong thị giác máy và nhận dạng, tuy nhiên
bản OpenCV 1.0 mãi tới tận năm 2006 mới chính thức được công bố và năm 2008 bản 1.1
(pre-release) mới được ra đời. Tháng 10 năm 2009, bản OpenCV thế hệ thứ hai ra đời
(thường gọi là phiên bản 2.x), phiên bản này có giao diện của C++ (khác với phiên bản
trước có giao diện của C) và có khá nhiều điểm khác biệt so với phiện bản thứ nhất.
Thư viện OpenCV ban đầu được sự hỗ trợ từ Intel, sau đó được hỗ trợ bở Willow Garage,
một phòng thí nghiệm chuyên nghiên cứu về công nghệ robot. Cho đến nay, OpenCV vẫn
là thư viện mở, được phát triển bởi nguồn quỹ không lợi nhuận (none -profit foundation)
và được sự hưởng ứng rất lớn của cộng đồng.
2. Phiên bản OpenCV 1 hay OpenCV 2?
uy
ễ
Cho tới nay, trải qua hơn 6 năm từ lúc phiên bản OpenCV đầu tiên được công bố, đã có
lần lượt nhiều phiên bản OpenCV ra đời, tuy nhiên có thể chia thư viện này thành hai bản
chính dựa trên những đặc điểm khác biệt lớn nhất của chúng: phiên bản OpenCV thế hệ
thứ nhất (hay còn gọi là phiên bản OpenCV 1.x) và phiên bản OpenCV thứ hai (hay còn
gọi là phiên bản OpenCV 2.x). Sau đây ta sẽ chỉ ra một số điểm khác biệt cơ bản giữa hai
phiên bản này.
OpenCV 1.x (bao gồm bản 1.0 và bản pre-release 1.1) dựa trên giao diện C, cấu
trúc của một ảnh số dựa trên cấu trúc của IplImage, trong khi thư OpenCV 2.x dựa
trên giao diện C++, cấu trúc của ảnh số, ma trận dựa trên cấu trúc của cv::Mat.
Trong OpenCV 1.x, người sử dụng phải hoàn toàn quản lý bộ nhớ của các đối
tượng, nghĩa là khi m ột đối tượng mới được tạo ra, ta phải luôn chú ý để giải
phóng nó khi không còn sử dụng nữa (trong nhiều trường hợp có thể sẽ bị tràn bộ
nhớ nếu không chú ý đều này), trong khi thư viện OpenCV 2.x việc quản lý bộ nhớ
trở nên dễ dàng hơn nhờ các hàm hủy các các lớp đối tượng trong OpenCV 2.x đã
thực hiện điều này khi một đối tượng không còn được sử dụng nữa.
Ng
-
-
Tác giả: Nguyễn Văn Long –
[email protected]
Page 5
Việc viết các dòng lệnh để thực hiện cùng một chức năng trong OpenCV 2.x là dễ
dàng hơn nhiều so với OpenCV 1.x, một phần là là giao diện C++ có phần dễ hiểu
hơn so với C, một phần là các hàm trong OpenCV 2.x đã được tối ưu hóa nhiều
bước trung gian không cần thiết về mặt giao diện người sử dụng. Chẳng hạn ta hãy
xét ví dụ về việc phát hiện đường tròn trong ảnh mầu dựa vào thuật toán Hough,
các bước để thực hiện là load một ảnh mầu, chuyển sang ảnh nhị phân, tìm biên
dựa trên bộ lọc canny và phát hiện đường tròn dựa trên thuật toán Hough. OpenCV
1.x thực hiện như sau:
Lo
ng
-
Ứng dụng xử lý ảnh trong thực tế với thư viện OpenCV
nV
ăn
// Phát hiện đường tròn trong ảnh OpenCV 1.x
IplImage*
src = cvLoadImage(“image.jpg”);
IplImage* gray = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 1);
cvCvtColor(src, gray, CV_BGR2GRAY);
cvCanny(gray, gray, 10, 30, 3);
CvMemStorage* storage = cvCreateMemStorage(0);
CvSeq* circles = cvHoughCircles(gray, storage, CV_HOUGH_GRADIENT, 1,
50, 100, 50);
Trong khi đó, OpenCV 2.x thực hiện như sau:
// Phát hiện đường tròn trong ảnh OpenCV 1.x
Mat src = imread(“image.jpg”);
Mat gray;
CvtColor(src, gray, CV_BGR2GRAY);
Canny(gray, gray, 10, 30, 3);
Vector
circles;
HoughCircles(gray, circles, CV_HOUGH_GRADIENT, 1, 50, 100, 50);
uy
ễ
Ta thấy rằng đối tượng ảnh gray trong OpenCV 2.x không cần phải khởi tạo, đối
tượng storage (đối tượng trung gian, không có ý nghĩa v ề mặt sử dụng) cũng
không cần phải khởi tạo (và do đó không cần giải phóng).
-
Thư viện OpenCV 1.x tuy chứa một lượng lớn hàm xử lý và thuật toán, tuy nhiên
nó vẫn ở dạng sơ khai. Thư viện OpenCV 2.x đã đư ợc bổ xung khá nhiều hàm,
thuật toán và được tối ưu khá nhiều đặc biệt trong các khía cạnh về phát hiện đối
tượng (detection), nhận dạng đối tượng (partten regconition) và theo dỗi đối tượng
(tracking). Hơn thế nữa, tuy có giao diện là C++ nhưng OpenCV 2.x vẫn dữ một
phần giao diện C để tương thích với các phiên bản của OpenCV 1.x …
Ng
Từ một số đặc điểm trên ta có thể thấy rằng thư viện OpenCV phiên bản 2.x là có nhiều
điểm nổi trội hơn so với phiên bản 1.x, Tuy nhiên trong một số trường hợp như ở các hệ
thống nhúng khi mà trình dịch chỉ đơn thuần chấp nhận ngôn ngữ C thì phiển bản 1.x vẫn
còn giá trị. Trong cuốn sách này, các nội dung cài đặt, thuật toán, ứng dụng … chỉ dành
cho OpenCV phiên bản 2.x trên nền tảng hệ điều hành Window.
3. Hướng dẫn sử dụng thư viện OpenCV trên Window
Tác giả: Nguyễn Văn Long – [email protected]
Page 6
Ứng dụng xử lý ảnh trong thực tế với thư viện OpenCV
Trên Microsoft Visual Studio
Lo
ng
Trước hết ta cần download thư viện OpenCV về máy tính, tốt hơn là luôn download bản
mới nhất tại địa chỉ http://sourceforge.net/projects/opencvlibrary/ . Chọn bản đã build sẵn
phù hợp với hệ điều hành đang dùng, bản OpenCV được sử dụng trong cuốn sách này là
bản 2.4.3 với lần update cuối cùng là vào ngày 25 tháng 12 năm 2012. Sau khi download
về máy, tiến hành cài đặt bình thường, ta để mặc định thư mục cài đặt là C:\ thư mục cài
đặt xong sẽ có dạng C:\opencv. Tiếp theo ta sẽ tiến hành tùy chỉnh để có thể làm việc với
OpenCV qua hai IDE thông dụng là Microsoft Visual Studio và Eclipse CDT
uy
ễ
nV
ăn
Phiên bản Visual studio sử dụng ở đây là phiên bản Visual Studio 2010, các phiên bản
trước ta hoàn toàn có thể cấu hình một cách tương tự.
Tạo một project mới: New > Project, trong cửa sổ New Project chọn Visual C++, Win32
console application. Đặt tên project là opencv
Ng
Chọn OK, sau đó nhấn Next, hộp thoại tiếp theo xuất hiện, ở hộp thoại này ta chọn
Application type là Console application và Additional option là Empty project, nhấn
Finish để kết thúc quá trình khởi tạo
Tác giả: Nguyễn Văn Long – [email protected]
Page 7
nV
ăn
Lo
ng
Ứng dụng xử lý ảnh trong thực tế với thư viện OpenCV
uy
ễ
Project mới được tạo ra là project hoàn toàn trống, ta phải thêm vào đó ít nhất một file
nguồn để chương trình có th ể chạy
được, trong Solution Explorer ta
click chuột phải vào Source Files,
chọn Add -> New Item… Hộp thoại
Add New Item hiện ra, ta chọn kiểu
cần thêm vào là C++ File(.cpp) đồng
thời trong ô Name ta đặt tên cho file
thêm vào, giả sử là FirstApp.cpp.
Bây giở trong file này ta có thể thêm
vào các #include và gọi hàm main()
để chạy chương trình.
Để chương trình có thể chạy được
với thư viện OpenCV ta cần tùy chỉnh lại một sô thuộc tính của project như sau
Ng
Vào Project -> Properties (hoặc nhấn tổ hợp phím Alt + F7) để mở hộp thoại Properties.
Hộp thoại opencv Property Pages hiện ra, trong mục Configuration Properties chọn
VC++ Directories, tương ứng bên phải, ta tìm mục Include Directories và Library
Directories. Ta sẽ chỉ đường dẫn hai thư mục này đến các phần tương ứng của thư viện
OpenCV.
Mục Include Directories, ta tùy chỉnh ở ô bên phải tới C:\opencv\build\include
Mục Library Directories trỏ đến thư mục C:\opencv\build\x86\vc10\lib nếu như ta sử
dụng hệ điều hành 32bit hoặc C:\opencv\build\x64\vc10\lib cho hệ điều hành 64bit.
Tác giả: Nguyễn Văn Long – [email protected]
Page 8
Ứng dụng xử lý ảnh trong thực tế với thư viện OpenCV
ng
Tiếp theo, trong hộp thoại opencv Property Pages -> Configuration Properties -> Linker
chọn Input, tương ứng ở ô bên phải, thêm vào các giá trị cho mục Additional
Dependencies là opencv_core243d.lib, opencv_imgproc243d.lib, opencv_highgui243d.lib.
nV
ăn
Lo
Chú
ý
là
các lib thêm vào sẽ tương ứng với các
header ta khai báo trong chương trình, và
tùy thuộc vào mục đích sử dụng mà ta có
thể thêm vào các lib các nhau, giả sử ta cần
sử dụng tới các hàm về video, khi đó ta
thêm
header
#include
thì trong phần
Additional Dependencies ta phải khai báo
thêm opencv_video243d.lib. Chữ d đứng
cuối các file trên thể hiện ta đang hoạt
động ở chế độ debug, ta có thể thêm các lib
không có chữ “d” ở cuối như
opencv_core243.lib … trong chế độ
release. Tuy nhiên khi đang còn h ọc tập và cần nhiều chỉnh sửa ta nên để ở chế độ debug.
Cuối cùng, khi dịch xong một chương trình, để nó có thể chạy được ta cần chú ý tới các
file *.dll. Cách đơn giản nhất là ta copy các file *.dll tương ứng (như
opencv_core243d.dll, opencv_imgproc243d.dll) vào thư mục chứa file chạy của chương
trình (file *.exe). Các file *.dll này nằm trong mục C:\opencv\build\x86\bin với win 32 bit
hoặc C:\opencv\build\x64\bin với win 64 bit. Với các phiên bản OpenCV cũ hơn, ta cần
copy luôn file tbb_debug.dll (trong chế độ debug) hoặc tbb.dll (trong chế độ release) vào
thư mục chứa file *.exe. tbb.dll (Thread building block) là file khá quan trọng, thiếu nó
chương trình sẽ báo lỗi.
uy
ễ
Sau khi đã hoàn tất việc chỉ dẫn thư mục chứa header, library và link tới các library tương
ứng, ta có thể include các header của opencv vào chương trình và có thể gọi các hàm làm
việc của OpenCV.
#include
#include
#include
#include
Ng
using namespace std;
using namespace cv;
void main()
{
...
}
Tác giả: Nguyễn Văn Long – [email protected]
Page 9
Ứng dụng xử lý ảnh trong thực tế với thư viện OpenCV
Với Eclipse CDT
Ng
uy
ễ
nV
ăn
Lo
ng
Khởi động Eclipse, Từ cửa sổ Eclipse chọn New -> C++ Project , hộp thoại C++ Project
xuất hiện, trong hộp thoại ta chọn Project name là opencv, Project type là Hello World
C++ Project (Có thể chọn là Empty
Project), Toolchains là MinGW GCC,
Chọn Finish và ta có một Project mới.
Bây giờ tùy chỉnh cho project này hoạt
động
được
với
OpenCV.
Trong cửa sổ của Eclipse chọn Project >Properties, cửa sổ Properties hiện ra.
Tron cửa sổ Properties chọn C/C++
Build->Settings. Trong tab Tool Settings.
Ở phần GCC C++ Compiller chọn
Include rồi dẫn đường dẫn tới mục
Include
của
OpenCV
là C:\opencv\build\include. Trong phần
MinGW C++ Linker chọn Library và
chọn các mục như sau: click vào dấu
cộng ở Library search path (-L) và dẫn
tới
thư
mục
lib: C:\opencv\build\x86\mingw\lib đối
với
Windows
32
bit
hoặc
C:\opencv\build\x64\mingw\lib đối với
Windows 64 bit. Tiếp đó click vào dấu "cộng" để thêm Library(-I) vào, các library cần
thêm lần lượt là: opencv_core243, opencv_highgui243, opencv_imgproc243 ... nói chung
là tùy vào nhu cầu sử dụng có thể thêm một hoặc nhiều lib vào.
Tác giả: Nguyễn Văn Long – [email protected]
Page 10
nV
ăn
Lo
ng
Ứng dụng xử lý ảnh trong thực tế với thư viện OpenCV
Ng
uy
ễ
Ta cũng cần phải copy các *.dll tương ứng vào thư mục chứa file chạy *.execủa chương
trình để chương trình có thể chạy thành công.
Tác giả: Nguyễn Văn Long – [email protected]
Page 11
Ứng dụng xử lý ảnh trong thực tế với thư viện OpenCV
ng
Chương II. Các phép xử lý ảnh và ứng dụng cơ bản
1. Chương trình đ ầu tiên
#include
#include
#include
#include
"stdafx.h"
using namespace std;
using namespace cv;
Lo
Trong bài này ta sẽ tìm hiểu một ví dụ đầu tiên như một chương trình Hello world để load
và hiển thị một ảnh. Chương trình như sau:
nV
ăn
int main()
{
cout<<"Chuong trinh dau tien"<
uy
ễ
#include
#include
#include
#include
using namespace cv;
Ng
void main()
{
Mat src = imread("LucBinh.jpg", CV_LOAD_IMAGE_COLOR);
Mat gray, hsv, ycrcb;
cvtColor(src, gray, CV_BGR2GRAY);
cvtColor(src, hsv, CV_BGR2HSV);
cvtColor(src, ycrcb, CV_BGR2YCrCb);
imshow("src", src);
imshow("gray", gray);
imshow("hsv", hsv);
imshow("ycrcb", ycrcb);
waitKey(0);
Tác giả: Nguyễn Văn Long – [email protected]
Page 16
uy
ễ
nV
ăn
Lo
Sau đây là hình ảnh khi chuyển đổi các không gian màu trên
ng
}
Ứng dụng xử lý ảnh trong thực tế với thư viện OpenCV
3. Điều chỉnh độ sang và độ tương phản trong ảnh
Ng
Trong bài này ta sẽ tìm hiểu về cấu trúc của một bức ảnh, cách tiếp cận và điều chỉnh tới
từng điểm ảnh.
Một ảnh số được lưu trữ trên máy tính là một ma trận các điểm ảnh (hay pixel). Trong
OpenCV nó được biểu diễn dưới dạng cv::Mat. Ta xét một kiểu ảnh thông thường nhất,
đó là ảnh RGB. Với ảnh này, mỗi pixel ảnh quan sát được là sự kết hợp của các thành
phần màu R (Red), Green (Green) và Blue (Blue). Sự kết hợp này theo những tỉ lệ R, G,
B khác nhau sẽ tạo ra vô số các màu sắc khác nhau. Giả sử ảnh được mã hóa bằng 8 bit
với từng kênh màu, khi đó mỗi giá trị của R, G, B sẽ nằm trong khoảng [0, 255]. Như vậy
ta có thể biểu diễn tới 255*255*255 ~ 1.6 triệu màu sắc từ ba màu cơ bản trên. Ta có thể
xem cách biểu diễn ảnh trong OpenCV ở định dạng cv::Mat qua hình ảnh sau:
Tác giả: Nguyễn Văn Long – [email protected]
Page 17
Ứng dụng xử lý ảnh trong thực tế với thư viện OpenCV
0, 0
1, 0
2, 0
n, 0
0, 0
1, 0
2, 0
n, 0
0, 0
1, 0
2, 0
n, 0
0, 1
1, 1
2, 1
N, 1
0, 1
1, 1
2, 1
n, 1
Cột m
0, 1
1, 1
2, 1
n, 1
0, m
1, m
2, m
n, m
0, m
1, m
2, m
n, m
0, m
1, m
2, m
n, m
Lo
Hàng 0
Hàng 1
Hàng 2
Hàng n
Cột 1
ng
Cột 0
"stdafx.h"
uy
ễ
#include
#include
#include
#include
nV
ăn
Như vậy, mỗi ảnh sẽ có n hàng và m cột, m gọi là chiều dài của ảnh (width) và n gọi là
chiều cao của ảnh (heigh). Mỗi pixel ở vị trí (i,j) trong ảnh sẽ tương ứng với 3 kênh màu
kết hợp trong nó. Để truy xuất tới từng pixel ảnh với những kênh màu riêng rẽ ta sử dụng
mẫu sau:
img.at(i,j)[k]
Trong đó, i ,j là pixel ở hàng thứ i và cột thứ j, img là ảnh mà ta cần truy xuất tới các pixel
của nó. cv::Vec3b là kiểu vector uchar 3 thành phần, dung để biểu thị 3 kênh màu tương
ứng. k là kênh màu thứ k, k = 0, 1, 2 tương ứng với kênh màu B, G, R. Chú ý là trong
OpenCV, hệ màu RGB được biểu diễn theo thứ tự chữ cái là BGR.
Sau đây ta sẽ áp dụng kiến thức trên để làm tăng, giảm độ sang và tương phản của một
ảnh màu, việc làm này cũng hoàn toàn tương t ự đối với ảnh xám, chỉ khác biệt là ảnh ta
dung một kênh duy nhất để biểu diễn ảnh xám.
Chương trình tăng, gi ảm độ sáng và độ tương phản của một ảnh
Giả sử f là một hàm biểu diễn cho một ảnh nào đó, f(x,y) là giá trị của pixel trong ảnh ở vị
trí (x,y). Đặt g(x,y) = αf(x,y) + β. Khi đó, nếu α ≠ 1, thì ta nói ảnh g(x,y) có độ tương phản
gấp α lần so với ảnh f(x,y). Nếu β ≠ 0ta nói độ sáng của ảnh g(x,y) đã thay đ ổi một lượng
là β. Dựa vào công thức trên ta có chương trình thay đ ổi độ sáng và tương phản của ảnh
như sau:
using namespace std;
using namespace cv;
Ng
int main()
{
cout<<"Chuong trinh dieu chinh do sang va tuong phan"<(i,j)[k] = saturate_cast(
alpha*(src.at(i,j)[k] ) + beta);
imshow("anh goc", src);
imshow("anh co sau khi chinh do tuong phan va do sang", dst);
waitKey(0);
return 0;
uy
ễ
nV
ăn
Lo
Trong chương trình trên, hàm clone() sẽ sao chép một ảnh giống hệt như ảnd gốc cho vào
ảnh đích (dst = src.clone()). Giá trị của các pixel ảnh f(x,y) và g(x,y) ở đây phải nằm trong
khoảng [0, 255], trong khi phép biến đổi g(x,y) = αf(x,y) + β có thể khiến cho giá trị của
g(x,y) vượt qua ngưỡng đó. Để tránh tình trạng tràn số hoặc kiểu dữ liệu không tương
thích, ta dùng thêm hàm saturate_cast(type). Hàm này sẽ biến kiểu dữ liệu
type nếu không phải là uchar thành kiểu dữ liệu uchar
Sau đây là kết quả chương trình với giá trị α = 2.0 và β = 30
4. Ảnh nhị phân, nhị phân hóa với ngưỡng động
Ng
Ảnh nhị phân là ảnh mà giá trị của các điểm ảnh chỉ được biểu diễn bằng hai giá trị 0
hoặc 255 tương ứng với hai màu đen hoặc trắng. Nhị phân hóa một ảnh là quá trình biến
một ảnh xám thành ảnh nhị phân. Gọi f(x,y) là giá trị cường độ sáng của một điểm ảnh ở
vị trí (x,y), T là ngưỡng nhị nhị phân. Khi đó, ảnh xám f sẽ được chuyển thành ảnh nhị
phân dựa vào công thức f(x,y) = 0 nếu f(x,y) ≤ T và f(x,y) = 255 nếu f(x,y) > T
Hình sau mô tả một ảnh nhị phân với ngưỡng nhị phân T = 100
Tác giả: Nguyễn Văn Long – [email protected]
Page 19
Lo
ng
Ứng dụng xử lý ảnh trong thực tế với thư viện OpenCV
Ảnh xám
Ảnh nhị phân
uy
ễ
nV
ăn
Hàm để chuyển nhị phân hóa ảnh trong OpenCV là hàm threshold(). Nguyên mẫu hàm
như sau:
threshold(cv::InputArray src, cv::OutputArray dst, double thresh, int maxval, int type)
Trong đó, src là ảnh đầu vào một kênh màu (ảnh xám …), dst là ảnh sau khi được nhị
phân hóa, thresh là ngưỡng nhị phân, maxval là giá trị lớn nhất trong ảnh (maxval = 255
đối với ảnh xám), type là kiểu nhị phân có thể là CV_THRESH_BINARY,
CV_THRESH_BINARY_INV, CV_THRESH_OTSU… lần lượt là nhị phân hóa thông
thường, nhị phân hóa ngược và nhị phân hóa theo thuật toán Otsu …
Kết quả của việc nhị phân hóa một ảnh phụ thuộc vào ngưỡng T, có nghĩa là v ới mỗi
ngưỡng T khác nhau thì ta có những ảnh nhị phân khác nhau. Hình sau mô tả 3 ảnh nhị
phân tương ứng với ngưỡng T = 50, T = 100 và T = 150.
Ng
T = 50
T = 100
T = 150
Để thu được một ảnh nhị phân tốt mà không cần phải quan tâm tới các điều kiện ánh sáng
khác nhau (không cần quan tâm tới ngưỡng T), người ta dùng một kĩ thuật sao cho với
mọi ngưỡng xám khác nhau ta luôn thu được một ảnh nhi phân tốt. Kĩ thuật đó gọi là kĩ
Tác giả: Nguyễn Văn Long – [email protected]
Page 20