작성
·
237
0
안녕하세요 무더위 건강 잘 챙기시길 바랍니다.
저는 직접 깃허브에 있는 코드로 구현 하고 있는 중입니다만 512*512를 인풋으로 넣어서 Neck까지 통과한 결과
P3, P4, P5, P6, P7이 각각 (1, 128, 128, 64) (1, 64, 64, 64) (1, 32, 32, 64) (1, 16, 16, 64) (1, 8, 8, 64)로 나왔고 각 셀에 9개 앵커박스를 할당해 boxnet을 통과시켜 concat하면 128*128*9 +64*64*9 +32*32*9 + 16*16*9 +8*8*9 = 196,416
(1, 196416, 4) 의 결과값을 얻었는데 서론이 너무 길었네요ㅜㅜ
Train시에 원본 이미지와 그에 따른 Annotation 파일에 BBox의 x, y, w, h 좌표가 있을 때 이 데이터가 피처맵들에 맞는 데이터로 변환이 되어서(?) 위에서 구한 결과값과 어떻게 비교가 되어서 학습이 될지 궁금합니다.
직관적인 제 생각으로는 만약 원본 이미지에 (10,10) 좌표에 바운딩박스가 있다면 반으로 줄인 피처맵에는 대략적으로 (5,5) 좌표에 박스가 위치하지 않을까 하는데 맞는지 궁금합니다
혹시 https://github.com/xuannianz/EfficientDet/tree/030fb7e10ab69a297c7723120c2d1be856a852c0 여기 코드에 그런 내용이 있다면 언급해주시면 정말 감사하겠습니다!
바쁘실텐데 귀찮게 해드려서 죄송합니다만 답변 부탁드립니다
답변 2
0
자세한 설명 감사드립니다!
추가적으로 말씀해주신 layers.py에서 bbox_transform_inv() 부분이 잘 모르겠어서 설명 한 번 부탁드립니다!
def bbox_transform_inv(boxes, deltas, scale_factors=None):
cxa = (boxes[..., 0] + boxes[..., 2]) / 2
cya = (boxes[..., 1] + boxes[..., 3]) / 2
wa = boxes[..., 2] - boxes[..., 0]
ha = boxes[..., 3] - boxes[..., 1]
ty, tx, th, tw = deltas[..., 0], deltas[..., 1], deltas[..., 2], deltas[..., 3]
if scale_factors:
ty *= scale_factors[0]
tx *= scale_factors[1]
th *= scale_factors[2]
tw *= scale_factors[3]
w = tf.exp(tw) * wa
h = tf.exp(th) * ha
cy = ty * ha + cya
cx = tx * wa + cxa
ymin = cy - h / 2.
xmin = cx - w / 2.
ymax = cy + h / 2.
xmax = cx + w / 2.
return tf.stack([xmin, ymin, xmax, ymax], axis=-1)
이 부분이 제가 보기엔 수업 때 알려주신 BBox Regression과 유사해 보여서요. 각 head layer에서 feature map 별 grid 형태로 좌표를 정하는 것 같고, <- 이 말씀이 bbox좌표들을 개별 feature map 의 grid 형태에 따른 좌표로 변환해준다는 것으로 해석하면 될까요??
마지막으로 하나만 더 질문드립니다 common.py에서 def preprocess_group_entry(self, image, annotations): 여기서 annotation을 scale 값으로 조정하는 것 외에 피처맵에 따른 annotation 조정은 찾기 어려운 것 같아서 혹시 어떤 함수들을 조합하는건지 알려주실 수 있으신가요?
제가 코드보는게 익숙치 않아서 ㅠㅠ 제 역량으로는 알기 힘들어서 이렇게 부탁드려요!
0
안녕하십니까,
지난번 올리신 질문과 이어지는 질문 같군요.
Train시에 원본 이미지와 그에 따른 Annotation 파일에 BBox의 x, y, w, h 좌표가 있을 때 이 데이터가 피처맵들에 맞는 데이터로 변환이 되어서(?) 위에서 구한 결과값과 어떻게 비교가 되어서 학습이 될지 궁금합니다.
직관적인 제 생각으로는 만약 원본 이미지에 (10,10) 좌표에 바운딩박스가 있다면 반으로 줄인 피처맵에는 대략적으로 (5,5) 좌표에 박스가 위치하지 않을까 하는데 맞는지 궁금합니다
=> 음, 직관적으로는 그렇게 매핑이 될 수 있습니다. 실제 매핑은 좀 더 복잡하긴 합니다.
보통 Head 추출되기 이전에 layer의 크기에 맞춰서 grid 형태로 좌표를 정한 다음에 여기를 기준으로 ground truth 좌표값을 매핑합니다. Head 추출이전에 feature map이 여러개 이기 때문에 매핑을 보다 편리하게 하기 위해서 정규화 값으로 0~1 사이로 변환하는 로직을 적용하는게 일반적입니다. 그래서 이렇게 변환된 값과 위에서 concat한 값을 비교하여 loss를 적용하여 학습 시킵니다.
보통은 모델을 만들때 grid 크기에 맞춰서 head를 만드는데, 보내주신 github 소스는 무척 깔끔하군요.
https://github.com/xuannianz/EfficientDet/blob/030fb7e10ab69a297c7723120c2d1be856a852c0/model.py 의 445 line에 fpn_features 여러개에 box_net만 붙여서 head layer들을 만들었고,
regression = [box_net([feature, i]) for i, feature in enumerate(fpn_features)]
그리고 https://github.com/xuannianz/EfficientDet/blob/master/layers.py 에서 bbox_transform_inv() 를 활용해서 각 head layer에서 feature map 별 grid 형태로 좌표를 정하는 것 같고,
ground truth annotation을 grid 크기에 맞춰서 입력해 주는 부분은 https://github.com/xuannianz/EfficientDet/blob/master/generators/common.py 의 여러 함수들을 활용해서 작업하는 것 같습니다.
훌륭한 소스 코드군요. 저도 나중에 시간이 나는대로 소스코드를 함 뜯어봐야 겠습니다.