Phát hiện cạnh OpenCV bằng Python với cv2.Canny() PlatoBlockchain Data Intelligence. Tìm kiếm dọc. Ái.

Phát hiện cạnh OpenCV bằng Python với cv2.Canny ()

Giới thiệu

Phát hiện cạnh là điều chúng ta làm một cách tự nhiên, nhưng không dễ dàng khi xác định các quy tắc cho máy tính. Trong khi nhiều phương pháp khác nhau đã được phát minh ra, phương pháp trị vì được phát triển bởi John F. Canny vào năm 1986, và được đặt tên một cách khéo léo là phương pháp Canny.

Nó nhanh, khá mạnh và hoạt động tốt nhất có thể đối với loại kỹ thuật hiện có. Ở phần cuối của hướng dẫn, bạn sẽ biết cách thực hiện phát hiện cạnh thời gian thực trên video và tạo ra nội dung nào đó theo dòng:

Phát hiện cạnh Canny

Phương pháp Canny là gì? Nó bao gồm bốn hoạt động riêng biệt:

  • Làm mịn Gaussian
  • Tính toán gradient
  • Độ phân giải không tối đa
  • Ngưỡng trễ

Làm mịn Gaussian được sử dụng như bước đầu tiên để “khử” hình ảnh đầu vào và làm dịu tiếng ồn, giúp đầu ra cuối cùng sạch hơn nhiều.

Độ dốc hình ảnh đã được sử dụng trong các ứng dụng trước đó để phát hiện cạnh. Đáng chú ý nhất, các bộ lọc Sobel và Scharr dựa trên độ dốc của hình ảnh. Bộ lọc Sobel có hai nhân (GxGy), Ở đâu Gx phát hiện các thay đổi theo chiều ngang, trong khi Gy phát hiện các thay đổi theo chiều dọc:

G

x

=

[

-
1

0

+
1

-
2

0

+
2

-
1

0

+
1

]

G

y

=

[

-
1

-
2

-
1

0

0

0

+
1

+
2

+
1

]

Khi bạn trượt chúng qua một hình ảnh, chúng sẽ “chọn” (nhấn mạnh) các đường theo hướng tương ứng của chúng. Các hạt nhân Scharr hoạt động theo cùng một cách, với các giá trị khác nhau:

G

x

=

[

+
3

0

-
3

+
10

0

-
10

+
3

0

-
3

]

G

y

=

[

+
3

+
10

+
3

0

0

0

-
3

-
10

-
3

]

Các bộ lọc này, sau khi được chuyển đổi qua hình ảnh, sẽ tạo ra các bản đồ đặc trưng:

Phát hiện cạnh OpenCV bằng Python với cv2.Canny() PlatoBlockchain Data Intelligence. Tìm kiếm dọc. Ái.

Tín dụng hình ảnh: Davidwkennedy

Đối với các bản đồ đối tượng này, bạn có thể tính toán độ lớn gradientđịnh hướng gradient - tức là mức độ dữ dội của sự thay đổi (khả năng một cái gì đó là một cạnh) và sự thay đổi đang chỉ theo hướng nào. Vì Gy biểu thị sự thay đổi theo chiều dọc (Y-gradient) và Gx biểu thị sự thay đổi theo chiều ngang (X-gradient) - bạn có thể tính toán độ lớn bằng cách áp dụng định lý Pitago, để có được cạnh huyền của tam giác được tạo thành bởi "trái" và Chỉ đường "đúng":

$$
{G} = {sqrt {{{G} _ {x}} ^ {2} + {{G} _ {y}} ^ {2}}}
$$

Sử dụng độ lớn và hướng, bạn có thể tạo ra một hình ảnh với viền của nó được đánh dấu:

Phát hiện cạnh OpenCV bằng Python với cv2.Canny() PlatoBlockchain Data Intelligence. Tìm kiếm dọc. Ái.

Tín dụng hình ảnh: Davidwkennedy

Tuy nhiên - bạn có thể thấy bao nhiêu tiếng ồn cũng được phát ra từ bề mặt của những viên gạch! Độ dốc hình ảnh rất nhạy cảm với nhiễu. Đây là lý do tại sao các bộ lọc Sobel và Scharr được sử dụng làm thành phần, nhưng không phải là cách tiếp cận duy nhất trong phương pháp của Canny. Làm mịn Gaussian cũng giúp ở đây.

Độ phân giải không tối đa

