컴퓨터 비전

Object Detection

인공지능파이썬 2025. 3. 7. 12:43

1. Object Detection
* Object Detection(객체 탐지)은 이미지나 영상에서 특정 객체의 존재 여부를 확인하고, 해당 객체의 위치를 바운딩 박스(bounding box)로 표시하는 기술입니다. 
* 이는 컴퓨터 비전에서 중요한 분야로, 이미지 내에서 여러 개의 객체를 동시에 탐지하고 분류할 수 있습니다. 
* Object Detection은 주로 딥러닝 기반의 CNN(합성곱 신경망) 모델을 활용하며, 대표적인 알고리즘으로는 R-CNN 계열(Faster R-CNN, Mask R-CNN), YOLO(You Only Look Once), SSD(Single Shot MultiBox Detector) 등이 있습니다. 
* 이러한 기술은 자율 주행, 보안 감시, 의료 영상 분석, 증강 현실 등 다양한 분야에서 활용됩니다.
* Object Detection은 방식에 따라 크게 딥러닝 기반 기법과 전통적인 기법으로 나눌 수 있으며, 딥러닝 기반 기법은 다시 1단계 탐지(One-Stage)와 2단계 탐지(Two-Stage) 방식으로 분류됩니다.

 

1-1. 전통적인 기법
* HOG(Histogram of Oriented Gradients) + SVM(Support Vector Machine), Haar Cascade, Selective Search 등의 방법을 사용하여 특징을 추출하고 객체를 탐지하는 방식입니다. 
* 하지만 최근에는 딥러닝 방식이 더 우수하여 잘 사용되지 않습니다.

 

### 1-2. 딥러닝 기반 기법
* 2단계 탐지(Two-Stage Detection):
    * Two-Stage Detection은 두 단계로 객체를 찾는 방식입니다. 
    * 첫 번째 단계에서는 이미지에서 "어디에 객체가 있을 것 같은지" 후보 영역(Region Proposal)을 찾습니다. 
    * 예를 들어, Faster R-CNN에서는 Region Proposal Network(RPN)이 다양한 위치에서 객체가 있을 가능성이 높은 영역을 예측합니다. 
    * 두 번째 단계에서는 이 후보 영역들을 하나씩 분석하여 "이것이 어떤 객체인지" 분류하고, 바운딩 박스를 정밀하게 조정합니다. 
    * 쉽게 말해, 먼저 전체 이미지를 훑어서 "여기에 뭔가 있다!"라고 판단한 후, 더 자세히 들여다보며 "이건 자동차야!"라고 확정하는 방식입니다. 
    * 이렇게 두 번에 걸쳐 탐지하기 때문에 정확도가 높지만 속도는 상대적으로 느릴 수 있습니다.

* 1단계 탐지(One-Stage Detection):
    * One-Stage Detection은 객체를 찾을 때 한 번의 과정만 거치는 방식입니다. 
    * 이미지를 입력받으면, 네트워크가 바로 객체의 위치(바운딩 박스)와 종류(클래스)를 동시에 예측합니다. 
    * 대표적인 알고리즘으로 YOLO(You Only Look Once)와 SSD(Single Shot MultiBox Detector)가 있습니다. 
    * 쉽게 말해, 이미지를 여러 영역으로 나눈 뒤, 각각의 영역에서 "여기에 자동차가 있다!"처럼 바로 객체를 판별하는 방식입니다. 
    * 이렇게 한 번에 예측하기 때문에 속도가 빠르지만, 정확도는 Two-Stage Detection보다 다소 낮을 수 있습니다. 
    * 따라서 실시간 객체 탐지가 중요한 자율주행, 영상 감시, 드론 탐색 등에서 많이 활용됩니다.

 

 

