저번 포스트에서 이야기했던 것처럼 CLIP은 LLM에 비해 긴 텍스트를 잘 encode하지 못하다. 그렇기 때문에 나는 CLIP 대신 LLM의 feature를 사용하여 language field를 학습시킬 계획이다(LLM feature-based language field). 하지만 LLM은 당연하게도 input을 텍스트의 형태로만 받기 때문에 기존 나의 논문 방식처럼 이미지를 그대로 사용할 수 없다. 그래서 나는 LLaVA를 통해 이미지를 잘 묘사하는 텍스트를 생성하고, LLM을 통해 이 텍스트의 feature를 추출하여 language field를 학습시키는 GT로 사용하려고 한다.
우선은 train dataset 중 첫번째 이미지를 LLaVA의 입력으로 주고 이 이미지 안의 모든 물체를 찾고 각 물체들을 묘사해달라고 부탁하였다. (입력 프롬프트: "Please look carefully at the image and describe all of the objects in this image." )
이 figurines scene 자체에 long-tail distribution에 해당하는 물체들이 많이 존재하고 있기 때문에 LLaVA가 이 scene의 모든 물체를 찾아주지는 못했다. 그래서 Chain-of-thought 방식 으로 여러개의 프롬프트를 주어서 LLaVA가 내가 원하는 답을 내놓을 수 있게 유도하였다. 아래처럼 jsonl 파일을 생성하여 LLaVA vqa의 입력으로 주었다.
{"question_id": 1, "text": "Please look carefully at the image with background masked and tell the foreground object.", "category": "generic"}
{"question_id": 2, "text": "Please describe that object with nouns or phrases. Please start with 'A '.", "category": "generic"}
{"question_id": 3, "text": "Please describe that object with three different ways with nouns or phrases.", "category": "generic"}
하지만 역시 테이블 위의 모든 물체를 설명하는 텍스트를 만들어내지는 못했다. 그래서 나는 SAM을 사용하여 background를 마스킹하고 LLaVA의 입력으로 주었다. 이전에 CLIPSeg 논문에서 background를 단순 마스킹하는 것보다 blur + dim 효과 를 동시에 주면 CLIP에서 이미지를 더 잘 인식하였다고 하여 동일한 방식을 적용하여 이미지를 마스킹했다.
sam = sam_model_registry["default"](checkpoint="/workspace/mnt/hyunji/workdirs/sam/sam_vit_h_4b8939.pth")
sam.cuda()
# SAM의 automatic mask generator
mask_generator = SamAutomaticMaskGenerator(sam)
brightness = 0.1
blur = 2
# 입력 이미지에 존재하는 모든 object의 마스크 획득
masks = mask_generator.generate(image)
def expand2square(image):
height, width, channel = image.shape
if width == height:
return image
elif width > height:
dif = width - height
image = np.pad(image, ((dif//2, dif//2), (0,0), (0,0)), 'constant', constant_values=0)
return image
else:
dif = height - width
image = np.pad(image, ((0,0), (dif//2, dif//2), (0,0)), 'constant', constant_values=0)
return image
for i in range(len(masks)):
mask_b = np.asarray(masks[i]["segmentation"], dtype="uint8")
w, h, x, y = masks[i]["bbox"]
image = np.array(image).astype(np.float64)
_, h, w = image.shape
image_b = image * brightness # 밝기 조절
img_bl = torch.from_numpy(cv2.GaussianBlur(image_b, (15, 15), blur))
mask_b = torch.tensor(mask_b)
mask_b = mask_b.expand(3, h, w).permute(1,2,0)
image = torch.tensor(image)
img_inp = image * mask_b + img_bl * (1-mask_b)
result_crop = img_inp[h:h+y, w:w+x]
result_crop = expand2square(result_crop) # 정사각형 모양으로 패치 사이즈를 맞춤
result_crop = np.array(result_crop, dtype=np.uint8)
result_crop = Image.fromarray(result_crop)
그렇게 위와 같은 패치를 생성할 수 있었다. 이를 LLaVA의 입력으로 주었더니 확연히 좋아진 결과를 확인할 수 있었다.
# 노란색 강아지 모양 피규어를 LLaVA의 입력으로 주었을 때의 output ("text")
{"question_id": 1, "prompt": "Please look carefully at the image with background masked and tell the foreground object.", "text": "The foreground object is a yellow cartoon character head, which is a toy or a plastic model of a character from the show \"Pokemon.\"", "answer_id": "ATBm2M9y8vUcR2Dq7UTufN", "model_id": "llava-v1.5-7b", "metadata": {}}
{"question_id": 2, "prompt": "Please describe that object with nouns or phrases. Please start with 'A '.", "text": "A yellow cartoon character head.", "answer_id": "aYANzdLVgAnbJn5VTMsLmH", "model_id": "llava-v1.5-7b", "metadata": {}}
{"question_id": 3, "prompt": "Please describe that object with three different ways with nouns or phrases.", "text": "1. A yellow cartoon character head.\n2. A yellow plastic head with a face.\n3. A yellow cartoon character head with a face and legs.", "answer_id": "QmQLejjaCy8xoYNh8KPt8u", "model_id": "llava-v1.5-7b", "metadata": {}}
# 파란색 코끼리 모양 피규어를 LLaVA의 입력으로 주었을 때의 output ("text")
{"question_id": 1, "prompt": "Please look carefully at the image with background masked and tell the foreground object.", "text": "The foreground object is a blue elephant figurine.", "answer_id": "JuwffGJvxTdfaQE54cuC5X", "model_id": "llava-v1.5-7b", "metadata": {}}
{"question_id": 2, "prompt": "Please describe that object with nouns or phrases. Please start with 'A '.", "text": "A blue elephant figurine.", "answer_id": "LdcauSAouyutJTLbrEUnwL", "model_id": "llava-v1.5-7b", "metadata": {}}
{"question_id": 3, "prompt": "Please describe that object with three different ways with nouns or phrases.", "text": "1. Toy: A blue elephant figurine, possibly made of plastic, with a hole in its head and a patterned design.\n2. Decoration: A blue elephant decoration, possibly made of plastic, with a hole in its head and a patterned design.\n3. Toy: A blue elephant toy, possibly made of plastic, with a hole in its head and a patterned design.", "answer_id": "6o9STq4Bs3WHMrzDAYcoP3", "model_id": "llava-v1.5-7b", "metadata": {}}
이렇게 나의 의도대로 이미지 내의 모든 물체에 대한 텍스트를 생성할 수 있었다. 이제 이 텍스트들을 BERT를 통해 embedding하여 feature GT를 생성해볼 예정이다. 이에 대한 내용은 다음 포스트에 작성하겠다.
'프로젝트' 카테고리의 다른 글
[논문 발전시키기] #3. BERT, SBERT의 last hidden state 로 이것저것 (0) | 2025.02.19 |
---|---|
[논문 발전시키기] #1. 주제 잡기: Open-Vocabulary 3D segmentation using textual semantics (0) | 2025.02.10 |
LLaMa 3.1 fine tuning 해서 챗봇 만들기 (1) | 2025.02.05 |