Edges (cạnh) và Edges detection (phát hiện edges)

Một phần của tài liệu nghiên cứu thư viện opencv ứng dụng trong việc nhận dạng biển báo giao thông (Trang 39 - 43)

CHƯƠNG 2: CƠ SỞ LÝ THUYẾT

2.4. Lý thuyết xử lý ảnh và các hàm hỗ trợ bởi OpenCV

2.4.2. Edges (cạnh) và Edges detection (phát hiện edges)

Edges là các điểm trong hình ảnh mà giá trị gradient (hay cường độ – intensity) của điểm đó có giá trị cao hơn so (thay đổi giá trị intensity rõ rệt) với giá trị của các điểm bên cạnh.

Để tính gradient của toàn bộ hình, lần lượt tính gradient theo hướng x và hướng y, sau đó kết hợp lại theo định lý Pitago.

Để tính gradient thì áp dụng filter với một kernel thích hợp, đối với trường hợp của edge thì tính gradient còn được gọi là derivative (đạo hàm).

Edges detect bằng Sobel và Schar derivative

Giải thuật Sobel và Schar là một phép toán tính đạo hàm, nó tính gần đúng gradient của một hình ảnh. Sobel có thể tính được đạo hàm cấp 1, 2, 3 và có thể áp dụng được nhiều kích thước của kernel. Schar là một trường hợp đặc biệt của Sobel, nó sử dụng một kernel có kích thước là 3 với giá trị khác với kích thước 3 của Sobel để cho độ chính xác cao hơn và chỉ có thể tính được đạo hàm cấp 1.

Do đó, có thể tìm được egdes của một hình ảnh ký hiệu là I , theo bước sau:

1. Tính đạo hàm cấp 1 theo từng hướng:

a. Hướng x được ký hiệu là Gx : áp dụng Sobel filter với một kernel có kích thước lẽ, ví dụ như kích thước là 3 là:

Gx=[−1 0−2 0−1 0 +++121]∗I

b. Hướng y được ký hiệu là Gy : áp dụng Sobel filter với một kernel có kích thước lẽ, ví dụ như kích thước là 3 là:

Gy=[−1+10 −2+02 −1+10 ]∗I

2. Sử dụng định lý Pitago trong tam giác để tính gradient của toàn bộ hình ảnh:

G=√Gx 2+G2y

Giá trị của kernel tuỳ thuộc vào bậc đạo hàm và kích thước của chính nó. Với Schar thì giá trị của kernel như sau:

Gx=[−10 0−3−3 00 +10+3+3 ]∗I Gy=[−3+30 −10100 −3+30 ]∗I

Sobel

Tính đạo hàm cấp 1, 2, 3 hoặc hỗn hợp của ma trận sử dụng giải thuật Sobel mở rộng.

void Sobel(InputArray src, OutputArray dst, int ddepth, int dx, int dy, int ksize = 3, double scale = 1, double delta = 0, int borderType = BORDER_DEFAULT)

Trong đó,

• src – Ma trận nguồn

• dst – Ma trận đích có size và số channels giống như src

• ddepth – depth của ma trận đích, tuỳ thuộc vào giá trị của src.depth()

◦ src.depth() = CV_8U , ddepth = -1/ CV_16S / CV_32F / CV_64F

◦ src.depth() =CV_16U / CV_16S , ddepth = -1/ CV_32F / CV_64F

◦ src.depth() =CV_32F , ddepth = -1/ CV_32F / CV_64F

◦ src.depth() =CV_64F , ddepth = -1/ CV_64F nếu ddepth = -1 thì dst.depth() = src.depth()

• dx – Bậc của đạo hàm theo hướng x

• dy – Bậc của đạo hàm theo hướng y

• ksize – Kích thước kernel thuộc các giá trị 1, 3, 5, 7

◦ Hoặc CV_SCHARR (giá trị –1) sẽ tương ứng với kernel 3 x 3 Schar filter

◦ Nếu giá trị là 1 sẽ tương ứng với kernel có kích thước là 3 x 1 và 1 x 3, và chỉ có thể tính được đạo hàm cấp 1 và 2

Schar

Tính đạo hàm cấp 1 của ma trận theo giải thuật Schar.

