Có gì mới?
Diễn đàn ứng dụng xử lý ảnh công nghiệp trong sản xuất

Đây là một tin nhắn khách mời. Đăng ký một tài khoản miễn phí ngay hôm nay để trở thành một thành viên! Sau khi đăng nhập, bạn sẽ có thể tham gia trang web này bằng cách thêm các chủ đề và bài đăng của riêng bạn, cũng như kết nối với các thành viên khác thông qua hộp thư đến riêng của bạn!

C/C++ Thuật toán Canny

Ngôn ngữ C/C++

admin

The inspirator
Thành viên BQT
Co-Founder
Admin
Machine Vision Expert
Green Industry
Tham gia
10/06/2021
Bài viết
55
Điểm
9,104
Nơi ở
Việt Nam
Thuật toán Canny là một trong những thuật toán phổ biến nhất được sử dụng trong xử lý ảnh để phát hiện cạnh. Nó được phát triển bởi John F. Canny vào năm 1986 và nhanh chóng trở thành một công cụ quan trọng trong thị giác máy tính và xử lý ảnh. Thuật toán Canny bao gồm nhiều bước:

1. Làm mịn ảnh (Smoothing): Sử dụng bộ lọc Gaussian để giảm nhiễu trong ảnh.
2. Tính độ dốc và hướng gradient: Sử dụng bộ lọc Sobel hoặc Prewitt để tính độ dốc của ảnh theo chiều ngang và chiều dọc. Từ đó, tính được độ dốc và hướng gradient.
3. Chuẩn hóa gradient: Chuẩn hóa độ dốc để có giá trị gradient nằm trong khoảng [0, 1].
4. Phát hiện cạnh: Sử dụng hysteresis thresholding để phát hiện cạnh và loại bỏ các pixel không quan trọng.

Dưới đây là một ví dụ về cách thực hiện thuật toán Canny trong ngôn ngữ C++ sử dụng thư viện OpenCV



Trong ví dụ trên, cv::Sobel được sử dụng để tính độ dốc theo chiều ngang và chiều dọc, cv::convertScaleAbs để chuẩn hóa gradient, và cv::Canny để thực hiện phát hiện cạnh. Hysteresis thresholding được sử dụng để loại bỏ các điểm không chắc chắn là cạnh. Hãy nhớ rằng bạn cần cài đặt thư viện OpenCV để sử dụng mã nguồn trên.
 
Sửa lần cuối:

hieule

Thành viên BQT
CTO
Admin
Dev Leader
Machine Vision Expert
Green Industry
Tham gia
21/10/2023
Bài viết
24
Điểm
1,039
Nơi ở
Việt Nam
Các bước thực hiện thuật toán Canny như trong bài viết của anh @thanhle về mặt thực hiện bản chất như sau:

C++:
// Làm mịn ảnh bằng bộ lọc Gaussian
void gaussianBlur(const std::vector<std::vector<int>>& input, std::vector<std::vector<double>>& output, int rows, int cols) {
    // TODO: Cài đặt Gaussian Blur
    // Ở đây, sử dụng bộ lọc trung bình đơn giản làm mịn ảnh
    for (int i = 1; i < rows - 1; ++i) {
        for (int j = 1; j < cols - 1; ++j) {
            output[i][j] = (input[i - 1][j - 1] + input[i - 1][j] + input[i - 1][j + 1] +
                            input[i][j - 1] + input[i][j] + input[i][j + 1] +
                            input[i + 1][j - 1] + input[i + 1][j] + input[i + 1][j + 1]) / 9.0;
        }
    }
}

// Tính độ dốc và hướng gradient bằng bộ lọc Sobel
void sobel(const std::vector<std::vector<double>>& input, std::vector<std::vector<double>>& gradX, std::vector<std::vector<double>>& gradY, int rows, int cols) {
    // TODO: Cài đặt Sobel Filter
    for (int i = 1; i < rows - 1; ++i) {
        for (int j = 1; j < cols - 1; ++j) {
            gradX[i][j] = input[i - 1][j - 1] + 2 * input[i][j - 1] + input[i + 1][j - 1] -
                           input[i - 1][j + 1] - 2 * input[i][j + 1] - input[i + 1][j + 1];

            gradY[i][j] = input[i - 1][j - 1] + 2 * input[i - 1][j] + input[i - 1][j + 1] -
                           input[i + 1][j - 1] - 2 * input[i + 1][j] - input[i + 1][j + 1];
        }
    }
}

// Chuẩn hóa gradient và tính độ dốc và hướng
void normalizeGradient(const std::vector<std::vector<double>>& gradX, const std::vector<std::vector<double>>& gradY, std::vector<std::vector<double>>& gradient, int rows, int cols) {
    // TODO: Chuẩn hóa gradient
    for (int i = 0; i < rows; ++i) {
        for (int j = 0; j < cols; ++j) {
            gradient[i][j] = std::sqrt(gradX[i][j] * gradX[i][j] + gradY[i][j] * gradY[i][j]);
        }
    }
}

// Phát hiện cạnh bằng hysteresis thresholding
void hysteresisThresholding(const std::vector<std::vector<double>>& gradient, std::vector<std::vector<int>>& edges, int rows, int cols, double lowThreshold, double highThreshold) {
    // TODO: Hysteresis Thresholding
    for (int i = 1; i < rows - 1; ++i) {
        for (int j = 1; j < cols - 1; ++j) {
            if (gradient[i][j] >= highThreshold) {
                edges[i][j] = 255;
            } else if (gradient[i][j] >= lowThreshold && gradient[i][j] < highThreshold) {
                // TODO: Thực hiện hysteresis thresholding cho pixel có giá trị gradient ở giữa
                // (thêm xử lý để kiểm tra các điểm xung quanh)
                edges[i][j] = 0;
            } else {
                edges[i][j] = 0;
            }
        }
    }
}

Trên đây là code diễn giải nội tại của các hàm thực cần thực hiện và chỉ mang tính tham khảo :))
 
1 Bình luận
admin
admin đã bình luận
@hieule viết thì viết cho xong nhỉ, sao còn chờ ai ? :cool:(y)
 

admin

The inspirator
Thành viên BQT
Co-Founder
Admin
Machine Vision Expert
Green Industry
Tham gia
10/06/2021
Bài viết
55
Điểm
9,104
Nơi ở
Việt Nam
Bình luận
Top