Sự Kết Hợp Các Mô Hình Nền Tảng Cho Các Tác Vụ Phân Vùng và Phát Hiện
Các Mô Hình Ngôn Ngữ Thị Giác (VLMs), Mô Hình Ngôn Ngữ Lớn (LLMs) và mô hình thị giác nền tảng đang phát triển mạnh mẽ trong thế giới AI hiện tại. Mặc dù các mô hình độc quyền như ChatGPT và Claude thúc đẩy các trường hợp sử dụng kinh doanh tại các tổ chức lớn, các biến thể mã nguồn mở nhỏ hơn của các LLM và VLM này thúc đẩy các công ty khởi nghiệp và sản phẩm của họ. Xây dựng bản demo hoặc prototype có thể giúp tiết kiệm chi phí và tạo ra thứ gì đó có giá trị cho khách hàng. Câu hỏi chính đặt ra ở đây là, “Làm thế nào chúng ta xây dựng thứ gì đó bằng cách kết hợp các mô hình nền tảng khác nhau mà có giá trị?” Trong bài viết này, mặc dù không phải là một sản phẩm hoàn chỉnh, chúng ta sẽ tạo ra thứ gì đó thú vị bằng cách kết hợp Molmo VLM, mô hình phân vùng nền tảng SAM2.1, CLIP và một mô hình NLP nhỏ từ spaCy. Tóm lại, chúng ta sẽ sử dụng sự kết hợp của các mô hình nền tảng cho các tác vụ phân vùng và phát hiện trong thị giác máy tính.
Nhảy đến phần Tải Code
Video 1. Bản demo về một số mô hình nền tảng như SAM2.1, Molmo và CLIP hoạt động cùng nhau để phân vùng và phát hiện đối tượng mở.
Dự án này vẫn đang trong giai đoạn khởi đầu và sẽ thay đổi rất nhiều trong tương lai, có thể phát triển thành một cái gì đó khác biệt, hoặc thậm chí thay đổi tên khi các chức năng tăng lên. Đây là một pipeline phân vùng bán tự động sử dụng ngôn ngữ tự nhiên và hỗ trợ bằng giọng nói, với các tính năng khác nhau để lựa chọn. Video trên cho thấy một cái nhìn thoáng qua về phiên bản hiện tại của ứng dụng.
Các Nghiên Cứu Trước Đây Theo Cùng Hướng
Đã có hai bài viết trước bài viết này khi dự án bắt đầu. Các bài viết này có code độc lập (file zip) để tải xuống để nó không xung đột với code hiện tại mà chúng ta đang làm việc.
- [SAM2 và Molmo: Phân Vùng Ảnh Sử Dụng Ngôn Ngữ Tự Nhiên]([Đường dẫn bài viết]): Bài viết này chứa giải thích khi chỉ trỏ bằng Molmo và phân vùng với SAM2.1 có sẵn.
- [Tích Hợp SAM2, Molmo và Whisper cho Phân Vùng Đối Tượng]([Đường dẫn bài viết]): Bài viết này cho thấy cách lệnh thoại hỗ trợ Whisper đã được thêm vào, có thể hữu ích cho các thiết bị di động và thiết bị biên.
Code hiện đã phức tạp hơn tương đối nhiều. Một file zip độc lập của cơ sở code hiện tại sẽ được cung cấp với bài viết này. Tuy nhiên, bạn có thể tự do khám phá kho lưu trữ SAM_Molmo_Whisper.
![Trang GitHub SAM-Molmo_Whisper.]([Đường dẫn hình ảnh])
Hình 1. Trang GitHub SAM_Molmo_Whisper.
Những gì chúng ta sẽ đề cập trong bài viết này về SAM_Molmo_Whisper?
- Mọi mô hình nền tảng chính – SAM2.1, Molmo VLM, CLIP và Whisper tích hợp với phần còn lại của code như thế nào để tạo ra một pipeline liền mạch?
- Làm thế nào một mô hình NLP nhỏ từ spaCy có thể giúp tạo ra một nhãn lớp mà không cần huấn luyện trước/fine-tuning cho các đối tượng trong thế giới thực?
- Ứng dụng hỗ trợ những tính năng khác nhau nào?
- Xử lý tuần tự các mask để có kết quả tốt hơn.
- Tự động gán nhãn bằng CLIP.
- Trỏ và trò chuyện với hình ảnh mà không cần xử lý mask SAM2.1.
- Vẽ các bounding box xung quanh tất cả các đối tượng được phân vùng mà không cần sử dụng mô hình học sâu.
LƯU Ý: Dự án này chủ yếu cho thấy việc tích hợp các mô hình AI nền tảng, phương thức và tác vụ khác nhau có thể giúp chúng ta tạo ra những gì. Điều này hoàn toàn dựa trên Ứng dụng Gradio. Trong tương lai, các pipeline tác vụ như vậy có thể được tích hợp với nhiều ứng dụng của bên thứ ba để tạo ra các pipeline hoàn toàn hoặc bán tự động.
Về Dự Án Này – Tại sao kết hợp Molmo VLM, SAM Segmentation, Whisper Voice Assistant và CLIP Auto-Labeling?
Tại sao sử dụng một sự kết hợp của các mô hình nền tảng cho các tác vụ phân vùng và phát hiện?
Dự án này chủ yếu bắt đầu như một suy nghĩ muộn sau khi thấy khả năng phân vùng của SAM2 và khả năng trỏ của Molmo. Mặc dù SAM2 có thể phân vùng tất cả các đối tượng trong hình ảnh khi được nhắc thủ công thông qua trỏ và bounding box, không có pipeline tự động nào hoạt động với ngôn ngữ tự nhiên. Điều gì xảy ra khi có hàng trăm đối tượng tương tự trong một hình ảnh? Chúng ta có nên trỏ và nhấp vào tất cả chúng không?
Cập nhật cho đoạn văn trên: Trong khi viết bài viết này, DINO-X đã được phát hành, nó có thể chấp nhận điểm hoặc hộp làm lời nhắc cho một đối tượng để nhận ra các đối tượng tương tự trong một hình ảnh.
Trong những trường hợp như vậy, khả năng trỏ của Molmo kết hợp với ngôn ngữ tự nhiên là một cứu cánh. Chỉ cần nhập, “Trỏ vào những chiếc xe” và nếu mọi thứ thuận lợi, chúng ta sẽ có một trăm chiếc xe tự động được trỏ (cùng với tọa độ từ Molmo) và phân vùng. Đó là nơi dự án bắt đầu.
Khi dự án phát triển, những khả năng cũng tăng lên. Ban đầu, ứng dụng không thể gán cấp lớp cho các đối tượng được phân vùng. Đây là nơi CLIP và spaCy xuất hiện.
Hơn nữa, chúng ta cũng có thể dễ dàng mở rộng kết quả cuối cùng để chứa bounding box xung quanh các đối tượng được phân vùng mà không cần sử dụng mô hình học sâu.
![Sử dụng sự kết hợp của các mô hình nền tảng để phát hiện và phân vùng chim và hoa cùng với nhãn CLIP.]([Đường dẫn hình ảnh])
Hình 2. Sử dụng sự kết hợp của các mô hình nền tảng để phát hiện và phân vùng chim và hoa cùng với nhãn CLIP.
Hình trên minh họa trường hợp tốt nhất từ pipeline khi tất cả các mô hình và tác vụ hoạt động song song.
Chủ yếu, chúng ta sẽ thảo luận về ba khả năng chính của ứng dụng cùng với việc trỏ và phân vùng:
- Làm thế nào để chúng ta thực hiện phân loại mở các đối tượng được phân vùng bằng CLIP và spaCy?
- Quy trình để thu được bounding box từ các mask phân vùng mà không cần sử dụng detector là gì?
- Làm thế nào chúng ta có thể làm cho các mask phân vùng tốt hơn với mô hình SAM2.1?
Điều đáng chú ý là chúng ta sẽ chỉ thảo luận về các đoạn code của các phần rất quan trọng bao gồm ba điểm trên.
Ứng Dụng Pipeline Tác Vụ
Sơ đồ sau đây cho thấy toàn bộ workflow và các tác vụ của ứng dụng.
![Lưu đồ cho thấy sự kết hợp các mô hình nền tảng được sử dụng trong pipeline SAM_Molmo_Whisper cho các tác vụ phân vùng và phát hiện.]([Đường dẫn hình ảnh])
Hình 3. Lưu đồ cho thấy sự kết hợp các mô hình nền tảng được sử dụng trong pipeline SAM_Molmo_Whisper.
Cấu Trúc Thư Mục Dự Án
Bạn sẽ tìm thấy cấu trúc thư mục sau sau khi tải xuống và giải nén file zip.
├── demo_data
│ ├── image_1.jpg
│ ├── image_2.jpg
│ ├── image_3.jpg
│ ├── image_4.jpg
│ ├── image_5.jpg
│ ├── image_6.jpg
│ ├── image_7.jpg
│ ├── image_8.jpg
│ ├── image_9.jpg
│ ├── video_1.mp4
│ └── video_1_short.mp4
├── docs
│ ├── readme_media
│ │ └── sam2_molmo_whisper-2024-10-11_07.09.47.mp4
│ └── data_credits.md
├── experiments
│ ├── video_frames [352 entries exceeds filelimit, not opening dir]
│ ├── video_out
│ │ ├── molmo_points_output.avi
│ │ └── output.avi
│ ├── figure.png
│ ├── sam2_molmo_clip.ipynb
│ ├── sam2_molmo.ipynb
│ └── sam2_molmo_video.ipynb
├── flagged
├── outputs
│ └── molmo_points_output.webm
├── temp
├── utils
│ ├── general.py
│ ├── load_models.py
│ ├── model_utils.py
│ └── sam_utils.py
├── app.py
├── LICENSE
├── README.md
└── requirements.txt
content_copy download Use code with caution.
- Thư mục dự án mẹ chứa script app.py có thể thực thi, giấy phép, README và file requirements.
- Thư mục utils chứa tất cả các script hỗ trợ để tải mô hình, logic cho forward pass mô hình và code trực quan hóa cùng với các chức năng tiện ích khác.
- Chúng ta cũng có một thư mục experiments chứa các Jupyter Notebook thử nghiệm.
- Thư mục demo_data chứa một vài hình ảnh và video mẫu mà chúng ta sử dụng cho các thử nghiệm.
Tải Code
[Tải xuống Source Code cho Hướng Dẫn này]([Đường dẫn tải xuống])
Thiết Lập SAM_Molmo_Whisper
File README chứa tất cả các bước để thiết lập dự án. Vì chúng ta đang làm việc với một codebase độc lập, chúng ta không cần clone kho lưu trữ. Chúng ta có thể chuyển thẳng đến việc cài đặt các yêu cầu.
pip install -r requirements.txt
content_copy download Use code with caution.
Tiếp theo, cài đặt SAM2 cần thiết cho phân vùng. Bạn nên clone SAM2 vào một thư mục riêng và sau đó chạy lệnh cài đặt.
git clone https://github.com/facebookresearch/sam2.git && cd sam2
pip install -e .
content_copy download Use code with caution.
Cuối cùng, cài đặt mô hình spaCy English mà chúng ta cần cho CLIP auto-labeling.
spacy download en_core_web_sm
content_copy download Use code with caution.
Kết Hợp Các Mô Hình Nền Tảng Cho Các Tác Vụ Phân Vùng và Phát Hiện
Như chúng ta đã thiết lập cho đến bây giờ, ứng dụng sử dụng một số mô hình:
- Molmo để trỏ/đếm/captioning.
- SAM để phân vùng ảnh.
- Các mô hình CLIP và spaCy English để phân loại.
- Whisper cho lời nhắc hỗ trợ bằng giọng nói.
Trong phần còn lại của bài viết và các phần phụ sau, chúng ta sẽ khám phá cách mỗi mô hình trên tương tác và giúp chúng ta đạt được phân vùng, phát hiện và phân loại đối tượng mở trong hình ảnh.
Khả Năng Trỏ và Đếm Của Molmo
Chúng ta sẽ bắt đầu với tác vụ đơn giản nhất có thể trong ứng dụng. Khả năng trỏ, đếm và captioning hình ảnh của Molmo.
Code cho tác vụ này chủ yếu nằm trong app.py và utils/sam_utils.py. Khi chúng ta chọn chế độ Chat Only từ Additional Inputs, thì tất cả các tùy chọn khác đều bị bỏ qua, bao gồm cả phân vùng.
![Chế độ Chat Only được bật trong ứng dụng SAM_Molmo_Whisper.]([Đường dẫn hình ảnh])
Hình 4. Chế độ Chat Only được bật trong ứng dụng SAM_Molmo_Whisper.
Trong trường hợp này, đoạn code sau trong hàm process_image của app.py được thực thi.
else:
masks, scores, logits, sorted_ind = None, None, None, None
if not chat_only: # Get SAM output
masks, scores, logits, sorted_ind = get_sam_output(
image, sam_predictor, input_points, input_labels
)
# Visualize results.
fig = show_masks(
image,
masks,
scores,
point_coords=input_points,
input_labels=input_labels,
borders=True,
draw_bbox=draw_bbox,
chat_only=chat_only
)
return fig, output, transcribed_text
content_copy download Use code with caution.Python
Vì chúng ta đang chọn chế độ Chat Only, chúng ta không cần SAM2.1 mask, scores và logits. Nếu người dùng nhắc trỏ vào một đối tượng, thì các điểm được trích xuất sẽ được vẽ trên hình ảnh bằng hàm show_points sau từ utils/sam_utils.py.
def show_points(coords, labels, ax, clip_label, marker_size=375):
pos_points = coords[labels==1]
neg_points = coords[labels==0]
ax.scatter(
pos_points[:, 0],
pos_points[:, 1],
color='green',
marker='.',
s=marker_size,
edgecolor='white',
linewidth=1.25
)
ax.scatter(
neg_points[:, 0],
neg_points[:, 1],
color='red',
marker='.',
s=marker_size,
edgecolor='white',
linewidth=1.25
)
if clip_label is not None:
ax = add_labels(
ax,
clip_label=clip_label,
labels=labels,
pos_points=pos_points,
neg_points=neg_points
)
content_copy download Use code with caution.Python
Hãy xem ba loại lời nhắc của người dùng và phản hồi của Molmo khác nhau trong chế độ này: captioning, pointing và đếm.
Bắt đầu với captioning hình ảnh, chúng ta tải hình ảnh lên và chọn chế độ Chat Only.
![Đầu ra từ chế độ Chat Only sử dụng pipeline SAM_Molmo_Whisper.]([Đường dẫn hình ảnh])
Hình 5. Đầu ra từ chế độ Chat Only sử dụng pipeline SAM_Molmo_Whisper. Chúng ta đã yêu cầu “Describe the image”.
Chúng ta sử dụng mô hình Molmo-1B MoE (Mixture of Experts) mặc định với tổng số 7B và 1B tham số đang hoạt động trong quá trình suy luận. Như chúng ta có thể thấy từ các kết quả trên, mô tả này khá phù hợp và chi tiết.
Tiếp theo, hãy yêu cầu mô hình trỏ vào hai con chim: “Point to the birds”.
![Sử dụng Molmo và chế độ Chat Only để đếm chim.]([Đường dẫn hình ảnh])
Hình 6. Sử dụng Molmo và chế độ Chat Only để đếm chim.
Mô hình trỏ thành công vào hai con chim.
Tác vụ thứ ba liên quan đến việc đếm các đối tượng. Chúng ta nhắc mô hình bằng “Count the birds”.
![Sử dụng Molmo và chế độ Chat Only để đếm chim.]([Đường dẫn hình ảnh])
Hình 7. Sử dụng Molmo và chế độ Chat Only để đếm chim.
Molmo cũng đưa ra các đầu ra tọa độ trong khi đếm. Trong kịch bản này, chúng ta nhận được tổng số đối tượng từ caption và điểm trên chim là tốt.
Ba tác vụ trên tóm tắt những gì chúng ta có thể đạt được chỉ với Molmo.
Kết Hợp Molmo và SAM2.1
Tập hợp các thử nghiệm này sẽ kết hợp các đầu ra tọa độ điểm của Molmo và khả năng phân vùng của SAM2.1.
Phân Vùng Một Lần Với Molmo và SAM2.1
Hãy bắt đầu với một hình ảnh đơn giản nơi có một vài người. Chúng ta nhắc với “Point to the women”.
![Phân vùng một lần bằng pipeline SAM_Molmo_Whisper với lời nhắc “Point to the women”.]([Đường dẫn hình ảnh])
Hình 8. Phân vùng một lần bằng pipeline SAM_Molmo_Whisper với lời nhắc “Point to the women”.
Chúng ta bỏ qua chế độ Chat Only lần này, chế độ này tự động tải mô hình SAM2.1 Hiera Large để phân vùng. Giữ tất cả các tùy chọn khác thành mặc định sẽ chuyển tất cả các điểm được phát hiện và hình ảnh qua SAM2.1 trong một lần. Như chúng ta có thể thấy, chỉ có hai trong số chúng được phân vùng đúng cách. Điều này thường xảy ra khi chúng ta truyền một số tọa độ điểm cùng một lúc cho SAM2.1.
Xử Lý Tuần Tự Với Molmo và SAM2.1
Để khắc phục vấn đề trên, chúng ta có thể sử dụng tùy chọn Xử Lý Tuần Tự (Sequential Processing). Điều này chuyển từng điểm được phát hiện và hình ảnh gốc qua SAM2.1 một cách tuần tự. Mask do SAM2.1 trả về được thêm vào một dummy mask mặc định và tổng hợp lại. Cuối cùng, các giá trị pixel bị giới hạn giữa 0 và 1. Khối code sau trong hàm process_image trong app.py xử lý phần logic đó.
if not chat_only and sequential_processing: # If sequential processing of points is enabled without CLIP.
final_mask = np.zeros_like(image.transpose(2, 0, 1), dtype=np.float32)
# This probably takes as many times longer as the number of objects
# detected by Molmo.
for input_point, input_label in zip(input_points, input_labels):
masks, scores, logits, sorted_ind = get_sam_output(
image,
sam_predictor,
input_points=[input_point],
input_labels=[input_label]
)
sorted_ind = np.argsort(scores)[::-1]
masks = masks[sorted_ind]
scores = scores[sorted_ind]
logits = logits[sorted_ind]
final_mask += masks
masks_copy = masks.copy()
masks_copy = masks_copy.transpose(1, 2, 0)
masked_image = (image * np.expand_dims(masks_copy[:, :, 0], axis=-1))
masked_image = masked_image.astype(np.uint8)
im = final_mask >= 1
final_mask[im] = 1
final_mask[np.logical_not(im)] = 0
fig = show_masks(
image,
final_mask,
scores,
point_coords=input_points,
input_labels=input_labels,
borders=True,
draw_bbox=draw_bbox,
random_color=random_color
)
return fig, output, transcribed_text
content_copy download Use code with caution.Python
![Sử dụng Xử Lý Tuần Tự với pipeline SAM_Molmo_Whisper để có kết quả hoàn hảo.]([Đường dẫn hình ảnh])
Hình 9. Sử dụng Xử Lý Tuần Tự với pipeline SAM_Molmo_Whisper để có kết quả hoàn hảo.
Vì SAM2.1 chỉ xử lý một điểm trong hình ảnh tại một thời điểm, các kết quả lần này rất tuyệt vời. Chúng ta sử dụng cùng một lời nhắc như trên và chọn Xử Lý Tuần Tự từ UI.
Vẽ Bounding Box Với Sự Trợ Giúp Của Contours
Như bạn có thể đã quan sát ở trên, chúng ta đang vẽ các contours xung quanh các mask được phân vùng. Điều này đạt được với OpenCV. OpenCV cũng cho phép trích xuất tọa độ trên cùng bên trái và chiều rộng và chiều cao của tất cả các contours bằng cách sử dụng cv2.boundingRect. Điều này dẫn đến việc chúng ta vẽ các bounding box xung quanh các đối tượng được phân vùng miễn phí (nói về mặt tham số).
Khối code sau trong hàm show_mask của utils/sam_utils.py xử lý điều này.
if borders:
import cv2
contours_orig, _ = cv2.findContours(
mask, cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_NONE
)
# Try to smooth contours
contours_smoothed = [
cv2.approxPolyDP(
contour, epsilon=0.01, closed=True
) for contour in contours_orig
]
mask_image = cv2.drawContours(
mask_image,
contours_smoothed,
-1,
(color[0], color[1], color[2], 1),
thickness=2
)
if bboxes: # Draw bounding boxes from contours if chosen from UI.
for contour in contours_orig:
bounding_boxes = cv2.boundingRect(contour)
cv2.rectangle(
mask_image,
pt1=(int(bounding_boxes[0]), int(bounding_boxes[1])),
pt2=(int(bounding_boxes[0]+bounding_boxes[2]), int(bounding_boxes[1]+bounding_boxes[3])),
color=(color[0], color[1], color[2], 1),
thickness=2
)
plt.imshow(mask_image)
content_copy download Use code with caution.Python
Khối code trên chú thích hình ảnh với cả contours và bounding box khi tùy chọn Draw Bounding Boxes được chọn. Hãy thử điều đó với cùng một hình ảnh đầu vào của những người phụ nữ.
![Sử dụng sequential processing và bounding box cùng với các bản đồ phân vùng.]([Đường dẫn hình ảnh])
Hình 10. Sử dụng sequential processing và bounding box cùng với các bản đồ phân vùng.
Pipeline có thể vẽ bounding box xung quanh các đối tượng được phân vùng một cách chính xác.
Tuy nhiên, trong một số trường hợp, khi hai contours chồng lên nhau (hoặc tiếp tục từ một đối tượng sang đối tượng khác), thì hai đối tượng riêng biệt sẽ có cùng một bounding box. Sau đây là một trường hợp thất bại như vậy.
![Các hộp chồng lấp khi sử dụng Sequential processing và khi hai người ở gần nhau.]([Đường dẫn hình ảnh])
Hình 11. Các hộp chồng lấp khi sử dụng Sequential processing và khi hai người ở gần nhau.
Trong kết quả trên, hai người có cùng bounding box có thể không lý tưởng trong một số trường hợp. Đây là điều cần phải chỉnh sửa trong phạm vi dự án trong tương lai.
Sử dụng CLIP và spaCy để Tự Động Gán Nhãn
Đến bây giờ, chúng ta hiểu rằng chúng ta có thể phân vùng hầu hết mọi đối tượng trong một hình ảnh. Điều này cực kỳ hữu ích nếu chúng ta có thể tích hợp các pipeline như vậy vào phần mềm chỉnh sửa và chú thích khác nhau. Tuy nhiên, trong những trường hợp đó, việc nhận một nhãn (hoặc tên lớp) cho đối tượng cũng có thể quan trọng. Mặc dù SAM2.1 vốn không có khả năng gán nhãn đối tượng, chúng ta có thể sử dụng một vài phương pháp tính toán thấp để lấy nhãn lớp của các đối tượng được phân vùng/phát hiện.
Đây là nơi khả năng của CLIP và spaCy NLP xuất hiện. Mô hình OpenAI CLIP có thể chấp nhận một hình ảnh và một danh sách chứa tất cả các lớp có thể có mà nó thuộc về và có khả năng xuất ra tên lớp chính xác từ danh sách bằng cách xử lý hình ảnh.
Ví dụ: chúng ta cung cấp cho CLIP một hình ảnh về một con mèo và một danh sách chứa – [‘cat’, ‘dog’, ‘panda’]