Thị giác máy tính vẫn là một ứng dụng cực kỳ hấp dẫn của trí tuệ nhân tạo. Cho dù đó là nhận dạng các yếu tố trên chiến trường hay dự đoán năng suất cây trồng, thị giác máy tính được cho là một trong những lĩnh vực có giá trị thương mại nhất (và quan trọng về mặt xã hội) của AI.
Tuy nhiên, giới hạn tỷ lệ đối với việc áp dụng các khả năng thị giác máy tính tốt nhất đôi khi là sự phức tạp liên quan đến việc xây dựng tập dữ liệu và thiết kế một hệ thống đầu cuối đơn giản sẽ thực hiện nhiệm vụ thị giác máy tính của bạn trên một hình ảnh mới.
Trong bài đăng trên blog này, chúng tôi sẽ xem xét từng bước cách giải quyết những vấn đề này bằng các công cụ tốt nhất như CVAT và Thông báo nhóm MinIO. Đến cuối bài đăng này, bạn sẽ có thể huấn luyện mô hình phát hiện đối tượng trên tập dữ liệu tùy chỉnh và sử dụng nó để đưa ra dự đoán bất cứ khi nào một hình ảnh mới xuất hiện.
Giả sử chúng ta muốn có thể nhận ra các loại máy bay có trong hình ảnh vệ tinh. Cũng giả sử chúng ta đang bắt đầu lại từ đầu: không có tập dữ liệu dựng sẵn, không có mô hình được đào tạo trước. Dưới đây là hai máy bay mẫu mà chúng tôi muốn phát hiện và nhận dạng trong hình ảnh vệ tinh của mình:
Các bước được nêu trong bài đăng này có thể được khái quát hóa cho bất kỳ tên miền nào. Thay vì phát hiện các loại máy bay, chúng ta có thể phân loại việc sử dụng đất hoặc thực hiện hồi quy để dự đoán năng suất cây trồng. Ngoài các hình ảnh truyền thống, chúng tôi cũng có thể đào tạo và thực hiện suy luận về các loại dữ liệu đa chiều khác như đám mây điểm LiDAR hoặc Hình ảnh địa chấn 3D; nó chỉ trở thành câu hỏi về dữ liệu huấn luyện trông như thế nào (và có thể là một mô hình học sâu khác thay vì YOLO). Nếu bạn có thêm câu hỏi về việc điều này sẽ trông như thế nào đối với một trường hợp sử dụng cụ thể, vui lòng đưa ra vấn đề trên repo GitHub!
Đối với dự án này, phần lớn là do không sở hữu vệ tinh chụp ảnh theo yêu cầu, tôi đã đến thăm các sân bay trên Google Earth và chụp nhiều ảnh chụp màn hình về các khu vực có thể nhìn thấy một số máy bay này. Việc lắp ráp bộ hình ảnh này mất khá nhiều thời gian nên tôi đã lưu trữ tất cả chúng vào một nhóm trên máy chủ MinIO của mình có tiêu đề “phát hiện đối tượng”. Trong môi trường sản xuất, lợi ích của việc lưu trữ các mẫu đã thu thập của bạn trên MinIO càng trở nên rõ ràng hơn. Sao chép chủ động, mức mã hóa cao nhất và GET/PUT siêu nhanh (kể tên một số) có nghĩa là các mẫu được thu thập cẩn thận của bạn sẽ có tính khả dụng cao, an toàn và bảo mật.
Để huấn luyện mô hình phát hiện đối tượng cho trường hợp sử dụng của bạn, cần có tập dữ liệu được gắn nhãn (hoặc 'chú thích'). Một công cụ tuyệt vời cho việc này là CVAT của OpenCV. Một tính năng thú vị là CVAT cung cấp tiện ích để kết nối nhóm MinIO của bạn dưới dạng “bộ lưu trữ đám mây” nhằm cung cấp trực tiếp hình ảnh trong nhóm của bạn vào công cụ chú thích tập dữ liệu. Để thực hiện việc này, hãy đảm bảo rằng máy chủ của Máy chủ MinIO của bạn có thể truy cập được vào máy chủ CVAT, đặc biệt nếu bạn đang chạy Máy chủ MinIO tại chỗ hoặc cục bộ trên máy tính xách tay của mình. Ngoài ra, xin lưu ý rằng có hai cách để sử dụng CVAT: (1) sử dụng ứng dụng web được cung cấp tại app.cvat.ai hoặc (2) chạy ứng dụng đó cục bộ. Trong cả hai trường hợp, khi bạn đã mở CVAT, hãy nhấp vào “Cloud Storages” trên thanh menu. Từ đó, bạn có thể điền vào biểu mẫu để đính kèm nhóm MinIO (Tương thích với S3) của mình:
Bây giờ chúng ta hãy tạo tác vụ ghi nhãn mới trong “Nhiệm vụ”:
Bạn sẽ được nhắc điền vào một biểu mẫu:
Khi tạo tác vụ, điều quan trọng là phải xác định chính xác các nhãn lớp (tôi đã xác định hai nhãn Hình chữ nhật có tiêu đề “SU30” và “TU95,” tương ứng với hai mặt phẳng mà tôi muốn phát hiện):
Bây giờ, bước còn lại là đính kèm nhóm MinIO đã thêm trước đó của chúng tôi làm nguồn dữ liệu. Trong “Chọn tệp”, hãy nhấp vào “Lưu trữ đám mây” và điền tên bạn đã cung cấp cho nguồn đó trước đó. Tôi đã sử dụng tên “minio-cv-bucket” ở trên.
Quá trình tải lên sẽ mất vài phút. Sau khi hoàn tất, bạn sẽ có thể thấy công việc chú thích của mình có sẵn trong “Việc làm”.
Bây giờ, bằng cách nhấp vào công việc, bạn có thể bắt đầu chú thích từng hình ảnh của mình. Cảnh báo: đây có thể là một quá trình tốn nhiều thời gian. Nói chung, trong môi trường sản xuất có nhu cầu chú thích lớn, tốt nhất nên giao nhiệm vụ này cho một nhóm nội bộ chuyên trách hoặc công ty ghi nhãn dữ liệu bên thứ ba.
Sau khi bạn chú thích xong, hãy xuất tập dữ liệu ở định dạng YOLO.
Tập dữ liệu đã xuất của bạn sẽ ở dạng tệp zip. Sau khi bạn giải nén nó, các tệp văn bản chú thích có định dạng YOLO sẽ nằm trong một thư mục kèm theo. Hãy nhìn vào chúng. Ở định dạng YOLO, chú thích của mỗi hình ảnh nằm trong một tệp văn bản trong đó mỗi dòng chứa hai góc của hộp giới hạn và lớp. Số lớp tương ứng với thứ tự bạn đã xác định nhãn khi tạo tác vụ. Vì vậy, trong ví dụ này, 0 sẽ tương ứng với Su-30 và 1 sẽ tương ứng với Tu-95.
Tại thời điểm này, hãy tạo một thư mục làm việc mới (hoặc nhập thư mục bạn đã tạo). Trong thư mục này, tạo một thư mục con có tên là 'dataset.' Trong 'tập dữ liệu', hãy tạo các thư mục sao cho thư mục làm việc của bạn trông như thế này:
my_cv_project (WORKING DIRECTORY) |---- dataset |----images |----train |----val |----test |----annotations |----train |----val |----test
Bây giờ bạn sẽ phải điền các thư mục con train, val và test cho cả hình ảnh và chú thích tương ứng của chúng (tệp văn bản). Tùy thuộc vào cách bạn muốn truy xuất và chia nhỏ các mẫu của mình. Một cách thực hành tốt là chia tổng số mẫu đào tạo của bạn thành 80% đào tạo, 10% xác nhận và 10% kiểm tra. Đảm bảo xáo trộn ngẫu nhiên các hình ảnh của bạn trước khi phân vùng chúng.
Cá nhân tôi đã sử dụng mc cp của MinIO Client trong dòng lệnh để nhanh chóng truy xuất tất cả hình ảnh từ nhóm 'phát hiện đối tượng' của mình. Ngoài ra, nếu bạn đã có tất cả hình ảnh mẫu ở một nơi trên máy tính cục bộ, bạn có thể trực tiếp làm việc với nó. Khi tôi đã có tất cả các mẫu của mình ở một nơi, tôi đã sử dụng tập lệnh Python để xáo trộn, phân tách và di chuyển hình ảnh cũng như chú thích của mình đến các thư mục train, val và test. Đây là kịch bản được cung cấp để thuận tiện . Nếu bạn có bất kỳ câu hỏi nào về cách sử dụng nó, vui lòng nêu vấn đề trong repo !
Cuối cùng, hãy đảm bảo rằng đối với mỗi hình ảnh mà bạn đã đặt trong các hình ảnh/xe lửa, hình ảnh/val hoặc hình ảnh/kiểm tra, tệp .txt chú thích phù hợp cũng nằm trong thư mục con tương ứng trong thư mục chú thích/. Ví dụ:
my_cv_project (WORKING DIRECTORY) |---- dataset |----images |----train - 5.png - 3.png - 2.png |----val - 4.png |----test - 1.png |----annotations |----train - 5.txt - 3.txt - 2.txt |----val - 4.txt |----test - 1.txt
Bây giờ, dữ liệu của chúng tôi đã có sẵn. Đã đến lúc xem mô hình phát hiện đối tượng của chúng tôi và bắt đầu đào tạo.
Tiêu chuẩn vàng hiện tại (về hiệu suất và tính dễ sử dụng) để nhận dạng đối tượng là lớp mô hình YOLO (Bạn chỉ nhìn một lần). Tại thời điểm viết bài, YOLOv8 là phiên bản mới nhất và được Ultralytics duy trì dưới dạng nguồn mở. YOLOv8 cung cấp một API đơn giản mà chúng ta có thể tận dụng để huấn luyện mô hình trên các chú thích mới tạo (và cuối cùng là chạy cả suy luận).
Hãy tải xuống YOLOv8:
$ pip install ultralytics
Bây giờ chúng ta có thể sử dụng công cụ YOLOv8 CLI hoặc Python SDK để đào tạo, xác thực và dự đoán. Tham khảo tài liệu YOLOv8 để biết thêm thông tin.
Trong thư mục làm việc của bạn, hãy xác định tệp YAML chỉ định vị trí của tập dữ liệu và thông tin chi tiết về các lớp. Lưu ý rằng các đường dẫn giống với những đường dẫn tôi đã tạo trước đó trong thư mục làm việc. Tôi gọi tập tin của mình là ' obj detect.yaml .' Ngoài ra, hãy lưu ý rằng hai nhãn loại máy bay phải được xác định theo cùng thứ tự như trong CVAT.
train: ./dataset/images/train/ val: ./dataset/images/val/ test: ./dataset/images/test/ # number of classes nc: 2 # class names names: ["SU-30","TU-95"]
Bắt đầu đào tạo mô hình YOLOv8 trên tập dữ liệu của chúng tôi bằng lệnh sau (sử dụng công cụ YOLO CLI). Tham khảo tài liệu YOLO để tìm hiểu thêm về tất cả các tùy chọn khác nhau mà bạn có thể định cấu hình cho việc đào tạo. Ở đây, tôi đang bắt đầu đào tạo cho 100 kỷ nguyên và đặt kích thước hình ảnh là 640 pixel (tất cả các hình ảnh đào tạo của chúng tôi sẽ được điều chỉnh tỷ lệ tương ứng trong quá trình đào tạo):
$ yolo task=detect \ mode=train \ model=yolov8s.pt \ data=objdetect.yaml \ epochs=100 \ imgsz=640
Quá trình đào tạo sẽ mất một khoảng thời gian, đặc biệt nếu bạn đang làm việc trên máy tính xách tay (như tôi), vì vậy bây giờ là thời điểm thích hợp để nghỉ ngơi (hoặc đọc trước 😀)!
Khi kết thúc vòng đào tạo, mô hình đã đào tạo của bạn cùng với các đồ thị và biểu đồ thú vị khác sẽ được lưu trữ trong thư mục được tạo tự động có tên là 'run'. Đầu ra của thiết bị đầu cuối (như bên dưới) sẽ cho biết vị trí cụ thể của kết quả của lần chạy gần nhất. Mỗi khi bạn huấn luyện một mô hình, một thư mục tương tự sẽ được tạo trong 'runs/ detect/'.
Results saved to runs/detect/train
Lưu ý: run/ detect/train/weights/ sẽ chứa các tệp PT có trọng số được huấn luyện chính xác. Hãy ghi nhớ vị trí này cho sau này.
Bạn có thể chạy xác thực bằng lệnh sau:
$ yolo task=detect \ mode=val \ model=path/to/best.pt \ data=objdetect.yaml
Kết quả sẽ được tự động lưu trữ trong một thư mục trong thư mục làm việc của bạn với đường dẫn có dạng 'runs/ detect/val.'
Để thực hiện suy luận trên tập kiểm tra, bạn có thể sử dụng lệnh sau:
$ yolo task=detect \ mode=predict \ model=path/to/best.pt \ conf=0.5 \ source=dataset/images/test
Kết quả sẽ được lưu trữ trong 'chạy/phát hiện/dự đoán.' Dưới đây là một số kết quả dự đoán trên bộ thử nghiệm:
Bây giờ chúng ta đã có một mô hình đã được huấn luyện có thể nhận dạng một số loại máy bay có trong ảnh vệ tinh, làm cách nào để chúng ta có thể sử dụng nó cho các ảnh mới một cách đơn giản ?
Thông báo nhóm MinIO là một công cụ hoàn hảo cho việc này. Chúng tôi có thể xây dựng một hệ thống có thể tự động thực hiện suy luận phát hiện đối tượng dựa trên một hình ảnh mới được thả vào nhóm của chúng tôi với sự trợ giúp của webhook.
Ở cấp độ cao, chúng tôi có 3 bước. Trước tiên, chúng ta cần xác định một điểm cuối có thể đóng vai trò là webhook để thực hiện phát hiện đối tượng trên hình ảnh mới bằng mô hình đã đào tạo của chúng ta. Thứ hai, chúng ta cần định cấu hình một số biến môi trường để triển khai Máy chủ MinIO để hướng dẫn nó truy cập điểm cuối webhook khi một số sự kiện xảy ra. Thứ ba, chúng ta cần định cấu hình loại sự kiện nhóm (tức là PUT) mà chúng ta muốn thực hiện. Chúng ta hãy đi qua nó từng bước một.
Đây là mã cho một máy chủ dựa trên Flask đơn giản ( detect_server.py ) chạy suy luận trên một hình ảnh mới được thêm vào nhóm MinIO:
""" This is a simple Flask inference server implementation that serves as a webhook for the event of a new image being added to a MinIO bucket. Object detection using YOLO will be performed on that image and the resulting predictions will be returned. """ from flask import Flask, request, abort, make_response from ultralytics import YOLO import tempfile from minio import Minio # Make sure the following are populated with your MinIO details # (Best practice is to use environment variables!) MINIO_ENDPOINT = '' MINIO_ACCESS_KEY = '' MINIO_SECRET_KEY = '' model = YOLO('/PATH/TO/best.pt') # load a custom model (path to trained weights) client = Minio( MINIO_ENDPOINT, access_key=MINIO_ACCESS_KEY, secret_key=MINIO_SECRET_KEY, ) app = Flask(__name__) @app.route('/', methods=['POST']) async def inference_bucket_webhook(): """ This endpoint will be called when a new object is placed in your inference bucket """ if request.method == 'POST': # Get the request event from the 'POST' call event = request.json bucket = event['Records'][0]['s3']['bucket']['name'] obj_name = event['Records'][0]['s3']['object']['key'] with tempfile.TemporaryDirectory() as temp_dir: temp_file_name = temp_dir+'/'+obj_name client.fget_object(bucket, obj_name, temp_file_name) # See https://docs.ultralytics.com/modes/predict/ for more information about YOLO inference options results = model.predict(source=temp_file_name, conf=0.5, stream=False) # A list of bounding boxes (if any) is returned. # Each bounding box is in the format [x1, y1, x2, y2, probability, class]. result = {"results": results[0].boxes.data.tolist()} print(result) resp = make_response(result, 200) return resp else: abort(400) if __name__ == '__main__': app.run()
Hãy khởi động máy chủ suy luận:
$ python detection_server.py * Serving Flask app 'detection_server' * Debug mode: off * Running on http://127.0.0.1:5000 Press CTRL+C to quit
Ghi lại tên máy chủ và cổng mà ứng dụng Flask đang chạy.
Tiếp theo, hãy bắt đầu cấu hình webhooks ở phía MinIO. Đầu tiên, đặt các biến môi trường sau. Thay thế <YOURFUNCTIONNAME> bằng tên chức năng bạn chọn. Để đơn giản, tôi sử dụng 'suy luận'. Ngoài ra, hãy đảm bảo rằng biến môi trường điểm cuối được đặt thành máy chủ và cổng chính xác cho máy chủ suy luận của bạn. Trong trường hợp này, http://localhost:5000 là nơi ứng dụng Flask của chúng tôi đang chạy.
$ export MINIO_NOTIFY_WEBHOOK_ENABLE_<YOURFUNCTIONNAME>=on $ export MINIO_NOTIFY_WEBHOOK_ENDPOINT_<YOURFUNCTIONNAME>=http://localhost:5000
Bây giờ, hãy khởi động lại Máy chủ MinIO bằng lệnh mc admin service restart ALIAS hoặc nếu khởi động máy chủ lần đầu tiên, bạn cũng có thể chỉ cần sử dụng lệnh minio server . Để biết thêm thông tin về việc khởi động lại/khởi động lại Máy chủ MinIO, hãy xem tài liệu MinIO. Lưu ý: Nên thay thế ALIAS bằng bí danh để triển khai máy chủ MinIO của bạn. Để biết thêm thông tin về cách đặt bí danh hoặc xem bí danh hiện có, hãy xem tài liệu .
Cuối cùng, hãy thêm nhóm và sự kiện mà chúng ta muốn được thông báo. Trong trường hợp của chúng tôi, chúng tôi muốn được thông báo về các sự kiện ` put` (tạo đối tượng mới) trong nhóm của chúng tôi. Tôi đã tạo một nhóm trống hoàn toàn mới cho mục đích này có tiêu đề “phát hiện suy luận”, vì vậy tôi sẽ thay thế nhóm đó bằng 'BUCKET'.
$ mc event add ALIAS/BUCKET arn:minio:sqs::<YOURFUNCTIONNAME>:webhook --event put
Bạn có thể kiểm tra xem mình đã định cấu hình đúng loại sự kiện cho thông báo nhóm hay chưa bằng cách xác minh xem " s3:ObjectCreated:* " có được xuất ra khi bạn chạy lệnh này hay không:
$ mc event ls local/detect-inference arn:minio:sqs::<YOURFUNCTIONNAME>:webhook
Để có giải thích chi tiết hơn về việc xuất bản các sự kiện nhóm lên webhook, hãy xem tài liệu . Bây giờ chúng ta đã sẵn sàng thử phát hiện đối tượng trên một hình ảnh hoàn toàn mới!
Đây là hình ảnh mới (có tiêu đề '1.png') tôi muốn tiến hành suy luận về:
Tôi thả hình ảnh mới vào nhóm 'phát hiện suy luận' của mình:
Gần như ngay lập tức, tôi có thể thấy các kết quả sau trên máy chủ Flask của mình:
$ python detection_server.py * Serving Flask app 'detection_server' * Debug mode: off * Running on http://127.0.0.1:5000 Press CTRL+C to quit image 1/1 /var/folders/xf/q7x0z8sn5nvckccp1g0m1vpm0000gn/T/tmpo6jx3w8u/1.png: 448x736 2 SU-30s, 101.0ms Speed: 4.1ms preprocess, 101.0ms inference, 5.8ms postprocess per image at shape (1, 3, 448, 736) {'results': [[1927.78369140625, 627.7123413085938, 1995.090576171875, 715.3443603515625, 0.8142037987709045, 0.0], [1735.740234375, 477.2108154296875, 1809.181640625, 555.767578125, 0.7766116261482239, 0.0]]} 127.0.0.1 - - [14/Sep/2023 15:39:21] "POST / HTTP/1.1" 200 -
Lưu ý rằng mỗi hộp giới hạn được phát hiện trong danh sách kết quả đều có định dạng YOLO [x1, y1, x2, y2, xác suất, lớp]. Dưới đây là các hộp giới hạn và các lớp được dự đoán được xếp chồng lên ảnh gốc:
Lưu ý: Đối với môi trường sản xuất và/hoặc mô hình máy học lớn, bạn nên sử dụng khung cung cấp mô hình đã được thiết lập sẵn như PyTorch Serve hoặc Triton Server để làm cho suy luận mạnh mẽ và đáng tin cậy hơn. Nếu bạn quan tâm đến điều đó, hãy xem bài đăng trước về Tối ưu hóa việc phân phát mô hình AI bằng MinIO và PyTorch Serve .
Chúng ta làm được rồi! Chúng tôi đã tìm hiểu cách MinIO và CVAT kết hợp với nhau để giữ cho các mẫu hình ảnh được thu thập của chúng tôi an toàn và sẵn có, cũng như cách tạo tập dữ liệu phát hiện đối tượng tùy chỉnh của chúng tôi. Sau đó, chúng tôi đã đào tạo mô hình YOLO tùy chỉnh của riêng mình cho nhiệm vụ tùy chỉnh của mình. Cuối cùng, chỉ với hơn 50 dòng mã, chúng tôi đã kết hợp một máy chủ suy luận bằng cách sử dụng Thông báo nhóm MinIO có thể chạy hình ảnh mới qua mô hình phát hiện đối tượng được đào tạo tùy chỉnh của chúng tôi.
Hơn nữa, đối với hầu hết các ứng dụng quan trọng của thị giác máy tính, tốt nhất nên tiến hành suy luận ở biên. Mặt khác, các ứng dụng nói trên dễ bị ảnh hưởng bởi độ trễ liên quan đến việc tải dữ liệu mới lên đám mây công cộng và chờ máy chủ suy luận trên đám mây phản hồi và đưa ra câu trả lời – chưa kể đến rủi ro do kết nối mạng bị lỗi. Vì lý do này, quy trình thị giác máy tính tập trung vào MinIO làm lớp dữ liệu sẽ có ý nghĩa hơn nhiều. Hãy tưởng tượng một chiếc máy bay không người lái bay trên sân bay, có thể chụp, lưu trữ và sử dụng mô hình đã được huấn luyện của chúng tôi trên hình ảnh mới bằng phần cứng và phần mềm hoàn chỉnh trên máy bay. Với việc triển khai cục bộ máy chủ MinIO, hệ thống suy luận dựa trên Thông báo nhóm mà chúng tôi xây dựng ở cuối bài đăng này hoạt động hoàn hảo cho tình huống này và vô số tình huống khác tương tự.
Nếu bạn có bất kỳ câu hỏi nào, hãy tham gia Kênh Slack của chúng tôi hoặc gửi thư cho chúng tôi theo địa chỉ [email protected] . Chúng tôi đang ở đây để giúp bạn.
Cũng được xuất bản ở đây .