不得不說,最近的AI技術(shù)圈很火熱,前面的風(fēng)頭大都是chatGPT的,自從前提Meta發(fā)布了可以分割一切的CV大模型之后,CV圈也熱起來了,昨天只是初步了解了一下SAM,然后寫了一篇基礎(chǔ)介紹說明的博客,早上一大早起來已經(jīng)有2k左右的閱讀量了。
?我果斷跑去官方項(xiàng)目地址看下:
?好恐怖的增長速度,昨天寫博客的時(shí)候也不到6k,今天一早已經(jīng)翻一倍,估計(jì)隨著這波宣傳推廣后,會(huì)迎來更加恐怖的增長,說明大家對(duì)他還是滿懷期待的。
今天主要是下載了官方的源碼,想要自己實(shí)踐使用一下預(yù)測提示輸入這樣的效果。
在官方的介紹中可以看到:
?可以有兩種使用當(dāng)時(shí),這里我先實(shí)踐使用的是第一種的方式,我使用的測試圖片也是官方源碼附帶的,如下:
?這里可以下載三款模型,如下:
?這里我遵從官方的指導(dǎo),使用默認(rèn)的H系列的模型也就是sam_vit_h_4b8939.pth
顯示原圖,如下:
image = cv2.imread('truck.jpg')
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
plt.figure(figsize=(10,10))
plt.imshow(image)
plt.axis('on')
plt.show()
結(jié)果如下:
?接下來可以加載所需要的模型權(quán)重,如下:
predictor = SamPredictor(build_sam(checkpoint="weights/sam_vit_h_4b8939.pth"))
SAM預(yù)測對(duì)象掩碼,給出預(yù)測所需對(duì)象的提示。該模型首先將圖像轉(zhuǎn)換為圖像嵌入,該圖像嵌入允許從提示有效地生成高質(zhì)量的掩模。SamPredictor類為模型提供了一個(gè)簡單的接口,用于提示模型。它允許用戶首先使用set_image方法設(shè)置圖像,該方法計(jì)算必要的圖像嵌入。然后,可以通過預(yù)測方法提供提示,以根據(jù)這些提示有效地預(yù)測掩碼。該模型可以將點(diǎn)提示和框提示以及上一次預(yù)測迭代中的掩碼作為輸入。
之后可以使用set_image喂入自己的圖像數(shù)據(jù),如下:
predictor.set_image(one_img)
masks, scores, logits = predictor.predict(
point_coords=input_point,
point_labels=input_label,
multimask_output=True,
)
print("masks.shape: ", masks.shape)
運(yùn)行輸出如下所示:
masks.shape: (3, 1200, 1800)
這是打印出來的掩碼的size,我們接下來直觀地展示出來掩碼的效果:
?圖像中我加入了一片綠葉,用來標(biāo)記自己加入的提示信息,這樣更為明顯一些
可以看到:一個(gè)點(diǎn)的標(biāo)記提示,SAM分割出來了三種結(jié)果,最后一種是我們所需要的整車的分割,但是前面兩種也是正確的,只是說是做的車窗的分割,那么如何能讓SAM更加有效理解我們的實(shí)際意圖呢?
安裝官方的說法是可以加入多提示,在這里這個(gè)例子的話我們就可以再加入別的點(diǎn)就行,如下:
我額外標(biāo)記了一點(diǎn),“誤導(dǎo)”模型,如下:
?紅色的小花我標(biāo)記為不屬于車身,模型最終分割的效果就是只有車窗了。
接下來,我將其標(biāo)記改為屬于目標(biāo)對(duì)象,效果如下:
?可以看到:這次模型只返回了一個(gè)結(jié)果,而且是我們自己想要的結(jié)果。
當(dāng)然了,如果已經(jīng)親身體驗(yàn)過官方開源的Demo網(wǎng)站的話,應(yīng)該就知道官方也提供了可以畫Box指定區(qū)域?qū)崿F(xiàn)分割,這里也是可以的。
?接下來來看實(shí)踐代碼,如下:
predictor.set_image(one_img)
input_box = np.array([425, 600, 700, 875])
masks, _, _ = predictor.predict(
point_coords=None,
point_labels=None,
box=input_box[None, :],
multimask_output=False,
)
plt.clf()
plt.figure(figsize=(20, 10))
plt.subplot(121)
plt.imshow(one_img)
plt.title("originalImage")
plt.subplot(122)
plt.imshow(one_img)
show_mask(masks[0], plt.gca())
show_box(input_box, plt.gca())
plt.axis('off')
plt.title("segmentImage")
plt.show()
效果如下:
?還是很不錯(cuò)的。
我這里之所以直接使用源碼內(nèi)置的數(shù)據(jù),主要就是不想再麻煩去自己標(biāo)注這些點(diǎn)或者是畫框,本來就是為了演示實(shí)踐功能的。
到此為止是不是覺得也就這樣的,其實(shí)還有,單獨(dú)提示輸入點(diǎn)或者框都是可以完美分割的,那么同時(shí)輸入點(diǎn)和框呢?答案是肯定也可以,官方的Demo已經(jīng)證實(shí)了,如下:
?接下來就是看如何用代碼實(shí)現(xiàn)了,如下:
#點(diǎn)+框分割
predictor.set_image(one_img)
masks, _, _ = predictor.predict(
point_coords=input_point,
point_labels=input_label,
box=input_box,
multimask_output=False,
)
plt.clf()
plt.figure(figsize=(20, 10))
plt.subplot(121)
plt.imshow(one_img)
plt.title("originalImage")
plt.subplot(122)
plt.imshow(one_img)
show_mask(masks[0], plt.gca())
show_box(input_box, plt.gca())
show_points(input_point, input_label, plt.gca())
plt.axis('off')
plt.title("segmentImage")
plt.show()
效果如下所示:
?因?yàn)闃?biāo)注了紅色小花為北京區(qū)域,這里SAM直接分割出來的就是輪胎輪廓了,而不是整體了還是很不錯(cuò)的了。
點(diǎn)+框的組合都可以,那么如果想批量輸入提示信息是否也是可以的呢?答案也是可以的,這里我們就看代碼如何實(shí)現(xiàn):
predictor.set_image(one_img)
input_box = np.array([425, 600, 700, 875])
transformed_boxes = predictor.transform.apply_boxes_torch(input_boxes, one_img.shape[:2])
masks, _, _ = predictor.predict_torch(
point_coords=None,
point_labels=None,
boxes=transformed_boxes,
multimask_output=False,
)
print("masks_shape: ", masks.shape)
plt.clf()
plt.figure(figsize=(20, 10))
plt.subplot(121)
plt.imshow(one_img)
plt.title("originalImage")
plt.subplot(122)
plt.imshow(one_img)
for mask in masks:
show_mask(mask.cpu().numpy(), plt.gca(), random_color=True)
for box in input_boxes:
show_box(box.cpu().numpy(), plt.gca())
plt.axis('off')
plt.title("segmentImage")
plt.show()
效果如下所示:
?官方同樣實(shí)現(xiàn)了更加高效簡潔的端到端推理方式,如果所有提示都提前可用,則可以以端到端的方式直接運(yùn)行SAM。這也允許對(duì)圖像進(jìn)行批處理。
圖像和提示都作為PyTorch張量輸入,這些張量已經(jīng)轉(zhuǎn)換為正確的幀。輸入被打包為圖像上的列表,每個(gè)元素都是一個(gè)dict,它采用以下鍵:
image:以CHW格式作為PyTorch張量的輸入圖像。
original_size:轉(zhuǎn)換為SAM輸入之前的圖像大小,格式為(H,W)。
point_coords:點(diǎn)提示的批量坐標(biāo)。
point_labels:點(diǎn)提示的批處理標(biāo)簽。
boxes:批量輸入框。
mask_inputs:批量輸入掩碼。
如果沒有提示,則可以排除該鍵。
輸出是每個(gè)輸入圖像的結(jié)果列表,其中列表元素是具有以下鍵的字典:
掩碼:預(yù)測的二進(jìn)制掩碼的批量火炬張量,即原始圖像的大小。
iou_predictions:模型對(duì)每個(gè)遮罩的質(zhì)量的預(yù)測。
low_res_logits:每個(gè)掩碼的低分辨率logits,可以在以后的迭代中作為掩碼輸入傳回模型。
代碼實(shí)例如下:
image1 = image # truck.jpg
image1_boxes = torch.tensor([
[75, 275, 1725, 850],
[425, 600, 700, 875],
[1375, 550, 1650, 800],
[1240, 675, 1400, 750],
], device=device)
image2 = cv2.imread('truck.jpg')
image2 = cv2.cvtColor(image2, cv2.COLOR_BGR2RGB)
image2_boxes = torch.tensor([
[450, 170, 520, 350],
[350, 190, 450, 350],
[500, 170, 580, 350],
[580, 170, 640, 350],
], device=device)
from segment_anything.utils.transforms import ResizeLongestSide
resize_transform = ResizeLongestSide(sam.image_encoder.img_size)
batched_input = [
{
'image': prepare_image(image1, resize_transform, sam),
'boxes': resize_transform.apply_boxes_torch(image1_boxes, image1.shape[:2]),
'original_size': image1.shape[:2]
},
{
'image': prepare_image(image2, resize_transform, sam),
'boxes': resize_transform.apply_boxes_torch(image2_boxes, image2.shape[:2]),
'original_size': image2.shape[:2]
}
]
batched_output = sam(batched_input, multimask_output=False)
print(batched_output[0].keys())
fig, ax = plt.subplots(1, 2, figsize=(20, 20))
ax[0].imshow(image1)
for mask in batched_output[0]['masks']:
show_mask(mask.cpu().numpy(), ax[0], random_color=True)
for box in image1_boxes:
show_box(box.cpu().numpy(), ax[0])
ax[0].axis('off')
ax[1].imshow(image2)
for mask in batched_output[1]['masks']:
show_mask(mask.cpu().numpy(), ax[1], random_color=True)
for box in image2_boxes:
show_box(box.cpu().numpy(), ax[1])
ax[1].axis('off')
plt.tight_layout()
plt.show()
結(jié)果如下:
文章來源:http://www.zghlxwxcb.cn/news/detail-418504.html
?花了基本上一早上把預(yù)測提示輸入的實(shí)踐走了一遍感覺還是可圈可點(diǎn)的,后面再繼續(xù)研究吧。文章來源地址http://www.zghlxwxcb.cn/news/detail-418504.html
到了這里,關(guān)于Segment Anything Model (SAM)——分割一切,具有預(yù)測提示輸入的圖像分割實(shí)踐的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!