2. YOLO
* YOLO(You Only Look Once)는 이미지 전체를 한 번에 처리해 객체의 위치와 종류를 동시에 예측하는 실시간 객체 탐지 알고리즘으로, 빠른 속도와 높은 효율성이 특징입니다. 
* 최신 버전인 YOLO8은 이전 모델들보다 개선된 네트워크 구조와 최적화된 학습 기법을 적용해 정확도와 속도를 크게 향상시켰으며, 특히 작은 객체나 복잡한 배경에서도 강력한 탐지 성능을 보입니다. 
* 이를 통해 다양한 실시간 컴퓨터 비전 응용 분야에서 뛰어난 활용도를 제공하고 있습니다.

```
YOLO 파일 형식
예) 14 0.31 0.34 0.212 0.547

14. 클래스 ID
0.31 : 중심 X 좌표
0.34 : 중심 Y 좌표
0.212 : 박스 너비
0.547 : 박스 높이
```
> YOLO 포맷은 객체의 위치를 이미지 크기에 맞게 정규화된 좌표값을 저장

 

 

2-1. PascalVOC 2007
* PascalVOC 2007은 객체 탐지(Object Detection), 분할(Segmentation), 동작 인식(Action Recognition) 등의 다양한 컴퓨터 비전 과제를 위한 벤치마크 데이터셋입니다. 
* 총 20개의 객체 클래스(예: 사람, 자동차, 개, 고양이 등)를 포함하며, 훈련(train), 검증(val), 테스트(test) 세트로 구성되어 있습니다. 
* 각 이미지에는 객체의 경계 상자(Bounding Box) 및 해당 클래스 레이블이 주어지며, Mean Average Precision(mAP) 평가 기준을 적용하여 성능을 측정합니다.

 

예시 1)

# PascalVOC 2007 Train/Val 다운로드
# train: 2501장, val: 2510장
!wget http://pjreddie.com/media/files/VOCtrainval_06-Nov-2007.tar

 

예시 2)

# test: 4952장
!wget http://pjreddie.com/media/files/VOCtest_06-Nov-2007.tar

 

예시 3)

# 폴더 
pascal_datasets
pascal_datasets/trainval
pascal_datasets/test
pascal_datasets/VOC
pascal_datasets/VOC/images
pascal_datasets/VOC/labels
pascal_datasets/VOC/images/train2007
pascal_datasets/VOC/images/val2007
pascal_datasets/VOC/images/test2007
pascal_datasets/VOC/labels/train2007
pascal_datasets/VOC/labels/val2007
pascal_datasets/VOC/labels/test2007

 

예시 4)

# 파일 및 디렉토리 경로를 객체 지향적으로 다룰 수 있는 모듈
from pathlib import Path

 

예시 5)

from pathlib import Path  # 파일 및 디렉터리 작업을 위한 Path 모듈 임포트

# 현재 디렉터리 내에 'pascal_datasets' 경로를 설정
root = Path('./pascal_datasets')

# 'pascal_datasets/trainval' 디렉터리를 생성 (이미 존재하면 오류 없이 유지)
Path('./pascal_datasets/trainval').mkdir(parents=True, exist_ok=True)

# 'pascal_datasets/test' 디렉터리를 생성 (이미 존재하면 오류 없이 유지)
Path('./pascal_datasets/test').mkdir(parents=True, exist_ok=True)

 

예시 6)

from pathlib import Path  # 파일 및 디렉터리 작업을 위한 Path 모듈 

root = Path('./pascal_datasets')  # 'pascal_datasets' 디렉터리 경로 설정

# 'images' 및 'labels' 폴더 안에 'train2007', 'val2007', 'test2007' 폴더 생성
for path1 in ('images', 'labels'):  # 'images'와 'labels' 두 개의 상위 폴더에 대해 반복
    for path2 in ('train2007', 'val2007', 'test2007'):  # 각각의 데이터셋 폴더에 대해 반복
        # 예: ./pascal_datasets/VOC/images/train2007 와 같은 경로 생성
        new_path = root / 'VOC' / path1 / path2
        new_path.mkdir(parents=True, exist_ok=True)  # 디렉터리를 생성 (이미 존재하면 무시)

 

