Professional Documents
Culture Documents
X Lý NH V I OpenCV - Hinh Thai PDF
X Lý NH V I OpenCV - Hinh Thai PDF
Giới thiệu
OpenCV (Open Computer Vision) là một thư viện mã nguồn mở chuyên dùng để xử lý các vấn đề liên
quan đến thị giác máy tính. Nhờ một hệ thống các giải thuật chuyên biệt, tối ưu cho việc xử lý thị giác
máy tính, vì vậy tính ứng dụng của OpenCV là rất lớn.
Xử lý ảnh là quá trình xử lý, thao tác hình ảnh để có một hình ảnh khác phù hợp với nhu cầu của người
dùng,...
Hình thái học toán học đã được phát triển cho hình ảnh nhị phân, và sau đó được mở rộng cho ảnh đa mức
xám (Image Grayscale),... Đây là một trong những kỹ thuật được áp dụng trong giai đoạn tiền xử lý. Hai
phép toán thường dùng là phép giãn nở (Dilation) và phép co (Erosion) . Từ hai phép toán cơ bản này
người ta phát triển thành một số phép toán như phép đóng (Closing) và phép mở (Opening).
Bạn có thể tìm hiểu nội dung ảnh nhị phân và ảnh xám cụ thể hơn trong bài viết Kỹ Thuật Grayscale Và
Nhị Phân Hoá Ảnh (Adaptive Threshold) :: www.stdio.vn/articles/read/383/ky-thuat-grayscale-va-nhi-
phan-hoa-anh-adaptive-threshold.
Trong các phép toán hình thái học, một phần tử cấu trúc có kích thước (NxN) được di chuyển khắp ảnh và
thực hiện phép tính toán với từng điểm ảnh (Pixel) của ảnh với (N2 -1) điểm ảnh (Pixel) lân cận (Không
tính điểm ở tâm). Phép tính toán ở đây tùy thuộc vào nội dung của phép toán hình thái học mà từ đó cho
ra một kết quả phù hợp:
Nếu gốc của phần tử cấu trúc (Ogirin) nằm ở phía bên trái thì ảnh sẽ có xu hướng co và giãn
nở về phía bên phải.
Nếu gốc của phần tử cấu trúc (Ogirin) nằm ở phía bên phải thì ảnh sẽ có xu hướng co và giãn về
nở phía bên trái.
Vì vậy: Trong các kết quả của phép toán xử lý hình thái học thì yếu tố quan trọng là phần tử cấu trúc.
Chú ý: Những nội dung kiến thức trên đây là phần tử cấu trúc dùng trong các phép toán hình thái học trên
ảnh nhị phân. Với ảnh đa mức xám thì phần tử cấu trúc tương tự nhưng khác ở chỗ là các giá trị phần tử
từ 0 đến 255 chứ không phải là chỉ 0 với 1 như phần tử cấu trúc trên ảnh nhị phân.
Công thức
Trong đó:
Phép giãn nở (Dilation) ảnh sẽ cho ra một tập điểm ảnh c thuộc D(i), bạn hoàn toàn dễ dàng thấy rằng đây
là một phép tổng giữa A và B.
A sẽ là tập con của D(i) . Chú ý: Nhận xét này không toàn toàn đúng với trường hợp phần tử cấu trúc B
không có gốc (Origin) hay nói cách khác là gốc (Origin) mang giá trị 0.
Ví dụ
Tôi có ma trận điểm ảnh Isrc, ma trận điểm ảnh sau phép giãn nở Idst và phần tử cấu trúc B.
Ứng với công thức ở trên, ta lần lượt đặt phần tử cấu trúc vào các điểm ảnh có giá trị 1 của ma
trận điểm ảnh Isrc. Kết quả thu được là ma trận điểm ảnh Idst.
Tính toán
Tôi có ở ma trận điểm ảnh Isrc = {(1, 2), (2,1), (2, 2), (2, 3), (2, 4), (2, 5), (3, 2), (3, 3), (3, 4), (3,
5),
(4, 2), (4, 4), (5, 1), (5, 2), (5, 3), (5, 4), (5, 5)}.
Tôi có ở ma trận phần tử cấu trúc B = {(0,0), (-1, 0), (0, 1)} với (0,0) là điểm gốc.
Áp dụng công thức phép giãn nở tôi có:
Isrc(0,0) = {(1, 2), (2,1), (2, 2), (2, 3), (2, 4), (2, 5), (3, 2), (3, 3), (3, 4), (3, 5), (4, 2), (4, 4), (5, 1),
(5, 2), (5, 3), (5, 4), (5, 5)}.
Isrc(-1,0) = {(0, 2), (1,1), (1, 2), (1, 3), (1, 4), (1, 5), (2, 2), (2, 3), (2, 4), (2, 5), (3, 2), (3, 4), (4, 1),
(4, 2), (4, 3), (4, 4), (4, 5)}.
Isrc(0, 1) = {(1, 3), (2,2), (2, 3), (2, 4), (2, 5), (2, 6), (3, 3), (3, 4), (3, 5), (3, 6), (4, 3), (4, 5), (5, 3),
(5, 3), (5, 4), (5, 5), (5, 6)}
Phép giãn nở của Isrc bởi B là hợp của Isrc(0,0), Isrc(-1,0) và Isrc(0,1) hay là Idst.
Với phần tử cấu trúc không có điểm gốc (Origin), cách tính toán cũng tương tự.
Công thức
Trong đó
Ví dụ
Tính toán
1. Tại ô vuông khoanh tròn tôi có 3 giá trị Isrc(2,2) = 10, Isrc(3,2) = 50 và Isrc(3,3) = 70.
2. Áp dụng công thức cho từng giá trị được liệt kê ở bước 1.
Isrc(2,2) = Isrc(1,2) = Isrc(3,2) = Isrc(1,2) = Isrc(3,2) = 10 + 10 = 20.
Isrc(3,2) = Isrc(3,1) = Isrc(3,3) = Isrc(2,2) = Isrc(4,2) = 50 + 10 = 60.
Isrc(3,3) = Isrc(3,4) = Isrc(3,2) = Isrc(2,3) = Isrc(4,3) = 70 + 10 = 80.
3. Bạn có thể dễ dàng thấy rằng có một số điểm ảnh Isrc trong tính toán ở trên có giá trị khác nhau.
Với các điểm ảnh đó, lúc này tôi chỉ việc lấy giá trị lớn nhất (Max) mà tôi có được.
Isrc(2,2) = 60, Isrc(2,3) = 80, Isrc(3,2) = 80, Isrc(3,3) = 80.
4. Tương tự với các điểm ảnh còn lại, tôi tính toán ra được kết quả giãn nở của ảnh đa mức xám
Isrc thành Idst như sau:
Công thức
Trong đó:
Phép co ảnh sẽ cho ra một tập điểm ảnh c thuộc A, nếu bạn đi chuyển phần tử cấu trúc B theo c, thì B
nằm trong đối tượng A.
E(i) là một tập con của tập ảnh bị co A. Chú ý: Nhận xét này không toàn toàn đúng với trường hợp phần
tử cấu trúc B không có gốc (Origin) hay nói cách khác là gốc (Origin) mang giá trị 0.
Ví dụ
Tôi có ma trận điểm ảnh Isrc, ma trận điểm ảnh sau phép co Idst và cấu trúc phần tử B.
Ứng với công thức ở trên, ta lần lượt đặt phần tử cấu trúc vào các điểm ảnh có giá trị 1 của ma
trận điểm ảnh Isrc. Kết quả thu được là ma trận điểm ảnh Idst.
Tính toán
Tôi có ở ma trận điểm ảnh Isrc = {(1, 2), (2,1), (2, 2), (2, 3), (2, 4), (2, 5), (3, 2), (3, 3), (3, 4), (3,
5),
(4, 2), (4, 4), (5, 1), (5, 2), (5, 3), (5, 4), (5, 5)}.
Tôi có ở ma trận phần tử cấu trúc B = {(0,0), (-1, 0), (0, 1)} với (0,0) là điểm gốc.
Ở đây, tôi không quan tâm tới toàn bộ các điểm đen (Mang giá trị 1) ở Isrc, tôi chỉ quan tâm tới
đến những tọa độ của các điểm đen (Mang giá trị 1) của Isrc khi mà tôi di chuyển phần tử cấu trúc
trên đối tượng ảnh Isrc thì gốc của B trùng với một điểm ảnh và các điểm lân cận mang giá trị
1 của phần tử cấu trúc B trùng với điểm đen (Mang giá trị 1) của Isrc theo phần tử cấu trúc B. Ví
dụ ở đây tôi có 6 điểm đen (Mang giá trị 1) trên Isrc phù hợp với điều kiện trên:
Isrc(2, 2), Isrc(3, 2), Isrc(3, 3), Isrc(3, 4), Isrc(5, 2), Isrc(2, 4).
Isrc(2,1) = Isrc(2,2) = 1 & Isrc(1,1) = 0. Vậy nên Isrc(2,1) không thỏa với cấu trúc phần tử. Nên
Isrc(2,1) = 0.
Isrc(2,2) = Isrc(1,2) = Isrc(2,3) = 1. Vậy nên Isrc(2,2) thỏa với cấu trúc phần tử B. Nên Isrc(3,3) = 1.
Với phần tử cấu trúc không có điểm gốc (Origin), cách tính toán cũng tương tự.
Công thức
Trong đó:
Ví dụ
Các điểm ảnh có trong ô Isrc (3,1) = 90, Isrc (4,2) = 50, Isrc (5,2) = 60, Isrc (5,3) = 70, Isrc (6,2) =
5, Isrc(5,1) = 10.
Trừ(-) các giá trị ở trên cho 10 (Giá trị phần tử trong phần tử cấu trúc).
Loại bỏ những điểm ảnh không tương ứng với hình dạng của phần tử cấu trúc. Ở đây giá
trị Isrc (3,1) = 0.
Các giá trị còn lại vì tương ứng với hình dạng của phần tử cấu trúc (Hình chữ thập) nên tôi giữa
lại. Và lúc này điểm ảnh trung tâm chính là Isrc (4,2) = 50 tương ứng với gốc của phần tử cấu trúc
(Origin).
Với những giá trị còn lại sau khi tôi loại bỏ những điểm ảnh không phù hợp. Theo công thức thì
tôi cần phải thay điểm ảnh bằng giá trị nhỏ nhất trong tập điểm ảnh đang xét và các điểm lân cận.
Ở đây giá trị nhỏ nhất là Isrc (6,2) = -5. Vì vậy, điểm ảnh tại Isrc (4,2) = 0. Cứ như vậy trên toàn ma
trận tôi có kết quả của việc co ảnh Isrc chính là Idst.
Phép toán mở (Opening) và phép toán đóng (Closing)
Phép toán mở (Opening) và phép toán đóng (Closing) là sự kết hợp của phép co (Erosion) và phép
giãn nở (Dilation) như trên. Ta được định nghĩa như sau.
Thực hiện phép co (Erosion) trước sau đó mới thực hiện phép giãn nở (Dilation).
Công thức
Ứng dụng
Phép toán mở (Opening) được ứng dụng trong việc loại bỏ các phần lồi lõm và làm cho đường bao các
đối tượng trong ảnh trở nên mượt mà hơn.
Thực hiện phép giãn nở (Dilation) trước sau đó mới thực hiện phép co (Erosion).
Công thức
Ứng dụng
Phép toán đóng (Closing) được dùng trong ứng dụng làm trơn đường bao các đối tượng, lấp đầy các
khoảng trống biên và loại bỏ những hố nhỏ.
Phân tích
Hàm getStructuringElement():
Phân tích
shape: Là hình dạng của phần tử cấu trúc. Ví dụ: MORPH_RECT. Bạn có thể tham khảo các loại
hình dạng của phần tử cấu trúc trong cv::MorphShapes.
ksize: Là kích thước của ma tận phần tử cấu trúc.
anchor: Là điểm neo của phần tử cấu trúc. Giá trị mặc định là (-1, -1).
Ví dụ
1. #include "opencv2/core/core.hpp"
2. #include "opencv2/highgui/highgui.hpp"
3. #include "opencv2/imgproc/imgproc.hpp"
4.
5. using namespace cv;
6.
7. int main() {
8.
9. Mat imageSrc = imread("stdio.png", CV_LOAD_IMAGE_GRAYSCALE);
10. Mat imageDst;
11. Mat imageBinary;
12.
13. threshold(imageSrc, imageBinary, 220, 255, CV_THRESH_BINARY);
14. cv::Mat kernel = cv::getStructuringElement(MORPH_CROSS, Size(5,5))
;
15. cv::morphologyEx(imageBinary, imageDst, MORPH_ERODE, kernel);
16.
17. imshow("imageBinary", imageBinary);
18. imshow("imageDst", imageDst);
19.
20. waitKey(0);
21. return 0;
22. }
Build/Run
Phép toán giãn nở và phép co có thể được gọi từ hàm cv::morphologyEx() thông qua tham số op lần lượt
là MORPH_DILATE và MORPH_ERODE. Ngoài ra, bạn có thể sử dụng phép giãn nở và phép co có thể
được gọi trực tiếp từ hàm cv::dialate() và cv::erode().
Chú ý
Các tham số của các hàm cv::dialate() và cv::erode() đều có ý nghĩ giống tham số
trong hàm cv::morphologyEx().
Một điều thật sự chú ý với nội dung của hình thái học trong ảnh. Trong OpenCV có cách cài đặt
ngược lại giữa đối tượng và nền ảnh, có nghĩa là trong phép giãn nở (Dilation), phần giãn nở là
nền của ảnh (Backgroud) chứ không phải các đối tượng vật thể trong ảnh và phép co (Erotion) sẽ
làm co nền của ảnh đồng thời giãn nở các đối tượng vật thể trong ảnh.
Tổng kết
Trong bài viết này, tôi đã giới thiệu những thuật toán cơ sở trong xử lý hình thái học, và đã giới thiệu
những thuật toán và ứng dụng phổ biến hiện nay của xử lý hình thái học trên ảnh nhị phân và ảnh xám.
Một trong những vấn đề quan trọng trong các thuật toán xử lý hình thái học là tìm và sử dụng phần tử cấu
trúc phù hợp để có được kết quả tốt nhất. Hầu hết các thuật toán xử lý hình thái học đều dựa trên những
thuật toán cơ bản như phép co ảnh, giãn ảnh, đóng ảnh và mở ảnh.