# Pytorch & Fast API & Huggingface
#### 0. DETR에 대해서
- 논문 링크: https://arxiv.org/pdf/2005.12872.pdf
- 논문 해석(한글): https://www.youtube.com/watch?v=hCWUTvVrG7E
- Baseline:
- DETR R50: https://dl.fbaipublicfiles.com/detr/detr-r50-e632da11.pth
- DETR R101: https://dl.fbaipublicfiles.com/detr/detr-r101-2c7b67e5.pth
- 성능 비교

#### 1. Torch Hub
- Dependency
```
pip install torch
pip install scipy
```
- Load Pretrained State for transfer learning
```
import torch
state = torch.hub.load_state_dict_from_url('https://dl.fbaipublicfiles.com/detr/detr-r50-e632da11.pth', map_location='cpu', check_hash=True)
model = custom_class.load_state_dict(state) # 직접 만든 모델 레이어에 state load
```
- Load Pretrained Model
```
import torch
model = torch.hub.load('facebookresearch/detr:main', 'detr_resnet50', pretrained=True)
```
#### 2. Hugging Face
##### 1. Code Lab에서 Pretrained 된 모델 로드
- Dependency
```
!pip install transformers
!pip install timm
```
- Load Pretrained Model
```
from transformers import DetrFeatureExtractor, DetrForObjectDetection
feature_extractor = DetrFeatureExtractor.from_pretrained('facebook/detr-resnet-50')
model = DetrForObjectDetection.from_pretrained('facebook/detr-resnet-50')
```
- Load Sample Image
```
from PIL import Image
import requests
url = 'https://drive.google.com/uc?export=download&id=1satnK-pt3PzOOKypkPd9MDUUXbkjs5ra'
image = Image.open(requests.get(url, stream=True).raw)
```
- Feature Extraction
```
inputs = feature_extractor(images=image, return_tensors="pt")
outputs = model(**inputs)
# model predicts bounding boxes and corresponding COCO classes
logits = outputs.logits
bboxes = outputs.pred_boxes
```
- Softmax
```
import torch
# keep only predictions of queries with 0.9+ confidence (excluding no-object class)
probas = outputs.logits.softmax(-1)[0, :, :-1]
keep = probas.max(-1).values > 0.9
# rescale bounding boxes
target_sizes = torch.tensor(image.size[::-1]).unsqueeze(0)
postprocessed_outputs = feature_extractor.post_process(outputs, target_sizes)
bboxes_scaled = postprocessed_outputs[0]['boxes'][keep]
bboxes_scaled.shape[0] # Box 갯수
```
- Count Object
```
def count_object(object_category):
count = 0
for p in probas[keep]:
cl = p.argmax()
if model.config.id2label[cl.item()] == object_category:
count = count + 1
print(count)
count_object('car') # detect된 object 중 car 갯수
```
- Plot
```
import matplotlib.pyplot as plt
# colors for visualization
COLORS = [[0.000, 0.447, 0.741], [0.850, 0.325, 0.098], [0.929, 0.694, 0.125],
[0.494, 0.184, 0.556], [0.466, 0.674, 0.188], [0.301, 0.745, 0.933]]
def plot_results(pil_img, prob, boxes):
plt.figure(figsize=(16,10))
plt.imshow(pil_img)
ax = plt.gca()
colors = COLORS * 100
for p, (xmin, ymin, xmax, ymax), c in zip(prob, boxes.tolist(), colors):
ax.add_patch(plt.Rectangle((xmin, ymin), xmax - xmin, ymax - ymin,
fill=False, color=c, linewidth=3))
cl = p.argmax()
text = f'{model.config.id2label[cl.item()]}: {p[cl]:0.2f}'
ax.text(xmin, ymin, text, fontsize=15,
bbox=dict(facecolor='yellow', alpha=0.5))
plt.axis('off')
plt.show()
plot_results(image, probas[keep], bboxes_scaled)
```
일산 주차장1

일산 주차장2

##### 2 PyCharm Local 머신에서 Pretrained 된 모델 로드
- Dependency
- Transformer 기반 모델을 사용하기 위한 필수 dependency
```
pip install transformers --file requirements.txt
pip install timm --file requirements.txt
```
- 원하는 Torch 버전 선택 [PyTorch Site](https://pytorch.org/get-started/locally/)
```
# 위에서 생성된 스크립트로 pytorch 설치
conda install pytorch torchvision torchaudio -c pytorch --file requirements.txt
```
- Environment 셋팅
- 프로젝트 생성시 Interpreter 설정

- 위에서 생성한 conda python을 Interpreter로 적용

- Code
- Class 선언
```
from transformers import DetrFeatureExtractor, DetrForObjectDetection
from PIL import Image
import requests
import torch
class CarCounterModel:
def __init__(self):
self.feature_extractor = DetrFeatureExtractor.from_pretrained('facebook/detr-resnet-50')
self.model = DetrForObjectDetection.from_pretrained('facebook/detr-resnet-50')
print('model loaded')
@staticmethod
def load_image(url):
image = Image.open(requests.get(url=url, stream=True).raw)
print('image size: ', image.size)
return image
def feature_extraction(self, image):
inputs = self.feature_extractor(images=image, return_tensors="pt")
return self.model(**inputs)
def softmax(self, image, outputs):
probas = outputs.logits.softmax(-1)[0, :, :-1]
keep = probas.max(-1).values > 0.9
target_sizes = torch.tensor(image.size[::-1]).unsqueeze(0)
postprocessed_outputs = self.feature_extractor.post_process(outputs, target_sizes)
bboxes_scaled = postprocessed_outputs[0]['boxes'][keep]
print('total detected object count: ', bboxes_scaled.shape[0])
return probas, keep, bboxes_scaled
def count_object(self, probas_keep, category='car'):
count = 0
for p in probas_keep:
cl = p.argmax()
if self.model.config.id2label[cl.item()] == category:
count = count + 1
print('total ', category, ' count: ', count)
```
- 실행
```
model = CarCounterModel()
url = 'https://drive.google.com/uc?export=download&id=1eC2ENVGBSyi04b_UAIryU6X8iTMdgzEh'
loaded_image = model.load_image(url)
features = model.feature_extraction(loaded_image)
probas, keep, bboxes = model.softmax(loaded_image, features)
model.count_object(probas[keep])
```
- 결과
```
model loaded
image size: (4032, 3024)
total detected object count: 4
total car count: 4
```
#### 2. Fast API 적용
- Dependency
```
pip install "fastapi[all] --file requirements.tst"
conda install -c conda-forge config --file requirements.txt
```
- 실행
```
uvicorn app:app --reload
```
- Code
```
from fastapi import FastAPI, File, UploadFile
from interface.image_url_interface import ImageUrlInterface
from model import CarCounterModel
app = FastAPI()
model = CarCounterModel()
@app.get("/health")
async def health_check():
return {
'status': 'ok'
}
@app.post("/url")
async def detect_from_image_link(request_body: ImageUrlInterface):
if len(request_body.url) == 0:
return 'invalid url'
loaded_image = model.load_image(request_body.url)
features = model.feature_extraction(loaded_image)
probas, keep, bboxes = model.softmax(loaded_image, features)
count = model.count_object(probas[keep], 'car')
return {
'total object count': bboxes.shape[0],
'car count': count
}
@app.post("/file")
async def detect_from_image_file(file: UploadFile = File()):
loaded_image = await model.load_image_file(file)
features = model.feature_extraction(loaded_image)
probas, keep, bboxes = model.softmax(loaded_image, features)
count = model.count_object(probas[keep], 'car')
return {
'total object count': bboxes.shape[0],
'car count': count
}
```