예시 7)

from pathlib import Path  # 파일 및 디렉터리 작업을 위한 Path 모듈 임포트

root = Path('./pascal_datasets')  # 'pascal_datasets' 디렉터리 경로 설정

# 'images' 및 'labels' 폴더 내에 'train2007', 'val2007', 'test2007' 하위 폴더 생성
for path1 in ('images', 'labels'):  # 'images'와 'labels' 폴더에 대해 반복
    for path2 in ('train2007', 'val2007', 'test2007'):  # 각 데이터셋 유형 폴더 생성
        # 예: './pascal_datasets/VOC/images/train2007' 같은 디렉터리 경로 설정
        new_path = root / 'VOC' / path1 / path2
        new_path.mkdir(parents=True, exist_ok=True)  # 디렉터리를 생성 (이미 존재하면 무시)

 

예시 8)

# VOC 데이터셋 압축 파일 해제
!tar -xvf VOCtrainval_06-Nov-2007.tar -C ./pascal_datasets/trainval/
!tar -xvf VOCtest_06-Nov-2007.tar -C ./pascal_datasets/test/

 

예시 9)

# 어노테이션을 YOLO 형식으로 변환
!git clone https://github.com/ssaru/convert2Yolo.git

 

예시 10)

%cd convert2Yolo/

 

예시 11)

# txt파일에 있는 패키지 설치
%pip install -qr requirements.txt

 

예시 11-2)

 

여기서 voc,names 파일을 메모장에 붙혀서 convert2Yolo/ 폴더에 넣어줍니다

aeroplane
bicycle
bird
boat
bottle
bus
car
cat
chair
cow
diningtable
dog
horse
motorbike
person
pottedplant
sheep
sofa
train
tvmonitor

 

 

예시 12)

# datasets: 데이터셋이 VOC 형식임을 지정
# img_path: 이미지 파일 경로
# label: 어노테이션(xml) 경로
# convert_output_path: YOLO 형식으로 변환된 라벨 저장 경로
# img_type: 사용할 이미지 파일 확장자
# manifest_path: 변환 과정에서 사용할 추가적인 정보 파일 저장 경로
# cls_list_file: VOC에서 사용할 클래스 목록이 정의된 파일

!python example.py \
    --datasets VOC \
    --img_path /content/pascal_datasets/trainval/VOCdevkit/VOC2007/JPEGImages \
    --label /content/pascal_datasets/trainval/VOCdevkit/VOC2007/Annotations \
    --convert_output_path /content/pascal_datasets/VOC/labels/train2007 \
    --img_type '.jpg' \
    --manifest_path /content \
    --cls_list_file ./voc.names

 

예시 13)

# /content/pascal_datasets/trainval/VOCdevkit/VOC2007/ImageSets/Main/val.txt 파일을 읽어서
# /content/pascal_datasets/VOC/labels/train2007 파일 중 txt 문서에 있는 파일을
# /content/pascal_datasets/VOC/labels/val2007 으로 옮기기

import shutil

path = '/content/pascal_datasets/trainval/VOCdevkit/VOC2007/ImageSets/Main/val.txt'

with open(path) as f:
    image_ids = f.read().strip().split()
    for id in image_ids:
        ori_path = '/content/pascal_datasets/VOC/labels/train2007'
        mv_path = '/content/pascal_datasets/VOC/labels/val2007'
        shutil.move(f'{ori_path}/{id}.txt', f'{mv_path}/{id}.txt')

 

예시 13-2)

pascal_datasets에 custom_voc.yaml 파일을 저장해서 넣는다

path: /content/pascal_datasets/VOC
train:
  - images/train2007
val:
  - images/val2007
test:
  - images/test2007

nc: 20
names: ['aeroplane', 'bicycle', 'bird', 'boat', 'bottle', 'bus', 'car', 'cat', 'chair', 'cow', 'diningtable', 'dog',
        'horse', 'motorbike', 'person', 'pottedplant', 'sheep', 'sofa', 'train', 'tvmonitor']

 