Một vấn đề đáng chú ý với bộ lọc Sobel là các cạnh không thực sự rõ ràng. Nó không giống như ai đó lấy một cây bút chì và vẽ một đường để tạo ra đường nét của hình ảnh. Các cạnh thường không được cắt rõ ràng trong hình ảnh, vì ánh sáng khuếch tán dần dần. Tuy nhiên, chúng ta có thể tìm thấy đường chung ở các cạnh và ép phần còn lại của các pixel xung quanh nó, thay vào đó, tạo ra một đường phân cách mỏng và sạch. Điều này được gọi là Siêu tăng không tối đa! Các pixel không phải tối đa (những pixel nhỏ hơn pixel mà chúng tôi đang so sánh với chúng trong một trường cục bộ nhỏ, chẳng hạn như nhân 3 × 3) được giải nén. Khái niệm này có thể áp dụng cho nhiều nhiệm vụ hơn thế này, nhưng chúng ta hãy gắn nó với ngữ cảnh này ngay bây giờ.

Ngưỡng trễ

Nhiều trường hợp không có cạnh có thể và có khả năng sẽ được đánh giá là có cạnh, do điều kiện ánh sáng, vật liệu trong ảnh, v.v. 't. Bạn có thể ngưỡng các độ dốc và chỉ bao gồm các độ dốc mạnh hơn, giả sử rằng các cạnh "thực" có cường độ cao hơn các cạnh "giả".

Ngưỡng hoạt động theo cách giống như bình thường - nếu gradient dưới ngưỡng thấp hơn, hãy loại bỏ nó (bằng không) và nếu nó trên ngưỡng cao nhất đã cho, hãy giữ nó. Mọi thứ ở giữa giới hạn dưới và giới hạn trên đều nằm trong "vùng màu xám". Nếu bất kỳ cạnh nào ở giữa các ngưỡng được kết nối với cạnh dứt khoát (những cái trên ngưỡng) - chúng cũng được coi là các cạnh. Nếu chúng không được kết nối, chúng có thể là arficats của một cạnh được tính toán sai.

Đó là ngưỡng trễ! Trên thực tế, nó giúp làm sạch đầu ra cuối cùng và loại bỏ các cạnh giả, tùy thuộc vào những gì bạn phân loại là cạnh giả. Để tìm các giá trị ngưỡng tốt, bạn thường thử nghiệm với các giới hạn trên và dưới khác nhau cho các ngưỡng hoặc sử dụng một phương pháp tự động như phương pháp của Otsu hoặc phương pháp Tam giác.

Hãy tải một hình ảnh vào và chia tỷ lệ xám cho nó (Canny, giống như Sobel / Scharr yêu cầu hình ảnh phải được chia tỷ lệ xám):

import cv2
import matplotlib.pyplot as plt

img = cv2.imread('finger.jpg', cv2.IMREAD_GRAYSCALE)
img_blur = cv2.GaussianBlur(img, (3,3), 0)

plt.imshow(img_blur, cmap='gray')

Phát hiện cạnh OpenCV bằng Python với cv2.Canny() PlatoBlockchain Data Intelligence. Tìm kiếm dọc. Ái.

Hình ảnh cận cảnh của một ngón tay sẽ đóng vai trò như một nền tảng thử nghiệm tốt để phát hiện cạnh - không dễ để phân biệt một dấu vân tay từ hình ảnh, nhưng chúng tôi có thể ước tính một dấu vân tay.

Phát hiện cạnh trên hình ảnh với cv2.Canny ()

Thuật toán của Canny có thể được áp dụng bằng cách sử dụng OpenCV's Canny() phương pháp:

cv2.Canny(input_img, lower_bound, upper_bound)

Xem hướng dẫn thực hành, thực tế của chúng tôi để học Git, với các phương pháp hay nhất, các tiêu chuẩn được ngành công nghiệp chấp nhận và bảng lừa đảo đi kèm. Dừng lệnh Googling Git và thực sự học nó!

Việc tìm kiếm sự cân bằng phù hợp giữa giới hạn dưới và giới hạn trên có thể khó khăn. Nếu cả hai đều thấp - bạn sẽ có ít cạnh. Nếu giới hạn dưới là thấp và giới hạn trên là cao - bạn sẽ có tiếng ồn. Nếu cả hai đều cao và gần nhau - bạn sẽ có ít cạnh. Vị trí phù hợp có khoảng cách vừa đủ giữa các giới hạn và có chúng ở đúng tỷ lệ. Cuộc thí nghiệm!

