dk - edit

This commit is contained in:
2026-06-29 17:59:06 +09:00
parent a3bbf78ea2
commit 71b3c21f28
2 changed files with 50 additions and 174 deletions
+38 -168
View File
@@ -1,181 +1,51 @@
# Person-Attribute-Recognition-MarketDuke
A simple baseline implemented in PyTorch for **pedestrian attribute recognition** task, evaluating on Market-1501-attribute and DukeMTMC-reID-attribute dataset.
# Person Attribute Recognition
## Dataset
You can get [Market-1501-attribute](https://github.com/vana77/Market-1501_Attribute) and [DukeMTMC-reID-attribute](https://github.com/vana77/DukeMTMC-attribute) annotations from [here](https://github.com/vana77). Also you need to download Market-1501 and DukeMTMC-reID dataset.
COCO80 기반 **YOLO26m** 객체 탐지 결과를 받아, 탐지된 **Person** 영역의 상세 속성을 분석하는 ClearML Agent입니다.
Then, create a folder named 'attribute' under your dataset path, and put corresponding annotations into the folder.
## 역할
For example,<br>
```
├── dataset
│ ├── DukeMTMC-reID
│ ├── bounding_box_test
│ ├── bounding_box_train
│ ├── query
│ ├── attribute
│ ├── duke_attribute.mat
1. YOLO26m이 COCO80 클래스로 이미지를 분석하고 Person의 바운딩 박스(`xywh`)를 전달
2. 해당 영역을 크롭한 뒤 보행자 속성 인식 모델로 상세 속성 추론
3. 결과를 ClearML 아티팩트로 업로드
## 입력 / 출력
| 항목 | 설명 |
|------|------|
| `--image_url` | 분석할 이미지 URL 또는 로컬 경로 |
| `--xywh` | Person 바운딩 박스 (`x,y,w,h`) — YOLO26m 탐지 결과 |
| 출력 | 성별, 연령대, 의류 색상·종류 등 속성 목록 (`final_result` 아티팩트) |
## 실행
```bash
python main.py \
--image_url "https://example.com/image.jpg" \
--xywh "404,290,74,193"
```
## Model
Trained model are provided. You may download it from [Google Drive](https://drive.google.com/drive/folders/1JTdjuEbxSLypnfUzVuuxLj1uSKAacfd0?usp=sharing) or [Baidu Drive](https://pan.baidu.com/s/1bByCxZp9bSs8YYZPbuK21A) (提取码:jpks).
## 요구 사항
You may download it and move `checkpoints` folder to your project's root directory.
- Python 3.11+
- PyTorch, torchvision, ClearML, requests
- 사전 학습 체크포인트: `checkpoints/market/resnet50_nfc/net_last.pth`
## Dependencies
* Python 3.5
* PyTorch >= 0.4.1
* torchvision >= 0.2.1
* matplotlib, sklearn, prettytable (optional)
### 설치
## Usage
```
python3 train.py --data-path ~/dataset --dataset [market | duke] --model resnet50 [--use-id]
python3 test.py --data-path ~/dataset --dataset [market | duke] --model resnet50 [--print-table]
python3 inference.py test_sample/test_market.jpg [--dataset market] [--model resnet50]
```bash
uv sync
# 또는
pip install -r requirements.txt
```
## Result
## ClearML
We use **binary classification** settings (considered each attribute as an independent binary classification problem), and the classification threshold is **0.5**.
| 항목 | 값 |
|------|-----|
| Project | `Person_Attribute_Recognition` |
| Task | `model-yolo-person-classify` |
***Note that the precision, recall and f1 score are denoted as '-' for some ill-defined cases.***
## 모델
### Market-1501 gallery
```
+------------+----------+-----------+--------+----------+
| attribute | accuracy | precision | recall | f1 score |
+------------+----------+-----------+--------+----------+
| young | 0.998 | 0.533 | 0.267 | 0.356 |
| teenager | 0.892 | 0.927 | 0.951 | 0.939 |
| adult | 0.895 | 0.582 | 0.450 | 0.508 |
| old | 0.992 | 0.037 | 0.012 | 0.019 |
| backpack | 0.883 | 0.828 | 0.672 | 0.742 |
| bag | 0.790 | 0.608 | 0.378 | 0.467 |
| handbag | 0.893 | 0.254 | 0.065 | 0.104 |
| clothes | 0.946 | 0.956 | 0.984 | 0.970 |
| down | 0.945 | 0.968 | 0.949 | 0.959 |
| up | 0.936 | 0.938 | 0.998 | 0.967 |
| hair | 0.877 | 0.871 | 0.773 | 0.819 |
| hat | 0.982 | 0.812 | 0.505 | 0.623 |
| gender | 0.919 | 0.947 | 0.864 | 0.903 |
| upblack | 0.954 | 0.859 | 0.790 | 0.823 |
| upwhite | 0.926 | 0.846 | 0.882 | 0.863 |
| upred | 0.974 | 0.904 | 0.840 | 0.871 |
| uppurple | 0.985 | 0.703 | 0.815 | 0.755 |
| upyellow | 0.976 | 0.895 | 0.836 | 0.865 |
| upgray | 0.909 | 0.852 | 0.391 | 0.537 |
| upblue | 0.946 | 0.868 | 0.420 | 0.566 |
| upgreen | 0.966 | 0.790 | 0.713 | 0.750 |
| downblack | 0.879 | 0.815 | 0.889 | 0.850 |
| downwhite | 0.956 | 0.608 | 0.550 | 0.578 |
| downpink | 0.989 | 0.795 | 0.782 | 0.788 |
| downpurple | 1.000 | - | - | - |
| downyellow | 0.999 | 0.000 | 0.000 | 0.000 |
| downgray | 0.878 | 0.756 | 0.443 | 0.559 |
| downblue | 0.861 | 0.762 | 0.446 | 0.563 |
| downgreen | 0.978 | 0.766 | 0.295 | 0.426 |
| downbrown | 0.958 | 0.754 | 0.590 | 0.662 |
+------------+----------+-----------+--------+----------+
Average accuracy: 0.9361
Average f1 score: 0.6492
```
### DukeMTMC-ReID gallery
```
+-----------+----------+-----------+--------+----------+
| attribute | accuracy | precision | recall | f1 score |
+-----------+----------+-----------+--------+----------+
| backpack | 0.829 | 0.794 | 0.926 | 0.855 |
| bag | 0.836 | 0.496 | 0.287 | 0.364 |
| handbag | 0.935 | 0.469 | 0.073 | 0.126 |
| boots | 0.905 | 0.784 | 0.791 | 0.787 |
| gender | 0.858 | 0.806 | 0.828 | 0.817 |
| hat | 0.898 | 0.883 | 0.680 | 0.768 |
| shoes | 0.916 | 0.756 | 0.414 | 0.535 |
| top | 0.893 | 0.590 | 0.381 | 0.463 |
| upblack | 0.821 | 0.827 | 0.903 | 0.864 |
| upwhite | 0.959 | 0.750 | 0.509 | 0.606 |
| upred | 0.973 | 0.745 | 0.649 | 0.694 |
| uppurple | 0.995 | 0.258 | 0.123 | 0.167 |
| upgray | 0.900 | 0.611 | 0.333 | 0.432 |
| upblue | 0.943 | 0.766 | 0.519 | 0.619 |
| upgreen | 0.975 | 0.463 | 0.403 | 0.431 |
| upbrown | 0.980 | 0.481 | 0.328 | 0.390 |
| downblack | 0.787 | 0.740 | 0.807 | 0.772 |
| downwhite | 0.945 | 0.771 | 0.395 | 0.522 |
| downred | 0.991 | 0.739 | 0.645 | 0.689 |
| downgray | 0.927 | 0.471 | 0.238 | 0.317 |
| downblue | 0.807 | 0.741 | 0.669 | 0.703 |
| downgreen | 0.997 | - | - | - |
| downbrown | 0.979 | 0.871 | 0.594 | 0.706 |
+-----------+----------+-----------+--------+----------+
Average accuracy: 0.9152
Average f1 score: 0.5739
```
### Inference
```
>> python inference.py test_sample/test_market.jpg --dataset market
age: teenager
carrying backpack: no
carrying bag: no
carrying handbag: no
type of lower-body clothing: dress
length of lower-body clothing: short
sleeve length: short sleeve
hair length: long hair
wearing hat: no
gender: female
color of upper-body clothing: white
color of lower-body clothing: white
>> python inference.py test_sample/test_duke.jpg --dataset duke
carrying backpack: no
carrying bag: yes
carrying handbag: no
wearing boots: no
gender: male
wearing hat: no
color of shoes: dark
length of upper-body clothing: short upper body clothing
color of upper-body clothing: black
color of lower-body clothing: blue
```
## Update
*20-06-03: Added **identity loss** for joint optimization; Adjusted the learning rate for better performace.*
*20-06-03: Updated **test.py**, settled the issue of ill-defined metrics.*
*19-09-16: Updated **inference.py**, fixed the error caused by missing data-transform.*
*19-09-06: Updated **test.py**, added **F1 score** for evaluating.*
*19-09-03: Added **inference.py**, thanks @ViswanathaReddyGajjala.*
*19-08-23: Released trained models.*
*19-01-09: Fixed the error caused by an update of market and duke attribute dataset.*
## FAQ
### 1. Why attribute order in import_Market1501Attribute.py is different for train and test data?
The label order in import_Market1501Attribute.py is consistent with the attribute order of the dataset.
You can load market_attribute.mat in MATLAB and print "market_attribute.train" or "market_attribute.test" to obtain these orders.
### 2. Why predictions in the Market-1501 dataset have 30 attributes instead of 27?
This repo consider attribute prediction as multiple binary classification, but some attribute have more than two categories.
For example, attribute 'age' in Market-1501 has four categories: young(1), teenager(2), adult(3), old(4). So it can be split into four attributes: 'young', 'teenager', 'adult' and 'old'.
That's why preds of Market-1501 has 30 attributes.
## Reference
*[1] Lin Y, Zheng L, Zheng Z, et al. Improving person re-identification by attribute and identity learning[J]. Pattern Recognition, 2019.*
- **탐지**: YOLO26m (COCO80)
- **속성 인식**: ResNet50 + NFC (Market-1501 Attribute, 기본값)
+10 -4
View File
@@ -19,10 +19,16 @@ transforms = T.Compose([
T.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
])
task = Task.init(
def init_acai_task(output):
task = Task.init(
project_name="Person_Attribute_Recognition",
task_name="model-yolo-person-classify"
)
)
result_data = {"output": output, "status": "PASS"}
task.upload_artifact(name="final_result", artifact_object=result_data)
class PredictDecoder(object):
@@ -103,8 +109,8 @@ def main(image, dataset='market', backbone='resnet50', use_id=False):
print(f'{name}: {value}')
print("=" * 50)
result_data = {"results": results, "status": "PASS"}
task.upload_artifact(name="final_result", artifact_object=result_data)
init_acai_task(results)
if __name__ == "__main__":