예시 14)

# /content/pascal_datasets/trainval/VOCdevkit/VOC2007/JPEGImages 와
# /content/pascal_datasets/test/VOCdevkit/VOC2007/JPEGImages 에서
# 이미지를 가져와 디렉토리에 맞게 저장

import os

path = '/content/pascal_datasets'

for folder, subset in ('trainval', 'train2007'), ('trainval', 'val2007'), ('test', 'test2007'):
  ex_imgs_path = f'{path}/{folder}/VOCdevkit/VOC2007/JPEGImages'
  label_path = f'{path}/VOC/labels/{subset}'
  img_path = f'{path}/VOC/images/{subset}'
  print(subset, ": ", len(os.listdir(label_path)))
  for lbs_list in os.listdir(label_path):
    shutil.move(os.path.join(ex_imgs_path, lbs_list.split('.')[0]+'.jpg'),
                    os.path.join(img_path, lbs_list.split('.')[0]+'.jpg'))

--->
train2007 :  2501
val2007 :  2510
test2007 :  4952

 

예시 15)

# content폴더로 옮긴다
%cd /content/

 

2-2. YAML 파일
* YAML 파일은 모델 구성, 데이터 경로, 하이퍼파라미터 등을 정의하는 설정 파일로, 모델 학습과 추론을 자동화하는 데 중요한 역할을 합니다.
* 주로 data.yaml과 model.yaml 같은 파일이 있으며, data.yaml은 학습 및 검증 데이터셋의 경로, 클래스 개수, 클래스 이름 등을 정의하고, model.yaml은 네트워크 구조(레이어, 채널 수, 활성화 함수 등)를 설정합니다.
* YAML 형식은 가독성이 뛰어나고 계층적 구조를 쉽게 표현할 수 있어 YOLO의 설정을 직관적으로 관리할 수 있으며, 이를 통해 사용자 맞춤형 모델을 효율적으로 구축할 수 있습니다.

 

 

예시 1)

# ultralytics 패키지 설치
!pip install -q ultralytics

 

예시 2)

from ultralytics import YOLO

 

예시 3)

# data: 데이터셋 설정 파일
# epochs: 학습 에포크 수
# batch: 배치 크기
# imgsz: 입력 이미지 크기
# device: GPU(0), CPU(-1)
# workers: 데이터 로딩에 사용할 CPU 스레드 수
# name: 학습 결과 저장 폴더명

model = YOLO('yolov8s.pt')

results = model.train(
    data='custom_voc.yaml',
    epochs=10,
    batch=32,
    imgsz=640,
    device=0,
    workers=2,
    name='custom_s'
)

 

 

3. 객체 탐지 모델의 성능 평가 지표
* 정밀도(Precision): 객체 탐지 모델이 예측한 객체 중 실제로 정답인 객체의 비율을 의미합니다.
  * 즉, 모델이 "이것이 객체다"라고 판단한 것들 중에서 실제로 맞는 것이 얼마나 많은지를 측정합니다.
  * 수식으로 표현하면 **Precision = (TP) / (TP + FP)**이며, 여기서 TP(True Positive)는 모델이 올바르게 탐지한 객체 수, FP(False Positive)는 잘못 탐지한 객체 수를 뜻합니다. 정밀도가 높을수록 모델이 잘못된 탐지를 덜 한다는 의미입니다.

* 재현율(Recall): 실제 존재하는 객체 중에서 모델이 올바르게 탐지한 객체의 비율을 의미합니다.
  * 즉, 놓치지 않고 얼마나 많은 객체를 찾았는지를 평가합니다. 수식으로 표현하면 **Recall = (TP) / (TP + FN)**이며, 여기서 FN(False Negative)은 모델이 놓친 실제 객체 수를 의미합니다.
  * 재현율이 높을수록 모델이 더 많은 객체를 탐지하지만, 때때로 잘못된 탐지(FP)도 많아질 수 있습니다.