Hình ảnh đầu vào sẽ bị làm mờ bằng phương pháp Canny, nhưng đôi khi, bạn sẽ được lợi từ việc làm mờ nó trước nó cũng đi vào. Phương pháp áp dụng độ mờ Gaussian 5 × 5 cho đầu vào trước khi thực hiện phần còn lại của các thao tác, nhưng ngay cả với độ mờ này, một số nhiễu vẫn có thể lọt qua, vì vậy chúng tôi đã làm mờ hình ảnh trước khi đưa nó vào thuật toán:


edge = cv2.Canny(img_blur, 20, 30)

fig, ax = plt.subplots(1, 2, figsize=(18, 6), dpi=150)
ax[0].imshow(img, cmap='gray')
ax[1].imshow(edge, cmap='gray')

Kết quả này trong:

Phát hiện cạnh OpenCV bằng Python với cv2.Canny() PlatoBlockchain Data Intelligence. Tìm kiếm dọc. Ái.

Các giá trị của 2030 ở đây không phải là tùy ý - Tôi đã thử nghiệm phương pháp này trên các tham số khác nhau và chọn một tập hợp dường như tạo ra kết quả tốt. Chúng ta có thể cố gắng tự động hóa điều này không?

Ngưỡng tự động cho cv2.Canny ()?

Bạn có thể tìm thấy một bộ giá trị ngưỡng tối ưu không? Có, nhưng nó không phải lúc nào cũng hoạt động. Bạn có thể thực hiện phép tính của riêng mình cho một số giá trị tốt, sau đó điều chỉnh phạm vi bằng sigma xung quanh ngưỡng đó:

lower_bound = (1-sigma)*threshold
upper_bound = (1+sigma)*threshold

Thời Gian sigma, nói, 0.33 - giới hạn sẽ là 0.66*threshold1.33*threshold, cho phép phạm vi ~ 1/3 xung quanh nó. Mặc dù vậy, việc tìm kiếm threshold là những gì khó khăn hơn. OpenCV cung cấp cho chúng ta phương pháp của Otsu (hoạt động hiệu quả với hình ảnh hai phương thức) và phương pháp Tam giác. Hãy thử cả hai, cũng như lấy giá trị pixel trung bình đơn giản làm tùy chọn thứ ba:

otsu_thresh, _ = cv2.threshold(img_blur, 0, 255, cv2.THRESH_OTSU)
triangle_thresh, _ = cv2.threshold(img_blur, 0, 255, cv2.THRESH_TRIANGLE)
manual_thresh = np.median(img_blur)

def get_range(threshold, sigma=0.33):
    return (1-sigma) * threshold, (1+sigma) * threshold

otsu_thresh = get_range(otsu_thresh)
triangle_thresh = get_range(triangle_thresh)
manual_thresh = get_range(manual_thresh)

print(f"Otsu's Threshold: {otsu_thresh} nTriangle Threshold: {triangle_thresh} nManual Threshold: {manual_thresh}")

Kết quả này trong:

Otsu's Threshold: (70.35, 139.65) 
Triangle Threshold: (17.419999999999998, 34.58) 
Manual Threshold: (105.18999999999998, 208.81)

Đây là những điều khá khác nhau! Từ các giá trị mà chúng ta đã thấy trước đây, chúng ta có thể dự đoán phương pháp Tam giác hoạt động tốt nhất ở đây. Ngưỡng thủ công không được cung cấp nhiều thông tin, vì nó chỉ lấy giá trị pixel trung bình và cuối cùng sẽ có ngưỡng cơ bản cao được nhân thêm thành một phạm vi rộng cho hình ảnh này. Phương pháp của Otsu ít gặp phải vấn đề này hơn, nhưng vẫn bị.

Nếu chúng tôi chạy Canny() phương pháp với các phạm vi ngưỡng sau:

edge_otsu = cv2.Canny(img_blur, *otsu_thresh)
edge_triangle = cv2.Canny(img_blur, *triangle_thresh)
edge_manual = cv2.Canny(img_blur, *manual_thresh)

fig, ax = plt.subplots(1, 3, figsize=(18, 6), dpi=150)
ax[0].imshow(edge_otsu, cmap='gray')
ax[1].imshow(edge_triangle, cmap='gray')
ax[2].imshow(edge_manual, cmap='gray')

Lưu ý: Hàm yêu cầu nhiều đối số và các ngưỡng của chúng ta là một bộ giá trị duy nhất. Chúng ta có thể phá hoại bộ thành nhiều đối số bằng cách đặt trước nó bằng *. Điều này cũng hoạt động trên danh sách và tập hợp, và là một cách tuyệt vời để cung cấp nhiều đối số sau khi lấy chúng bằng phương tiện lập trình.