void Scharr(InputArray src, OutputArray dst, int ddepth, int dx, int dy, double scale = 1, double delta = 0, int borderType = BORDER_DEFAULT)

Các đối số tương tự như hàm Sobel.

Khi gọi:

Scharr(src, dst, ddepth, dx, dy, scale, delta, borderType)

Sẽ tương tự như gọi:

Sobel(src, dst, ddepth, dx, dy, CV_SCHARR, scale, delta, borderType)

Egdes detect bằng Canny

Giải thuật Canny sử dụng một vài bước tiền xử lý (preprocessing) và hậu xử lý (postprocessing) để cho kết quả egdes được rõ ràng hơn so với Sobel và Schar, các bước cài đặt giải thuật Canny:

1. Áp dụng filter với bộ lọc GaussianBlur với kích thước kernel là 5 để giảm nhiễu:

K= 1

159[245 12 15 12 549 125 49 24 4 9 12 9 4 2 4 5 4 2]

2. Tìm gradient của hình ảnh tương tự như giải thuật Sobel:

a. Áp dụng filter với kernel có kích thước bằng 3 theo hướng x và y:

Gx=[−1 0−2 0−1 0 +++121]∗I Gy=[−1+10 −2+20 −1+01]∗I

b. Tìm gradient và hướng của toàn bộ hình ảnh:

G=√Gx

2+G2y θ=arctan(Gy Gx)

3. Non-maximum suppression được áp dụng, nhằm loại bỏ các pixel mà không phải là một phần của edge, giúp cho edges được mảnh (mỏng) và rõ ràng hơn.

4. Hysteresis tiếp tục được áp dụng để loại bỏ thành phần nhiễu, bằng cách cung cấp 2 giá trị ngưỡng cận trên và cận dưới (threshold upper và lower)

a. Nếu giá trị gradient của pixel lớn hơn giá trị upper thì giữ lại b. Nếu giá trị gradient của pixel nhỏ hơn giá trị lower thì loại bỏ

c. Nếu giá trị gradient của pixel nhỏ hơn giá trị upper và lớn hơn lower thì giữ lại nếu pixel đó có kết nối với pixel mà giá trị của nó lớn hơn upper

Tỷ lệ upper:lower thường được khuyên sử dụng là 2:1 hoặc 3:1.

Canny

Tìm edges sử dụng giải thuật Canny.

void Canny(InputArray image, OutputArray edges, double threshold1, double threshold2, int apertureSize = 3, bool L2gradient = false)

Trong đó,

• image – Hình ảnh đơn kênh 8-bit

• edges – Hình ảnh đích có size và type giống như image

• threshold1 – Giá trị cận dưới của Hysteresis

• threshold2 – Giá trị cận trên của Hysteresis

Ví dụ 2.11: Đọc vào một hình ảnh màu BRG và xử lý để phát hiện một đối tượng màu lam.

#include "opencv2/opencv.hpp"

using namespace std;

using namespace cv;

#define WINDOW_NAME "Canny edges detector"

Mat brgImage, hsvImage;

int main(int argc, char const* argv[]) { brgImage = imread(argv[1], IMREAD_COLOR);

cvtColor(brgImage, hsvImage, COLOR_BGR2HSV);

Mat hsImage(brgImage.size(), CV_8UC2);

int fromTo[] = { 0, 0, 1, 1 };

mixChannels(&hsvImage, 1, &hsImage, 1, fromTo, 2);

Mat edgesImage(brgImage.size(), CV_8UC1);

inRange(hsImage, Scalar(110, 100), Scalar(130, 255), edgesImage);

medianBlur(edgesImage, edgesImage, 3);

Canny(edgesImage, edgesImage, 40, 40 * 3, 3);

namedWindow(WINDOW_NAME, WINDOW_AUTOSIZE);

imshow(WINDOW_NAME, edgesImage); waitKey(0);

return 0;

}

Hình 2.8: Edges detect object

Một phần của tài liệu nghiên cứu thư viện opencv ứng dụng trong việc nhận dạng biển báo giao thông (Trang 39 - 43)

Tải bản đầy đủ (PDF)

(65 trang)