* AP(Average Precision): 특정 클래스에 대해 Precision-Recall 곡선을 기반으로 평균 정밀도를 계산한 값입니다.
    * AP는 Recall을 0에서 1까지 변화시키면서 Precision을 계산한 후 평균을 내는 방식으로 구합니다.
    * 객체 탐지 모델의 성능을 측정하는 대표적인 방법이며, 보통 특정 IoU 기준에서 계산됩니다(예: AP@IoU=0.5는 IoU가 0.5 이상인 경우에 대해 AP를 구함)


* IoU(Intersection over Union): 예측된 바운딩 박스와 실제 객체의 바운딩 박스가 얼마나 겹치는지를 나타내는 값입니다.
    * IoU는 두 박스가 겹치는 영역의 면적을 두 박스의 총 합집합 면적으로 나누어 계산합니다.
    * 값이 1에 가까울수록 예측 박스와 실제 박스가 거의 일치한다는 뜻이며, 보통 객체 탐지 성능 평가에서 특정 임계값(예: IoU ≥ 0.5)을 기준으로 모델의 정확도를 평가합니다.


* mAP(mean Average Precision): 여러 클래스에 대한 AP 값을 평균 낸 값으로, 전체 모델의 객체 탐지 성능을 평가하는 종합적인 지표입니다.
    * 단일 클래스가 아닌 전체 데이터셋에 포함된 모든 클래스의 성능을 반영하며, 다양한 IoU 임곗값(예: 0.5~0.95)에 대해 평균을 내기도 합니다.
    * 높은 mAP 값은 모델이 다양한 클래스의 객체를 정확하게 탐지한다는 것을 의미합니다.
    
    * mAP@50: IoU(Intersection over Union)가 0.5(50%) 이상이면 정답으로 인정하고 계산한 평균 정밀도입니다. 즉, 모델이 대략적인 위치라도 맞추면 성능이 좋게 나옵니다.
    * mAP@50-95: IoU를 0.5부터 0.95까지 0.05 간격으로 변화시키면서 성능을 평가한 평균 정밀도입니다. 즉, 객체의 위치를 더욱 정확하게 맞춰야 높은 점수를 받기 때문에 더 엄격한 기준입니다.

 

 

예시 1)

# 학습된 모델 로드
model = YOLO("runs/detect/custom_s/weights/best.pt")

 

 

예시 2)

# 검증 수행
results = model.val(
    data="custom_voc.yaml",  # 데이터셋 설정
    imgsz=640,               # 이미지 크기
    iou=0.5,                 # IoU 임계값
    batch=32,                # 배치 크기
    device=0,                # GPU 사용
    workers=2,               # 데이터 로드 시 병렬 처리할 워커 수
    half=True,               # FP16 연산 활성화 (속도 향상)
    split="test"             # 테스트 데이터셋을 사용
)

print(results)

 

예시 3)

model = YOLO("runs/detect/custom_s/weights/best.pt")

# 객체 탐지 수행
results = model.predict(
    source="/content/pascal_datasets/VOC/images/custom2007",  # 테스트 이미지 폴더
    imgsz=640,           # 입력 이미지 크기
    conf=0.25,           # 신뢰도(Confidence) 임계값
    device=0,            # GPU 사용 (CPU 사용 시 "cpu")
    save=True,           # 탐지 결과 저장
    save_txt=True,       # 탐지 결과를 txt 형식으로 저장 (YOLO 포맷)
    save_conf=True       # 탐지된 객체의 신뢰도 점수도 저장
)

print(results)

 

 

 

 

 

 

 

 

 

728x90
LIST

'컴퓨터 비전' 카테고리의 다른 글

segmentation  (2) 2025.03.12
이안류 CCTV 데이터셋  (0) 2025.03.11
OCR  (6) 2025.03.06
4-(2). OpenCV  (0) 2025.03.05
4. OpenCV  (0) 2025.03.05