Kết quả này trong:

Phát hiện cạnh OpenCV bằng Python với cv2.Canny() PlatoBlockchain Data Intelligence. Tìm kiếm dọc. Ái.

Phương pháp Tam giác hoạt động khá tốt ở đây! Điều này không đảm bảo rằng nó cũng sẽ hoạt động tốt trong các trường hợp khác.

Phát hiện cạnh thời gian thực trên video với cv2.Canny ()

Cuối cùng, hãy áp dụng tính năng phát hiện cạnh Canny cho video trong thời gian thực! Chúng tôi sẽ hiển thị video đang được xử lý (từng khung hình khi hoàn thành) bằng cách sử dụng cv2.imshow() sẽ hiển thị một cửa sổ với khung mà chúng tôi muốn hiển thị. Mặc dù vậy, chúng tôi cũng sẽ lưu video vào tệp MP4 để sau này có thể kiểm tra và chia sẻ.

Để tải video bằng OpenCV, chúng tôi sử dụng VideoCapture() phương pháp. Nếu chúng tôi vượt qua 0 - nó sẽ ghi lại từ webcam hiện tại, vì vậy bạn cũng có thể chạy mã trên webcam của mình! Nếu bạn nhập tên tệp, nó sẽ tải tệp:

def edge_detection_video(filename):
    cap = cv2.VideoCapture(filename)
    
    fourcc = cv2.VideoWriter_fourcc(*'MP4V')
    out = cv2.VideoWriter('output.mp4', fourcc, 30.0, (int(cap.get(3)), int(cap.get(4))), isColor=False)
    
    while cap.isOpened():
        (ret, frame) = cap.read()
        if ret == True:
            frame = cv2.GaussianBlur(frame, (3, 3), 0)
            frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
            edge = cv2.Canny(frame, 50, 100)
            out.write(edge)
            cv2.imshow('Edge detection', edge)
        else:
            break

        if cv2.waitKey(10) & 0xFF == ord('q'):
            break

    cap.release()
    out.release()
    cv2.destroyAllWindows()

edge_detection_video('secret_video.mp4')

Sản phẩm VideoWriter chấp nhận một số tham số - tên tệp đầu ra, FourCC (bốn mã codec, biểu thị codec được sử dụng để mã hóa video), tốc độ khung hình và độ phân giải dưới dạng một bộ tuple. Để không đoán hoặc thay đổi kích thước video - chúng tôi đã sử dụng chiều rộng và chiều cao của video gốc, có được thông qua VideoCapture ví dụ chứa dữ liệu về chính video, chẳng hạn như chiều rộng, chiều cao, tổng số khung hình, v.v.

Trong khi chụp được mở, chúng tôi cố gắng đọc khung hình tiếp theo với cap.read(), trả về mã kết quả và khung tiếp theo. Mã kết quả là True or False, biểu thị sự hiện diện của khung tiếp theo hoặc thiếu khung. Chỉ khi có khung, chúng tôi sẽ cố gắng xử lý thêm, nếu không, chúng tôi sẽ phá vỡ vòng lặp. Đối với mỗi khung hình hợp lệ, chúng tôi chạy nó qua hiệu ứng mờ gaussian, chuyển nó sang thang độ xám, chạy cv2.Canny() trên đó và viết nó bằng cách sử dụng VideoWriter vào đĩa và hiển thị bằng cách sử dụng cv2.imshow() để xem trực tiếp.

Cuối cùng, chúng tôi phát hành trình ghi và ghi video, vì cả hai đều làm việc với các tệp trên đĩa và phá hủy tất cả các cửa sổ hiện có.

Khi bạn chạy phương thức với secret_video.mp4 input - bạn sẽ thấy một cửa sổ bật lên và sau khi hoàn tất, một tệp trong thư mục làm việc của bạn:

Phát hiện cạnh OpenCV bằng Python với cv2.Canny() PlatoBlockchain Data Intelligence. Tìm kiếm dọc. Ái.

Kết luận

Trong hướng dẫn này, chúng tôi đã xem xét cách phát hiện cạnh Canny hoạt động và các bộ phận cấu thành của nó - làm mịn gaussian, bộ lọc Sobel và độ chuyển màu hình ảnh, Độ siêu âm không tối đa và Ngưỡng độ trễ. Cuối cùng, chúng tôi đã khám phá các phương pháp tìm kiếm phạm vi ngưỡng tự động để phát hiện cạnh Canny với cv2.Canny()và sử dụng kỹ thuật này trên video, cung cấp khả năng phát hiện cạnh thời gian thực và lưu kết quả vào tệp video.

