parent
19f5c68ac4
commit
2839a55803
@ -1,127 +0,0 @@
|
||||
import argparse
|
||||
import os
|
||||
import cv2
|
||||
import numpy as np
|
||||
import onnxruntime
|
||||
from paddleocr.ppocr.data.imaug.operators import (
|
||||
E2EResizeForTest, KeepKeys, NormalizeImage, ToCHWImage
|
||||
)
|
||||
# from ppocr.data.imaug.operators import (
|
||||
# E2EResizeForTest, KeepKeys, NormalizeImage, ToCHWImage
|
||||
# )
|
||||
from paddleocr.ppocr.postprocess.pg_postprocess import PGPostProcess
|
||||
# from ppocr.postprocess.pg_postprocess import PGPostProcess
|
||||
from pgnet.chr_dct import chr_dct_list
|
||||
|
||||
|
||||
class PGNetPredictor:
|
||||
def __init__(self, model_path, cpu=False):
|
||||
self.model_path = model_path
|
||||
self.dict_path = "ic15_dict.txt"
|
||||
|
||||
if not os.path.exists(self.dict_path):
|
||||
with open(self.dict_path, "w") as f:
|
||||
f.writelines(chr_dct_list)
|
||||
|
||||
providers = ["CPUExecutionProvider"] if cpu else ["CUDAExecutionProvider"]
|
||||
self.sess = onnxruntime.InferenceSession(model_path, providers=providers)
|
||||
|
||||
self.transforms = [
|
||||
E2EResizeForTest(max_side_len=768, valid_set="totaltext"),
|
||||
NormalizeImage(scale=1/255.0, mean=[0.485,0.456,0.406],
|
||||
std=[0.229,0.224,0.225], order="hwc"),
|
||||
ToCHWImage(),
|
||||
KeepKeys(keep_keys=["image", "shape"]),
|
||||
]
|
||||
|
||||
self.pgpostprocess = PGPostProcess(
|
||||
character_dict_path=self.dict_path,
|
||||
valid_set="totaltext",
|
||||
score_thresh=0.5,
|
||||
mode="fast",
|
||||
)
|
||||
|
||||
def preprocess(self, img):
|
||||
self.ori_im = img.copy()
|
||||
data = {"image": img}
|
||||
|
||||
for transform in self.transforms:
|
||||
data = transform(data)
|
||||
|
||||
img, shape_list = data
|
||||
return np.expand_dims(img, axis=0), np.expand_dims(shape_list, axis=0)
|
||||
|
||||
def predict(self, img):
|
||||
ort_inputs = {self.sess.get_inputs()[0].name: img}
|
||||
outputs = self.sess.run(None, ort_inputs)
|
||||
|
||||
return {
|
||||
"f_border": outputs[0],
|
||||
"f_char": outputs[1],
|
||||
"f_direction": outputs[2],
|
||||
"f_score": outputs[3],
|
||||
}
|
||||
|
||||
def clip_boxes(self, boxes, shape):
|
||||
h, w = shape[:2]
|
||||
clipped = []
|
||||
for box in boxes:
|
||||
box[:, 0] = np.clip(box[:, 0], 0, w - 1)
|
||||
box[:, 1] = np.clip(box[:, 1], 0, h - 1)
|
||||
clipped.append(box)
|
||||
return np.array(clipped)
|
||||
|
||||
def postprocess(self, preds, shape_list):
|
||||
result = self.pgpostprocess(preds, shape_list)
|
||||
pts, texts = result["points"], result["texts"]
|
||||
return self.clip_boxes(pts, self.ori_im.shape), texts
|
||||
|
||||
def infer(self, img):
|
||||
img_input, shape = self.preprocess(img)
|
||||
preds = self.predict(img_input)
|
||||
return self.postprocess(preds, shape)
|
||||
|
||||
|
||||
def draw_results(frame, boxes, texts):
|
||||
for box, text in zip(boxes, texts):
|
||||
box = box.astype(int).reshape(-1, 1, 2)
|
||||
cv2.polylines(frame, [box], True, (255,255,0), 2)
|
||||
cv2.putText(frame, text, tuple(box[0][0]), cv2.FONT_HERSHEY_SIMPLEX,
|
||||
0.7, (0,255,0), 2)
|
||||
return frame
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(description="PGNet Video OCR")
|
||||
parser.add_argument("--model", type=str, required=True)
|
||||
parser.add_argument("--video", type=str, required=True)
|
||||
parser.add_argument("--cpu", action="store_true")
|
||||
args = parser.parse_args()
|
||||
|
||||
predictor = PGNetPredictor(args.model, args.cpu)
|
||||
|
||||
cap = cv2.VideoCapture(args.video)
|
||||
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
|
||||
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
|
||||
fps = cap.get(cv2.CAP_PROP_FPS)
|
||||
|
||||
out_name = os.path.splitext(os.path.basename(args.video))[0] + "_pgnet_output.mp4"
|
||||
out_path = os.path.join(os.path.dirname(args.video), out_name)
|
||||
|
||||
writer = cv2.VideoWriter(out_path, cv2.VideoWriter_fourcc(*"mp4v"), fps, (width, height))
|
||||
|
||||
print(f"▶ Processing video... (Output: {out_path})")
|
||||
|
||||
while True:
|
||||
ret, frame = cap.read()
|
||||
if not ret:
|
||||
break
|
||||
|
||||
boxes, texts = predictor.infer(frame)
|
||||
frame = draw_results(frame, boxes, texts)
|
||||
writer.write(frame)
|
||||
|
||||
cap.release()
|
||||
writer.release()
|
||||
|
||||
print("🎉 Done! Video saved:", out_path)
|
||||
@ -1,39 +0,0 @@
|
||||
import torch
|
||||
from torchvision import datasets, transforms
|
||||
from torch.utils.data import DataLoader
|
||||
import os
|
||||
|
||||
def get_face_dataloaders(data_dir, batch_size=64, num_workers=4):
|
||||
"""
|
||||
Input: data_dir (e.g., ~/face_exp/datasets)
|
||||
Structure assumed: data_dir/CASIA-WebFace/ID/images.jpg
|
||||
"""
|
||||
|
||||
# 1. Train Transform (Augmentation + Resize to 128x128)
|
||||
train_transform = transforms.Compose([
|
||||
transforms.Resize((128, 128), interpolation=transforms.InterpolationMode.BICUBIC),
|
||||
transforms.RandomHorizontalFlip(p=0.5),
|
||||
transforms.ColorJitter(brightness=0.1, contrast=0.1, saturation=0.1),
|
||||
transforms.ToTensor(),
|
||||
transforms.Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5])
|
||||
])
|
||||
|
||||
# 2. Path Setup
|
||||
train_dir = os.path.join(data_dir, 'CASIA-WebFace')
|
||||
|
||||
if not os.path.exists(train_dir):
|
||||
raise FileNotFoundError(f"데이터셋 경로를 찾을 수 없습니다: {train_dir}\n'CASIA-WebFace' 폴더가 해당 위치에 있는지 확인해주세요.")
|
||||
|
||||
# 3. Dataset & Loader
|
||||
train_dataset = datasets.ImageFolder(root=train_dir, transform=train_transform)
|
||||
|
||||
train_loader = DataLoader(
|
||||
train_dataset,
|
||||
batch_size=batch_size,
|
||||
shuffle=True,
|
||||
num_workers=num_workers,
|
||||
pin_memory=True,
|
||||
drop_last=True
|
||||
)
|
||||
|
||||
return train_loader, len(train_dataset.classes)
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,149 +0,0 @@
|
||||
import torch
|
||||
import torch.nn as nn
|
||||
import torch.nn.functional as F
|
||||
import math
|
||||
|
||||
# --------------------------------------------------------
|
||||
# Basic Blocks (Quantization Friendly: ReLU used)
|
||||
# --------------------------------------------------------
|
||||
def conv3x3(in_planes, out_planes, stride=1):
|
||||
return nn.Conv2d(in_planes, out_planes, kernel_size=3, stride=stride,
|
||||
padding=1, bias=False)
|
||||
|
||||
class Bottleneck(nn.Module):
|
||||
expansion = 4
|
||||
|
||||
def __init__(self, inplanes, planes, stride=1, downsample=None):
|
||||
super(Bottleneck, self).__init__()
|
||||
# Kernel size restricted to 1 and 3 for board compatibility
|
||||
self.conv1 = nn.Conv2d(inplanes, planes, kernel_size=1, bias=False)
|
||||
self.bn1 = nn.BatchNorm2d(planes)
|
||||
self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=stride, padding=1, bias=False)
|
||||
self.bn2 = nn.BatchNorm2d(planes)
|
||||
self.conv3 = nn.Conv2d(planes, planes * self.expansion, kernel_size=1, bias=False)
|
||||
self.bn3 = nn.BatchNorm2d(planes * self.expansion)
|
||||
# self.relu = nn.ReLU(inplace=True) # PReLU -> ReLU
|
||||
self.relu = nn.ReLU(inplace=False) # PReLU -> ReLU
|
||||
self.downsample = downsample
|
||||
self.stride = stride
|
||||
|
||||
def forward(self, x):
|
||||
residual = x
|
||||
out = self.conv1(x)
|
||||
out = self.bn1(out)
|
||||
out = self.relu(out)
|
||||
out = self.conv2(out)
|
||||
out = self.bn2(out)
|
||||
out = self.relu(out)
|
||||
out = self.conv3(out)
|
||||
out = self.bn3(out)
|
||||
if self.downsample is not None:
|
||||
residual = self.downsample(x)
|
||||
out += residual
|
||||
out = self.relu(out)
|
||||
return out
|
||||
|
||||
# --------------------------------------------------------
|
||||
# Backbone: Modified ResNet-50
|
||||
# --------------------------------------------------------
|
||||
class ResNetFace(nn.Module):
|
||||
def __init__(self, block, layers, embedding_size=128):
|
||||
super(ResNetFace, self).__init__()
|
||||
self.inplanes = 64
|
||||
|
||||
# Stem Block: 7x7 replaced by three 3x3 convs
|
||||
self.stem = nn.Sequential(
|
||||
nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1, bias=False),
|
||||
nn.BatchNorm2d(64),
|
||||
# nn.ReLU(inplace=True),
|
||||
nn.ReLU(inplace=False),
|
||||
nn.Conv2d(64, 64, kernel_size=3, stride=1, padding=1, bias=False),
|
||||
nn.BatchNorm2d(64),
|
||||
# nn.ReLU(inplace=True),
|
||||
nn.ReLU(inplace=False),
|
||||
nn.Conv2d(64, 64, kernel_size=3, stride=2, padding=1, bias=False),
|
||||
nn.BatchNorm2d(64),
|
||||
# nn.ReLU(inplace=True),
|
||||
nn.ReLU(inplace=False),
|
||||
)
|
||||
self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)
|
||||
|
||||
self.layer1 = self._make_layer(block, 64, layers[0])
|
||||
self.layer2 = self._make_layer(block, 128, layers[1], stride=2)
|
||||
self.layer3 = self._make_layer(block, 256, layers[2], stride=2)
|
||||
self.layer4 = self._make_layer(block, 512, layers[3], stride=2)
|
||||
|
||||
# Output Head: 128x128 Input -> 4x4 Feature Map
|
||||
self.avgpool = nn.AvgPool2d(4) # Result: 1x1
|
||||
|
||||
# FC layer replaced by 1x1 Conv for 128-d embedding
|
||||
self.fc_conv = nn.Conv2d(512 * block.expansion, embedding_size, kernel_size=1, bias=False)
|
||||
self.bn_last = nn.BatchNorm2d(embedding_size)
|
||||
|
||||
# Init weights
|
||||
for m in self.modules():
|
||||
if isinstance(m, nn.Conv2d):
|
||||
nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')
|
||||
elif isinstance(m, nn.BatchNorm2d):
|
||||
nn.init.constant_(m.weight, 1)
|
||||
nn.init.constant_(m.bias, 0)
|
||||
|
||||
def _make_layer(self, block, planes, blocks, stride=1):
|
||||
downsample = None
|
||||
if stride != 1 or self.inplanes != planes * block.expansion:
|
||||
downsample = nn.Sequential(
|
||||
nn.Conv2d(self.inplanes, planes * block.expansion,
|
||||
kernel_size=1, stride=stride, bias=False),
|
||||
nn.BatchNorm2d(planes * block.expansion),
|
||||
)
|
||||
layers = []
|
||||
layers.append(block(self.inplanes, planes, stride, downsample))
|
||||
self.inplanes = planes * block.expansion
|
||||
for _ in range(1, blocks):
|
||||
layers.append(block(self.inplanes, planes))
|
||||
return nn.Sequential(*layers)
|
||||
|
||||
def forward(self, x):
|
||||
x = self.stem(x)
|
||||
x = self.maxpool(x)
|
||||
x = self.layer1(x)
|
||||
x = self.layer2(x)
|
||||
x = self.layer3(x)
|
||||
x = self.layer4(x)
|
||||
x = self.avgpool(x)
|
||||
x = self.fc_conv(x)
|
||||
x = self.bn_last(x) # Output: [N, 128, 1, 1]
|
||||
return x
|
||||
|
||||
# --------------------------------------------------------
|
||||
# ArcFace Loss Header
|
||||
# --------------------------------------------------------
|
||||
class ArcFace(nn.Module):
|
||||
def __init__(self, in_features, out_features, s=64.0, m=0.50):
|
||||
super(ArcFace, self).__init__()
|
||||
self.in_features = in_features
|
||||
self.out_features = out_features
|
||||
self.s = s
|
||||
self.m = m
|
||||
self.weight = nn.Parameter(torch.FloatTensor(out_features, in_features))
|
||||
nn.init.xavier_uniform_(self.weight)
|
||||
|
||||
def forward(self, input, label):
|
||||
# Flatten [N, 128, 1, 1] -> [N, 128] for loss calculation
|
||||
embedding = input.view(input.size(0), -1)
|
||||
|
||||
cosine = F.linear(F.normalize(embedding), F.normalize(self.weight))
|
||||
|
||||
# Stable implementation of ArcFace
|
||||
theta = torch.acos(torch.clamp(cosine, -1.0 + 1e-7, 1.0 - 1e-7))
|
||||
target_logits = torch.cos(theta + self.m)
|
||||
|
||||
one_hot = torch.zeros_like(cosine)
|
||||
one_hot.scatter_(1, label.view(-1, 1).long(), 1)
|
||||
|
||||
output = one_hot * target_logits + (1.0 - one_hot) * cosine
|
||||
output *= self.s
|
||||
return output
|
||||
|
||||
def get_face_model():
|
||||
return ResNetFace(Bottleneck, [3, 4, 6, 3], embedding_size=128)
|
||||
@ -1,120 +0,0 @@
|
||||
import torch
|
||||
import torch.nn as nn
|
||||
import torch.optim as optim
|
||||
import os
|
||||
import argparse
|
||||
from tqdm import tqdm
|
||||
from datetime import datetime # 시간 정보를 가져오기 위해 추가
|
||||
|
||||
# Import our custom modules
|
||||
from model import get_face_model, ArcFace
|
||||
from dataset import get_face_dataloaders
|
||||
|
||||
def main():
|
||||
# --------------------------------------------------------
|
||||
# 1. Hyperparameters & Settings
|
||||
# --------------------------------------------------------
|
||||
parser = argparse.ArgumentParser(description='Face Recognition Training for Apache 6')
|
||||
|
||||
# 데이터셋 경로 (사용자 환경에 맞게 기본값 설정)
|
||||
parser.add_argument('--data_dir', type=str, default='/home/cuuva/face_exp/datasets', help='Path to datasets')
|
||||
|
||||
# 결과 저장 최상위 경로 (여기 아래에 시간별 폴더가 생김)
|
||||
parser.add_argument('--project_dir', type=str, default='./results', help='Base directory for results')
|
||||
|
||||
parser.add_argument('--epochs', type=int, default=20, help='Number of epochs')
|
||||
parser.add_argument('--batch_size', type=int, default=64, help='Batch size')
|
||||
parser.add_argument('--lr', type=float, default=0.1, help='Learning rate')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
||||
print(f"Device: {device}")
|
||||
|
||||
# --------------------------------------------------------
|
||||
# [수정됨] 실험 디렉토리 생성 로직 (yy-mm-dd-hour-minute)
|
||||
# --------------------------------------------------------
|
||||
# 현재 시간 구하기
|
||||
current_time = datetime.now().strftime("%y-%m-%d-%H-%M")
|
||||
|
||||
# 최종 저장 경로: ./results/23-12-12-15-30/
|
||||
save_dir = os.path.join(args.project_dir, current_time)
|
||||
|
||||
# 폴더 생성
|
||||
os.makedirs(save_dir, exist_ok=True)
|
||||
print(f"✅ Experiment results will be saved to: {save_dir}")
|
||||
|
||||
# --------------------------------------------------------
|
||||
# 2. Load Data
|
||||
# --------------------------------------------------------
|
||||
print("Loading Data...")
|
||||
try:
|
||||
train_loader, num_classes = get_face_dataloaders(args.data_dir, args.batch_size)
|
||||
print(f"Classes (People): {num_classes}, Batch Size: {args.batch_size}")
|
||||
except Exception as e:
|
||||
print(f"❌ Error loading data: {e}")
|
||||
return
|
||||
|
||||
# --------------------------------------------------------
|
||||
# 3. Initialize Model & Loss
|
||||
# --------------------------------------------------------
|
||||
# Backbone (보드에 배포할 모델)
|
||||
backbone = get_face_model().to(device)
|
||||
|
||||
# ArcFace Header (학습용 Loss 계산기)
|
||||
metric_fc = ArcFace(in_features=128, out_features=num_classes).to(device)
|
||||
|
||||
# Loss
|
||||
criterion = nn.CrossEntropyLoss()
|
||||
|
||||
# Optimizer
|
||||
optimizer = optim.SGD([
|
||||
{'params': backbone.parameters()},
|
||||
{'params': metric_fc.parameters()}
|
||||
], lr=args.lr, momentum=0.9, weight_decay=5e-4)
|
||||
|
||||
# Scheduler
|
||||
scheduler = optim.lr_scheduler.MultiStepLR(optimizer, milestones=[8, 14, 18], gamma=0.1)
|
||||
|
||||
# --------------------------------------------------------
|
||||
# 4. Training Loop
|
||||
# --------------------------------------------------------
|
||||
print("🚀 Start Training...")
|
||||
|
||||
for epoch in range(args.epochs):
|
||||
backbone.train()
|
||||
metric_fc.train()
|
||||
|
||||
running_loss = 0.0
|
||||
pbar = tqdm(train_loader, desc=f"Epoch {epoch+1}/{args.epochs}")
|
||||
|
||||
for images, labels in pbar:
|
||||
images, labels = images.to(device), labels.to(device)
|
||||
|
||||
optimizer.zero_grad()
|
||||
|
||||
# Forward Pass
|
||||
features = backbone(images) # [N, 128, 1, 1]
|
||||
outputs = metric_fc(features, labels) # [N, Num_Classes]
|
||||
|
||||
# Loss Calc & Backward
|
||||
loss = criterion(outputs, labels)
|
||||
loss.backward()
|
||||
optimizer.step()
|
||||
|
||||
running_loss += loss.item()
|
||||
pbar.set_postfix({'loss': running_loss / (pbar.n + 1)})
|
||||
|
||||
scheduler.step()
|
||||
|
||||
# [수정됨] Save Checkpoint (.pt 확장자 사용)
|
||||
# 해당 실험 폴더(save_dir) 안에 저장됨
|
||||
save_path = os.path.join(save_dir, f"backbone_epoch_{epoch+1}.pt")
|
||||
torch.save(backbone.state_dict(), save_path)
|
||||
|
||||
# 마지막 에폭일 때 로그 출력
|
||||
if epoch == args.epochs - 1:
|
||||
print(f"🎉 Training Finished! Final model saved at: {save_path}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@ -1,119 +0,0 @@
|
||||
import torch
|
||||
import torch.nn.functional as F
|
||||
from torch.utils.data import Dataset, DataLoader
|
||||
from torchvision import transforms
|
||||
from PIL import Image
|
||||
import os
|
||||
import numpy as np
|
||||
|
||||
# --------------------------------------------------------
|
||||
# 1. LFW Dataset Loader
|
||||
# --------------------------------------------------------
|
||||
class LFWDataset(Dataset):
|
||||
def __init__(self, lfw_dir, pairs_path, transform=None):
|
||||
self.lfw_dir = lfw_dir
|
||||
self.pairs_path = pairs_path
|
||||
self.transform = transform
|
||||
self.validation_images = self.get_lfw_paths(lfw_dir)
|
||||
|
||||
def get_lfw_paths(self, lfw_dir):
|
||||
# pairs.txt 파싱하여 이미지 경로 쌍과 정답(issame) 리스트 생성
|
||||
pairs = []
|
||||
with open(self.pairs_path, 'r') as f:
|
||||
lines = f.readlines()[1:] # 첫 줄(헤더) 건너뜀
|
||||
|
||||
for line in lines:
|
||||
p = line.strip().split('\t')
|
||||
|
||||
if len(p) == 3: # 같은 사람 (name, img1_num, img2_num)
|
||||
name = p[0]
|
||||
img1 = os.path.join(lfw_dir, name, f"{name}_{int(p[1]):04d}.jpg")
|
||||
img2 = os.path.join(lfw_dir, name, f"{name}_{int(p[2]):04d}.jpg")
|
||||
issame = True
|
||||
pairs.append((img1, img2, issame))
|
||||
|
||||
elif len(p) == 4: # 다른 사람 (name1, img1_num, name2, img2_num)
|
||||
name1 = p[0]
|
||||
img1 = os.path.join(lfw_dir, name1, f"{name1}_{int(p[1]):04d}.jpg")
|
||||
name2 = p[2]
|
||||
img2 = os.path.join(lfw_dir, name2, f"{name2}_{int(p[3]):04d}.jpg")
|
||||
issame = False
|
||||
pairs.append((img1, img2, issame))
|
||||
return pairs
|
||||
|
||||
def __len__(self):
|
||||
return len(self.validation_images)
|
||||
|
||||
def __getitem__(self, index):
|
||||
img1_path, img2_path, issame = self.validation_images[index]
|
||||
|
||||
try:
|
||||
img1 = Image.open(img1_path).convert('RGB')
|
||||
img2 = Image.open(img2_path).convert('RGB')
|
||||
except Exception as e:
|
||||
# 혹시 파일이 없을 경우를 대비한 더미 (실제론 파일 확인 필요)
|
||||
print(f"File Load Error: {e}")
|
||||
img1 = Image.new('RGB', (128, 128))
|
||||
img2 = Image.new('RGB', (128, 128))
|
||||
|
||||
if self.transform:
|
||||
img1 = self.transform(img1)
|
||||
img2 = self.transform(img2)
|
||||
|
||||
return img1, img2, issame
|
||||
|
||||
# --------------------------------------------------------
|
||||
# 2. Evaluation Function
|
||||
# --------------------------------------------------------
|
||||
def validate_lfw(model, lfw_loader, device):
|
||||
model.eval()
|
||||
similarities = []
|
||||
actual_issame = []
|
||||
|
||||
print("🔍 Validating on LFW...")
|
||||
with torch.no_grad():
|
||||
for img1, img2, issame in lfw_loader:
|
||||
img1, img2 = img1.to(device), img2.to(device)
|
||||
|
||||
# Feature Extraction
|
||||
feat1 = model(img1) # [B, 128, 1, 1]
|
||||
feat2 = model(img2) # [B, 128, 1, 1]
|
||||
|
||||
# Flatten
|
||||
feat1 = feat1.view(feat1.size(0), -1)
|
||||
feat2 = feat2.view(feat2.size(0), -1)
|
||||
|
||||
# Cosine Similarity Calculation
|
||||
# 128차원 벡터의 코사인 유사도 (-1 ~ 1)
|
||||
cos_sim = F.cosine_similarity(feat1, feat2)
|
||||
|
||||
similarities.extend(cos_sim.cpu().numpy())
|
||||
actual_issame.extend(issame.numpy())
|
||||
|
||||
similarities = np.array(similarities)
|
||||
actual_issame = np.array(actual_issame)
|
||||
|
||||
# ----------------------------------------------------
|
||||
# Best Threshold Search (단순화된 버전)
|
||||
# ----------------------------------------------------
|
||||
best_acc = 0.0
|
||||
best_th = 0.0
|
||||
|
||||
# -1.0 부터 1.0 까지 0.01 단위로 Threshold를 이동하며 정확도 측정
|
||||
thresholds = np.arange(-1.0, 1.0, 0.01)
|
||||
|
||||
for th in thresholds:
|
||||
# th보다 크면 True(동일인), 작으면 False(타인) 예측
|
||||
predict_issame = np.greater(similarities, th)
|
||||
|
||||
# 정답과 비교
|
||||
true_positives = np.sum(np.logical_and(predict_issame, actual_issame))
|
||||
true_negatives = np.sum(np.logical_and(np.logical_not(predict_issame), np.logical_not(actual_issame)))
|
||||
|
||||
acc = (true_positives + true_negatives) / len(actual_issame)
|
||||
|
||||
if acc > best_acc:
|
||||
best_acc = acc
|
||||
best_th = th
|
||||
|
||||
return best_acc, best_th
|
||||
@ -1,38 +0,0 @@
|
||||
import easyocr
|
||||
import cv2
|
||||
from matplotlib import pyplot as plt
|
||||
import time # ⬅ 추가
|
||||
|
||||
# 1. EasyOCR Reader 생성
|
||||
reader = easyocr.Reader(['ko', 'en'], gpu=False)
|
||||
|
||||
# 2. 이미지 불러오기
|
||||
# image_path = '/home/cuuva/다운로드/test/ocr_resized.png'
|
||||
image_path = '/home/cuuva/experiment/custom_LP_detect/ocr2.png'
|
||||
image = cv2.imread(image_path)
|
||||
image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
|
||||
|
||||
# ------------------------
|
||||
# 3. OCR 수행 및 시간 측정
|
||||
# ------------------------
|
||||
start_time = time.time()
|
||||
results = reader.readtext(image_rgb, detail=1)
|
||||
end_time = time.time()
|
||||
print(f"Inference time: {end_time - start_time:.3f} seconds")
|
||||
|
||||
# 4. 결과 출력 및 시각화
|
||||
for (bbox, text, prob) in results:
|
||||
print(f"Detected text: {text}, Confidence: {prob:.2f}")
|
||||
|
||||
# 바운딩 박스
|
||||
top_left = tuple(map(int, bbox[0]))
|
||||
bottom_right = tuple(map(int, bbox[2]))
|
||||
cv2.rectangle(image_rgb, top_left, bottom_right, (0, 255, 0), 2)
|
||||
cv2.putText(image_rgb, text, (top_left[0], top_left[1]-10),
|
||||
cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 255), 2)
|
||||
|
||||
# 5. 시각화
|
||||
plt.figure(figsize=(10,6))
|
||||
plt.imshow(image_rgb)
|
||||
plt.axis('off')
|
||||
plt.show()
|
||||
File diff suppressed because one or more lines are too long
@ -0,0 +1,94 @@
|
||||
import os
|
||||
import glob
|
||||
from tqdm.notebook import tqdm # 주피터 노트북용 진행바
|
||||
|
||||
# ==========================================
|
||||
# 1. 절대 경로 설정 (수정된 부분)
|
||||
# ==========================================
|
||||
# 사용자 홈 디렉토리(/home/cuuva)를 포함한 전체 경로를 입력합니다.
|
||||
SRC_ROOT = '/home/cuuva/git/Detection_Experiment/datasets/fashionpedia_yolo/labels_all_bak'
|
||||
DST_ROOT = '/home/cuuva/git/Detection_Experiment/datasets/fashionpedia_yolo/labels_reduced'
|
||||
|
||||
# ==========================================
|
||||
# 2. 클래스 매핑 규칙 (Old ID -> New ID)
|
||||
# ==========================================
|
||||
# 0(shirt), 1(top), 2(sweater) -> 0 (shirt)
|
||||
# 3(cardigan), 4(jacket) -> 1 (jacket)
|
||||
# 6(pants) -> 2 (pants)
|
||||
# 13(glasses) -> 3 (glasses)
|
||||
class_mapping = {
|
||||
0: 0, 1: 0, 2: 0,
|
||||
3: 1, 4: 1,
|
||||
6: 2,
|
||||
13: 3
|
||||
}
|
||||
|
||||
print(f"원본 경로: {SRC_ROOT}")
|
||||
print(f"저장 경로: {DST_ROOT}")
|
||||
print("-" * 30)
|
||||
|
||||
# ==========================================
|
||||
# 3. 데이터 변환 로직
|
||||
# ==========================================
|
||||
def process_yolo_labels(src_root, dst_root, mapping):
|
||||
subsets = ['train', 'val']
|
||||
|
||||
total_files = 0
|
||||
total_objects_kept = 0
|
||||
|
||||
for subset in subsets:
|
||||
src_dir = os.path.join(src_root, subset)
|
||||
dst_dir = os.path.join(dst_root, subset)
|
||||
|
||||
# 소스 디렉토리 존재 확인
|
||||
if not os.path.exists(src_dir):
|
||||
print(f"⚠️ 에러: 소스 폴더를 찾을 수 없습니다 -> {src_dir}")
|
||||
continue
|
||||
|
||||
# 타겟 디렉토리 생성
|
||||
os.makedirs(dst_dir, exist_ok=True)
|
||||
|
||||
# 파일 목록 로드
|
||||
txt_files = glob.glob(os.path.join(src_dir, '*.txt'))
|
||||
total_files += len(txt_files)
|
||||
|
||||
print(f"🚀 Processing [{subset}]: {len(txt_files)} files found.")
|
||||
|
||||
# 변환 시작
|
||||
for file_path in tqdm(txt_files, desc=f"{subset} Converting"):
|
||||
file_name = os.path.basename(file_path)
|
||||
dst_path = os.path.join(dst_dir, file_name)
|
||||
|
||||
new_lines = []
|
||||
|
||||
with open(file_path, 'r') as f:
|
||||
lines = f.readlines()
|
||||
|
||||
for line in lines:
|
||||
parts = line.strip().split()
|
||||
if not parts: continue
|
||||
|
||||
old_cls = int(parts[0])
|
||||
coords = parts[1:] # x, y, w, h
|
||||
|
||||
# 매핑 규칙에 있는 클래스만 남김
|
||||
if old_cls in mapping:
|
||||
new_cls = mapping[old_cls]
|
||||
new_line = f"{new_cls} {' '.join(coords)}\n"
|
||||
new_lines.append(new_line)
|
||||
total_objects_kept += 1
|
||||
|
||||
# 파일 쓰기 (빈 파일이라도 생성하여 구조 유지)
|
||||
with open(dst_path, 'w') as f:
|
||||
f.writelines(new_lines)
|
||||
|
||||
return total_files, total_objects_kept
|
||||
|
||||
# 실행
|
||||
processed_cnt, kept_cnt = process_yolo_labels(SRC_ROOT, DST_ROOT, class_mapping)
|
||||
|
||||
print("="*30)
|
||||
print("✅ 변환 완료")
|
||||
print(f"총 처리된 파일: {processed_cnt}개")
|
||||
print(f"남은 객체 수: {kept_cnt}개")
|
||||
print(f"저장된 위치: {DST_ROOT}")
|
||||
@ -0,0 +1,106 @@
|
||||
task: detect
|
||||
mode: train
|
||||
model: yolov8m.pt
|
||||
data: /home/cuuva/git/Detection_Experiment/datasets/fashionpedia_yolo/fashionpedia_custom.yaml
|
||||
epochs: 500
|
||||
time: null
|
||||
patience: 50
|
||||
batch: -1
|
||||
imgsz: 640
|
||||
save: true
|
||||
save_period: -1
|
||||
cache: false
|
||||
device: '0'
|
||||
workers: 8
|
||||
project: fashionpedia_exp
|
||||
name: yolov8m_fashion_4class
|
||||
exist_ok: false
|
||||
pretrained: true
|
||||
optimizer: AdamW
|
||||
verbose: true
|
||||
seed: 0
|
||||
deterministic: true
|
||||
single_cls: false
|
||||
rect: false
|
||||
cos_lr: false
|
||||
close_mosaic: 10
|
||||
resume: false
|
||||
amp: true
|
||||
fraction: 1.0
|
||||
profile: false
|
||||
freeze: null
|
||||
multi_scale: false
|
||||
compile: false
|
||||
overlap_mask: true
|
||||
mask_ratio: 4
|
||||
dropout: 0.0
|
||||
val: true
|
||||
split: val
|
||||
save_json: false
|
||||
conf: null
|
||||
iou: 0.7
|
||||
max_det: 300
|
||||
half: false
|
||||
dnn: false
|
||||
plots: true
|
||||
source: null
|
||||
vid_stride: 1
|
||||
stream_buffer: false
|
||||
visualize: false
|
||||
augment: false
|
||||
agnostic_nms: false
|
||||
classes: null
|
||||
retina_masks: false
|
||||
embed: null
|
||||
show: false
|
||||
save_frames: false
|
||||
save_txt: false
|
||||
save_conf: false
|
||||
save_crop: false
|
||||
show_labels: true
|
||||
show_conf: true
|
||||
show_boxes: true
|
||||
line_width: null
|
||||
format: torchscript
|
||||
keras: false
|
||||
optimize: false
|
||||
int8: false
|
||||
dynamic: false
|
||||
simplify: true
|
||||
opset: null
|
||||
workspace: null
|
||||
nms: false
|
||||
lr0: 0.001
|
||||
lrf: 0.01
|
||||
momentum: 0.937
|
||||
weight_decay: 0.0005
|
||||
warmup_epochs: 3.0
|
||||
warmup_momentum: 0.8
|
||||
warmup_bias_lr: 0.1
|
||||
box: 7.5
|
||||
cls: 0.5
|
||||
dfl: 1.5
|
||||
pose: 12.0
|
||||
kobj: 1.0
|
||||
nbs: 64
|
||||
hsv_h: 0.015
|
||||
hsv_s: 0.7
|
||||
hsv_v: 0.4
|
||||
degrees: 0.0
|
||||
translate: 0.1
|
||||
scale: 0.5
|
||||
shear: 0.0
|
||||
perspective: 0.0
|
||||
flipud: 0.0
|
||||
fliplr: 0.5
|
||||
bgr: 0.0
|
||||
mosaic: 1.0
|
||||
mixup: 0.0
|
||||
cutmix: 0.0
|
||||
copy_paste: 0.0
|
||||
copy_paste_mode: flip
|
||||
auto_augment: randaugment
|
||||
erasing: 0.4
|
||||
cfg: null
|
||||
tracker: botsort.yaml
|
||||
save_dir: /home/cuuva/git/Detection_Experiment/fashion_yolo/fashionpedia_exp/yolov8m_fashion_4class
|
||||
|
@ -0,0 +1,106 @@
|
||||
task: detect
|
||||
mode: train
|
||||
model: yolov8m.pt
|
||||
data: /home/cuuva/git/Detection_Experiment/fashion_yolo/finetuning_exp/finetuning_dataset.yaml
|
||||
epochs: 200
|
||||
time: null
|
||||
patience: 50
|
||||
batch: -1
|
||||
imgsz: 640
|
||||
save: true
|
||||
save_period: -1
|
||||
cache: false
|
||||
device: '0'
|
||||
workers: 8
|
||||
project: finetuned_exp
|
||||
name: yolov8m_finetuned_16class
|
||||
exist_ok: false
|
||||
pretrained: true
|
||||
optimizer: AdamW
|
||||
verbose: true
|
||||
seed: 0
|
||||
deterministic: true
|
||||
single_cls: false
|
||||
rect: false
|
||||
cos_lr: false
|
||||
close_mosaic: 10
|
||||
resume: false
|
||||
amp: true
|
||||
fraction: 1.0
|
||||
profile: false
|
||||
freeze: null
|
||||
multi_scale: false
|
||||
compile: false
|
||||
overlap_mask: true
|
||||
mask_ratio: 4
|
||||
dropout: 0.0
|
||||
val: true
|
||||
split: val
|
||||
save_json: false
|
||||
conf: null
|
||||
iou: 0.7
|
||||
max_det: 300
|
||||
half: false
|
||||
dnn: false
|
||||
plots: true
|
||||
source: null
|
||||
vid_stride: 1
|
||||
stream_buffer: false
|
||||
visualize: false
|
||||
augment: false
|
||||
agnostic_nms: false
|
||||
classes: null
|
||||
retina_masks: false
|
||||
embed: null
|
||||
show: false
|
||||
save_frames: false
|
||||
save_txt: false
|
||||
save_conf: false
|
||||
save_crop: false
|
||||
show_labels: true
|
||||
show_conf: true
|
||||
show_boxes: true
|
||||
line_width: null
|
||||
format: torchscript
|
||||
keras: false
|
||||
optimize: false
|
||||
int8: false
|
||||
dynamic: false
|
||||
simplify: true
|
||||
opset: null
|
||||
workspace: null
|
||||
nms: false
|
||||
lr0: 0.001
|
||||
lrf: 0.01
|
||||
momentum: 0.937
|
||||
weight_decay: 0.0005
|
||||
warmup_epochs: 3.0
|
||||
warmup_momentum: 0.8
|
||||
warmup_bias_lr: 0.1
|
||||
box: 7.5
|
||||
cls: 0.5
|
||||
dfl: 1.5
|
||||
pose: 12.0
|
||||
kobj: 1.0
|
||||
nbs: 64
|
||||
hsv_h: 0.015
|
||||
hsv_s: 0.7
|
||||
hsv_v: 0.4
|
||||
degrees: 0.0
|
||||
translate: 0.1
|
||||
scale: 0.5
|
||||
shear: 0.0
|
||||
perspective: 0.0
|
||||
flipud: 0.0
|
||||
fliplr: 0.5
|
||||
bgr: 0.0
|
||||
mosaic: 1.0
|
||||
mixup: 0.0
|
||||
cutmix: 0.0
|
||||
copy_paste: 0.0
|
||||
copy_paste_mode: flip
|
||||
auto_augment: randaugment
|
||||
erasing: 0.4
|
||||
cfg: null
|
||||
tracker: botsort.yaml
|
||||
save_dir: /home/cuuva/git/Detection_Experiment/fashion_yolo/finetuning_exp/finetuned_exp/yolov8m_finetuned_16class
|
||||
|
@ -0,0 +1,106 @@
|
||||
task: detect
|
||||
mode: train
|
||||
model: /home/cuuva/git/Detection_Experiment/fashion_yolo/fashionpedia_exp/yolov8m_fashion_final/weights/best_fashion_16class.pt
|
||||
data: /home/cuuva/git/Detection_Experiment/fashion_yolo/finetuning_exp/finetuning_dataset.yaml
|
||||
epochs: 200
|
||||
time: null
|
||||
patience: 50
|
||||
batch: -1
|
||||
imgsz: 640
|
||||
save: true
|
||||
save_period: -1
|
||||
cache: false
|
||||
device: '0'
|
||||
workers: 8
|
||||
project: finetuned_exp
|
||||
name: yolov8m_finetuned_16class2
|
||||
exist_ok: false
|
||||
pretrained: true
|
||||
optimizer: AdamW
|
||||
verbose: true
|
||||
seed: 0
|
||||
deterministic: true
|
||||
single_cls: false
|
||||
rect: false
|
||||
cos_lr: false
|
||||
close_mosaic: 10
|
||||
resume: false
|
||||
amp: true
|
||||
fraction: 1.0
|
||||
profile: false
|
||||
freeze: null
|
||||
multi_scale: false
|
||||
compile: false
|
||||
overlap_mask: true
|
||||
mask_ratio: 4
|
||||
dropout: 0.0
|
||||
val: true
|
||||
split: val
|
||||
save_json: false
|
||||
conf: null
|
||||
iou: 0.7
|
||||
max_det: 300
|
||||
half: false
|
||||
dnn: false
|
||||
plots: true
|
||||
source: null
|
||||
vid_stride: 1
|
||||
stream_buffer: false
|
||||
visualize: false
|
||||
augment: false
|
||||
agnostic_nms: false
|
||||
classes: null
|
||||
retina_masks: false
|
||||
embed: null
|
||||
show: false
|
||||
save_frames: false
|
||||
save_txt: false
|
||||
save_conf: false
|
||||
save_crop: false
|
||||
show_labels: true
|
||||
show_conf: true
|
||||
show_boxes: true
|
||||
line_width: null
|
||||
format: torchscript
|
||||
keras: false
|
||||
optimize: false
|
||||
int8: false
|
||||
dynamic: false
|
||||
simplify: true
|
||||
opset: null
|
||||
workspace: null
|
||||
nms: false
|
||||
lr0: 0.001
|
||||
lrf: 0.01
|
||||
momentum: 0.937
|
||||
weight_decay: 0.0005
|
||||
warmup_epochs: 3.0
|
||||
warmup_momentum: 0.8
|
||||
warmup_bias_lr: 0.1
|
||||
box: 7.5
|
||||
cls: 0.5
|
||||
dfl: 1.5
|
||||
pose: 12.0
|
||||
kobj: 1.0
|
||||
nbs: 64
|
||||
hsv_h: 0.015
|
||||
hsv_s: 0.7
|
||||
hsv_v: 0.4
|
||||
degrees: 0.0
|
||||
translate: 0.1
|
||||
scale: 0.5
|
||||
shear: 0.0
|
||||
perspective: 0.0
|
||||
flipud: 0.0
|
||||
fliplr: 0.5
|
||||
bgr: 0.0
|
||||
mosaic: 1.0
|
||||
mixup: 0.0
|
||||
cutmix: 0.0
|
||||
copy_paste: 0.0
|
||||
copy_paste_mode: flip
|
||||
auto_augment: randaugment
|
||||
erasing: 0.4
|
||||
cfg: null
|
||||
tracker: botsort.yaml
|
||||
save_dir: /home/cuuva/git/Detection_Experiment/fashion_yolo/finetuning_exp/finetuned_exp/yolov8m_finetuned_16class2
|
||||
|
@ -0,0 +1,106 @@
|
||||
task: detect
|
||||
mode: train
|
||||
model: yolov8m.pt
|
||||
data: /home/cuuva/git/Detection_Experiment/fashion_yolo/finetuning_exp/finetuning_dataset.yaml
|
||||
epochs: 200
|
||||
time: null
|
||||
patience: 50
|
||||
batch: -1
|
||||
imgsz: 640
|
||||
save: true
|
||||
save_period: -1
|
||||
cache: false
|
||||
device: '0'
|
||||
workers: 8
|
||||
project: finetuned_exp
|
||||
name: yolov8m_finetuned_16class2
|
||||
exist_ok: false
|
||||
pretrained: true
|
||||
optimizer: AdamW
|
||||
verbose: true
|
||||
seed: 0
|
||||
deterministic: true
|
||||
single_cls: false
|
||||
rect: false
|
||||
cos_lr: false
|
||||
close_mosaic: 10
|
||||
resume: false
|
||||
amp: true
|
||||
fraction: 1.0
|
||||
profile: false
|
||||
freeze: null
|
||||
multi_scale: false
|
||||
compile: false
|
||||
overlap_mask: true
|
||||
mask_ratio: 4
|
||||
dropout: 0.0
|
||||
val: true
|
||||
split: val
|
||||
save_json: false
|
||||
conf: null
|
||||
iou: 0.7
|
||||
max_det: 300
|
||||
half: false
|
||||
dnn: false
|
||||
plots: true
|
||||
source: null
|
||||
vid_stride: 1
|
||||
stream_buffer: false
|
||||
visualize: false
|
||||
augment: false
|
||||
agnostic_nms: false
|
||||
classes: null
|
||||
retina_masks: false
|
||||
embed: null
|
||||
show: false
|
||||
save_frames: false
|
||||
save_txt: false
|
||||
save_conf: false
|
||||
save_crop: false
|
||||
show_labels: true
|
||||
show_conf: true
|
||||
show_boxes: true
|
||||
line_width: null
|
||||
format: torchscript
|
||||
keras: false
|
||||
optimize: false
|
||||
int8: false
|
||||
dynamic: false
|
||||
simplify: true
|
||||
opset: null
|
||||
workspace: null
|
||||
nms: false
|
||||
lr0: 0.001
|
||||
lrf: 0.01
|
||||
momentum: 0.937
|
||||
weight_decay: 0.0005
|
||||
warmup_epochs: 3.0
|
||||
warmup_momentum: 0.8
|
||||
warmup_bias_lr: 0.1
|
||||
box: 7.5
|
||||
cls: 0.5
|
||||
dfl: 1.5
|
||||
pose: 12.0
|
||||
kobj: 1.0
|
||||
nbs: 64
|
||||
hsv_h: 0.015
|
||||
hsv_s: 0.7
|
||||
hsv_v: 0.4
|
||||
degrees: 0.0
|
||||
translate: 0.1
|
||||
scale: 0.5
|
||||
shear: 0.0
|
||||
perspective: 0.0
|
||||
flipud: 0.0
|
||||
fliplr: 0.5
|
||||
bgr: 0.0
|
||||
mosaic: 1.0
|
||||
mixup: 0.0
|
||||
cutmix: 0.0
|
||||
copy_paste: 0.0
|
||||
copy_paste_mode: flip
|
||||
auto_augment: randaugment
|
||||
erasing: 0.4
|
||||
cfg: null
|
||||
tracker: botsort.yaml
|
||||
save_dir: /home/cuuva/git/Detection_Experiment/fashion_yolo/finetuning_exp/finetuned_exp/yolov8m_finetuned_16class2
|
||||
|
@ -0,0 +1,106 @@
|
||||
task: detect
|
||||
mode: train
|
||||
model: yolov8m.pt
|
||||
data: /home/cuuva/git/Detection_Experiment/fashion_yolo/finetuning_exp/finetuning_dataset.yaml
|
||||
epochs: 200
|
||||
time: null
|
||||
patience: 50
|
||||
batch: -1
|
||||
imgsz: 640
|
||||
save: true
|
||||
save_period: -1
|
||||
cache: false
|
||||
device: '0'
|
||||
workers: 8
|
||||
project: finetuned_exp
|
||||
name: yolov8m_finetuned_4class
|
||||
exist_ok: false
|
||||
pretrained: true
|
||||
optimizer: AdamW
|
||||
verbose: true
|
||||
seed: 0
|
||||
deterministic: true
|
||||
single_cls: false
|
||||
rect: false
|
||||
cos_lr: false
|
||||
close_mosaic: 10
|
||||
resume: false
|
||||
amp: true
|
||||
fraction: 1.0
|
||||
profile: false
|
||||
freeze: null
|
||||
multi_scale: false
|
||||
compile: false
|
||||
overlap_mask: true
|
||||
mask_ratio: 4
|
||||
dropout: 0.0
|
||||
val: true
|
||||
split: val
|
||||
save_json: false
|
||||
conf: null
|
||||
iou: 0.7
|
||||
max_det: 300
|
||||
half: false
|
||||
dnn: false
|
||||
plots: true
|
||||
source: null
|
||||
vid_stride: 1
|
||||
stream_buffer: false
|
||||
visualize: false
|
||||
augment: false
|
||||
agnostic_nms: false
|
||||
classes: null
|
||||
retina_masks: false
|
||||
embed: null
|
||||
show: false
|
||||
save_frames: false
|
||||
save_txt: false
|
||||
save_conf: false
|
||||
save_crop: false
|
||||
show_labels: true
|
||||
show_conf: true
|
||||
show_boxes: true
|
||||
line_width: null
|
||||
format: torchscript
|
||||
keras: false
|
||||
optimize: false
|
||||
int8: false
|
||||
dynamic: false
|
||||
simplify: true
|
||||
opset: null
|
||||
workspace: null
|
||||
nms: false
|
||||
lr0: 0.001
|
||||
lrf: 0.01
|
||||
momentum: 0.937
|
||||
weight_decay: 0.0005
|
||||
warmup_epochs: 3.0
|
||||
warmup_momentum: 0.8
|
||||
warmup_bias_lr: 0.1
|
||||
box: 7.5
|
||||
cls: 0.5
|
||||
dfl: 1.5
|
||||
pose: 12.0
|
||||
kobj: 1.0
|
||||
nbs: 64
|
||||
hsv_h: 0.015
|
||||
hsv_s: 0.7
|
||||
hsv_v: 0.4
|
||||
degrees: 0.0
|
||||
translate: 0.1
|
||||
scale: 0.5
|
||||
shear: 0.0
|
||||
perspective: 0.0
|
||||
flipud: 0.0
|
||||
fliplr: 0.5
|
||||
bgr: 0.0
|
||||
mosaic: 1.0
|
||||
mixup: 0.0
|
||||
cutmix: 0.0
|
||||
copy_paste: 0.0
|
||||
copy_paste_mode: flip
|
||||
auto_augment: randaugment
|
||||
erasing: 0.4
|
||||
cfg: null
|
||||
tracker: botsort.yaml
|
||||
save_dir: /home/cuuva/git/Detection_Experiment/fashion_yolo/finetuning_exp/finetuned_exp/yolov8m_finetuned_4class
|
||||
|
@ -0,0 +1,25 @@
|
||||
# path: /home/cuuva/git/Detection_Experiment/datasets/finetune_dataset/
|
||||
|
||||
train: /home/cuuva/git/Detection_Experiment/datasets/finetune_dataset/train/images/
|
||||
val: /home/cuuva/git/Detection_Experiment/datasets/finetune_dataset/val/images/
|
||||
|
||||
# Classes
|
||||
nc: 16 # (18개 -> 16개로 감소)
|
||||
|
||||
names:
|
||||
0: shirt(blouse)
|
||||
1: t-shirt(sweatshirt)
|
||||
2: sweater
|
||||
3: cardigan
|
||||
4: jacket
|
||||
5: vest
|
||||
6: pants
|
||||
7: shorts
|
||||
8: skirt
|
||||
9: coat
|
||||
10: dress # (dress + jumpsuit + cape)
|
||||
11: glasses # (Old 13)
|
||||
12: hat # (Old 14)
|
||||
13: shoe # (Old 15)
|
||||
14: bag, wallet # (Old 16)
|
||||
15: scarf # (Old 17)
|
||||
@ -0,0 +1,18 @@
|
||||
from ultralytics import YOLO
|
||||
|
||||
# 1. 모델 로드 (YOLOv8m 사용)
|
||||
# model = YOLO('yolov8m.pt')
|
||||
model = YOLO("/home/cuuva/git/Detection_Experiment/fashion_yolo/fashionpedia_exp/yolov8m_fashion_final/weights/best_fashion_16class.pt")
|
||||
|
||||
train_results = model.train(
|
||||
data="/home/cuuva/git/Detection_Experiment/fashion_yolo/finetuning_exp/finetuning_dataset.yaml",
|
||||
epochs=200,
|
||||
imgsz=640,
|
||||
batch=-1,
|
||||
device="cuda",
|
||||
optimizer='AdamW',
|
||||
lr0=0.001,
|
||||
patience=50,
|
||||
project='finetuned_exp',
|
||||
name='yolov8m_finetuned_16class',
|
||||
)
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Loading…
Reference in new issue