Tiến xa hơn - Học sâu thực tế cho thị giác máy tính

Bản tính ham học hỏi của bạn khiến bạn muốn tiến xa hơn? Chúng tôi khuyên bạn nên kiểm tra Khóa học: “Học sâu thực tế cho thị giác máy tính với Python”.

Phát hiện cạnh OpenCV bằng Python với cv2.Canny() PlatoBlockchain Data Intelligence. Tìm kiếm dọc. Ái.

Một khóa học thị giác máy tính khác?

Chúng tôi sẽ không phân loại các chữ số MNIST hoặc thời trang MNIST. Họ đã phục vụ phần của họ từ lâu lắm rồi. Quá nhiều tài nguyên học tập đang tập trung vào bộ dữ liệu cơ bản và kiến ​​trúc cơ bản trước khi để các kiến ​​trúc hộp đen nâng cao gánh vác gánh nặng về hiệu suất.

Chúng tôi muốn tập trung vào sự làm sáng tỏ, tính thực tiễn, sự hiểu biết, trực giácdự án thực tế. Muốn học làm thế nào Bạn có thể làm nên điều khác biệt? Chúng tôi sẽ đưa bạn đi từ cách bộ não của chúng ta xử lý hình ảnh để viết một bộ phân loại học sâu cấp độ nghiên cứu cho bệnh ung thư vú đến mạng lưới học tập sâu "ảo giác", dạy cho bạn các nguyên tắc và lý thuyết thông qua công việc thực tế, trang bị cho bạn bí quyết và công cụ để trở thành chuyên gia ứng dụng học sâu để giải quyết vấn đề thị giác máy tính.

Có gì bên trong?

  • Các nguyên tắc đầu tiên của tầm nhìn và cách máy tính có thể được dạy để "nhìn"
  • Các tác vụ và ứng dụng khác nhau của thị giác máy tính
  • Các công cụ giao dịch sẽ giúp công việc của bạn dễ dàng hơn
  • Tìm kiếm, tạo và sử dụng bộ dữ liệu cho thị giác máy tính
  • Lý thuyết và ứng dụng của Mạng nơ ron chuyển đổi
  • Xử lý sự thay đổi tên miền, đồng xuất hiện và các sai lệch khác trong tập dữ liệu
  • Chuyển giao Học tập và tận dụng thời gian đào tạo cũng như các tài nguyên tính toán của người khác vì lợi ích của bạn
  • Xây dựng và đào tạo một máy phân loại ung thư vú tiên tiến nhất
  • Cách áp dụng liều lượng hoài nghi lành mạnh vào các ý tưởng chủ đạo và hiểu được hàm ý của các kỹ thuật được áp dụng rộng rãi
  • Hình dung “không gian khái niệm” của ConvNet bằng t-SNE và PCA
  • Các nghiên cứu điển hình về cách các công ty sử dụng kỹ thuật thị giác máy tính để đạt được kết quả tốt hơn
  • Đánh giá mô hình thích hợp, hình dung không gian tiềm ẩn và xác định sự chú ý của mô hình
  • Thực hiện nghiên cứu miền, xử lý tập dữ liệu của riêng bạn và thiết lập các thử nghiệm mô hình
  • Các kiến ​​trúc tiên tiến, sự phát triển của các ý tưởng, điều gì làm cho chúng trở nên độc đáo và cách thực hiện chúng
  • KerasCV - một thư viện WIP để tạo các mô hình và đường ống hiện đại
  • Cách phân tích cú pháp và đọc các bài báo và tự thực hiện chúng
  • Lựa chọn mô hình tùy thuộc vào ứng dụng của bạn
  • Tạo một đường dẫn học máy từ đầu đến cuối
  • Phong cảnh và trực giác khi phát hiện đối tượng với R-CNN, RetinaNets, SSD và YOLO nhanh hơn
  • Phân đoạn phiên bản và ngữ nghĩa
  • Nhận dạng đối tượng trong thời gian thực với YOLOv5
  • Đào tạo máy dò đối tượng YOLOv5
  • Làm việc với Máy biến áp bằng KerasNLP (thư viện WIP dành cho ngành công nghiệp)
  • Tích hợp Transformers với ConvNets để tạo phụ đề cho hình ảnh
  • Ngủ sâu
  • Tối ưu hóa mô hình Deep Learning cho thị giác máy tính

Dấu thời gian:

Thêm từ xếp chồng lên nhau