본문 바로가기
AI/컴퓨터 비전

18. YOLO v8을 이용한 차량 파손 검사

by 사라리24 2024. 8. 13.



1. Image Segmentation

* 컴퓨터 비전 분야에서 이미지나 비디오의 디지털 데이터를 여러 개의 부분 또는 객체로 분할하는 기술
* 이미지의 중요한 요소들을 식별하고 각 요소를 개별적으로 분석할 수 있게 하는 것

 

1. Image Segmentation의 유형

  • Sementic Segmentation
    • 이미지의 각 픽셀을 미리 정의된 클래스 레이블 중 하나로 분류
    • 예) 자율 주행차로의 도로, 차선, 보행자 등을 식별
  • Instance Segmentation
    • 동일한 클래스 내의 서로 다른 개체들을 개별적으로 식별
    • 예) 이미지 내에 있는 개별 물체의 수를 파악하고 각각 물체를 식별 및 추적하는 경우
  • Panoptic Segmentation
    • Semantic Segmentation, Instance Segmentation을 결합한 형태
    • 배경과 같은 클래스를 처리하는 Semantic Segmentation과 개체를 구분하는 Instance Segmentation을 모두 수행
    • 예) 풍경 이미지에서 하늘, 도로, 나무와사람, 자동차를 동시에 식별

 

  • 데이터 정보

 

  • 폴더생성







 

 

import


       
        import os
        import random
        import shutil
        import cv2
        import glob
        import json
        import numpy as np
        import matplotlib.pyplot as plt
        from tqdm import tqdm


 

 

 

파일 경로 설정


       
        data_root = '/content/drive/MyDrive/1. KDT/8. 컴퓨터 비전/9. Segmentation'
        file_root = f'{data_root}/data'


 

 

 

클래스 이름, 프로젝트 이름 설정


       
      cls_list = ['Scratched','Breakage','Separated','Crushed']
      project_name='cd'


 

 

폴더 구조 생성


       
        train_root = f'{file_root}/{project_name}/train'
        valid_root = f'{file_root}/{project_name}/valid'
        test_root = f'{file_root}/{project_name}/test'

        for folder in [train_root, valid_root, test_root]:
            if not os.path.exists(folder):
                os.makedirs(folder)
            for s in ['images','labels']:
                s_folder = f'{folder}/{s}'
                if not os.path.exists(s_folder):
                    os.makedirs(s_folder)


 

 

라벨링 형태 YOLO 형식으로 바꿀 함수 생성


       
        # 라벨링 형태 변환(YOLO) : [cls, xc, yx, w, h]
        # [[x2,y1],[x2,y2]...]->[cls xc yc w h] : normalize
        def json_to_yolo_polygon(polygon, w, h):
            yolo_list = []
            for p in polygon:
                yolo_list.append(p[0]/w)
                yolo_list.append(p[1]/h)
            return " ".join([str(x) for x in yolo_list])

 

 

 

annotations에 json 파일 1,200개가 들어간 것을 확인


     
        file_list = glob.glob(f'{file_root}/annotations/*.json')
        random.seed(2024)
        random.shuffle(file_list)
        print(len(file_list))

 
1200

 

첫번째 파일 확인


       

        file_list[0]


/content/drive/MyDrive/1. KDT/8. 컴퓨터 비전/9. Segmentation/data/annotations/0004696_as-3293974.json

 

 

JSON 파일에서 라벨링 데이터를 읽어 YOLO 포맷의 텍스트 파일로 변환


       
      # 라벨링 형태 변환 파일 생성(json -> txt) 테스트
      mask_name = file_list[0].split('/')[-1].replace('json', 'txt')
      result = []

      with open(file_list[0], 'r') as json_file:
          data = json.load(json_file)
          h = data['images']['height']
          w = data['images']['width']
          for ann in data['annotations']:
              label = ann['damage']
              if label in cls_list:
                  polygon_coord = ann['segmentation'][0][0][:-1]
                  cood_string = json_to_yolo_polygon(polygon_coord, w, h)
                  yolo_string = f'{cls_list.index(label)} {cood_string}'
                  result.append(yolo_string)

 
  • mask_name = file_list[0].split('/')[-1].replace('json', 'txt'):
    • file_list[0]에 있는 첫 번째 파일 경로에서 파일명을 추출한 후, 확장자를 .json에서 .txt로 변경합니다.
    • 예를 들어, file_list[0]가 /path/to/file/0000459_sc-226797.json일 때, mask_name은 0000459_sc-226797.txt가 됩니다.
  • result = []:
    • YOLO 포맷으로 변환된 라벨 데이터를 저장할 빈 리스트를 초기화합니다.
  • with open(file_list[0], 'r') as json_file::
    • file_list[0]의 첫 번째 JSON 파일을 읽기 모드('r')로 엽니다.
  • data = json.load(json_file):
    • JSON 파일의 내용을 data 변수에 로드합니다. data는 이제 JSON 파일의 데이터 구조를 담고 있습니다.
  • h = data['images']['height']:
    • 이미지의 높이(height) 값을 JSON 데이터에서 추출하여 h 변수에 저장합니다.
  • w = data['images']['width']:
    • 이미지의 너비(width) 값을 JSON 데이터에서 추출하여 w 변수에 저장합니다.
  • for ann in data['annotations']::
    • JSON 데이터의 annotations 리스트를 반복하여 각 주석(annotation)을 처리합니다.
  • label = ann['damage']:
    • 주석에서 손상(damage) 정보를 추출하여 label 변수에 저장합니다.
  • if label in cls_list::
    • 추출한 label이 클래스 목록(cls_list)에 있는지 확인합니다. 만약 label이 cls_list에 포함된다면, 다음 코드를 실행합니다.
  • polygon_cood = ann['segmentation'][0][0][:-1]:
    • 주석에서 다각형 좌표(segmentation)를 추출합니다. 여기서 [0][0][:-1]은 첫 번째 좌표를 가져오고 마지막 값을 제외한 나머지 좌표를 polygon_cood에 저장합니다.
  • cood_string = json_to_yolo_polygon(polygon_cood, w, h):
    • json_to_yolo_polygon 함수로 다각형 좌표를 YOLO 포맷의 문자열로 변환합니다. 이 함수는 다각형의 상대적 좌표를 YOLO 형식에 맞게 변환합니다.
  • yolo_string = f'{cls_list.index(label)} {cood_string}':
    • 클래스 인덱스(클래스가 cls_list에서 몇 번째인지)를 구하고, 변환된 좌표 문자열(cood_string)과 결합하여 YOLO 포맷의 문자열(yolo_string)을 만듭니다.
    • 예를 들어, 클래스 인덱스가 0이고, 좌표 문자열이 "0.5 0.5 0.7 0.7"이라면 yolo_string은 "0 0.5 0.5 0.7 0.7"이 됩니다.
  • result.append(yolo_string):
    • 생성된 YOLO 포맷의 문자열을 result 리스트에 추가합니다.
  • 주석
더보기

     
        # 첫 번째 JSON 파일의 이름에서 확장자를 '.txt'로 변경한 후, 해당 이름을 mask_name 변수에 저장
        mask_name = file_list[0].split('/')[-1].replace('json', 'txt')

        # YOLO 포맷으로 변환된 라벨 데이터를 저장할 빈 리스트 초기화
        result = []

        # 첫 번째 JSON 파일을 읽기 모드로 염
        with open(file_list[0], 'r') as json_file:
            # JSON 데이터를 파싱하여 data 변수에 저장
            data = json.load(json_file)
           
            # 이미지의 높이와 너비를 JSON 데이터에서 추출하여 각각 h와 w 변수에 저장
            h = data['images']['height']
            w = data['images']['width']
           
            # JSON 데이터의 'annotations' 리스트를 반복하여 각 주석(annotation) 처리
            for ann in data['annotations']:
                # 각 주석에서 손상(damage) 정보를 추출하여 label 변수에 저장
                label = ann['damage']
               
                # 만약 label이 클래스 목록(cls_list)에 있는 경우에만 다음 코드를 실행
                if label in cls_list:
                    # 주석에서 다각형 좌표(segmentation)를 추출하고, 마지막 값을 제외한 나머지 좌표를 polygon_cood에 저장
                    polygon_cood = ann['segmentation'][0][0][:-1]
                   
                    # 다각형 좌표를 YOLO 포맷의 문자열로 변환
                    cood_string = json_to_yolo_polygon(polygon_cood, w, h)
                   
                    # 클래스 인덱스와 변환된 좌표 문자열을 결합하여 YOLO 포맷의 문자열 생성
                    yolo_string = f'{cls_list.index(label)} {cood_string}'
                   
                    # YOLO 포맷의 문자열을 result 리스트에 추가
                    result.append(yolo_string)


 

 

 

txt 파일 확인


     
      result


 

 

라벨링 형태 변환 파일 생성(json -> txt)


       
 
        # 라벨링 형태 변환 파일 생성(json -> txt)
        if not os.path.isdir(f'{file_root}/labels'):
            os.mkdir(f'{file_root}/labels')

        for file in tqdm(file_list):
            result = []
            with open(file, 'r') as json_file:
                data = json.load(json_file)
                h = data['images']['height']
                w = data['images']['width']
                for ann in data['annotations']:
                    label = ann['damage']
                    if label in cls_list:
                        polygon_cood = ann['segmentation'][0][0][:-1]
                        cood_string = json_to_yolo_polygon(polygon_cood, w, h)
                        yolo_string = f'{cls_list.index(label)} {cood_string}'
                        result.append(yolo_string)
            if result:
                save_path = file.replace('annotations', 'labels').replace('json', 'txt')
                with open(save_path, 'w', encoding='utf-8') as f:
                    f.write('\n'.join(result))





 

 

 

훈련(train), 검증(validation), 테스트(test) 세트로 나누고, 각 파일을 해당하는 폴더로 복사하기


       
          file_list = glob.glob(f'{file_root}/labels/*.txt')
          random.shuffle(file_list)
          test_ratio = 0.1
          num_file = len(file_list)

          test_list = file_list[:int(num_file*test_ratio)]
          valid_list = file_list[int(num_file*test_ratio):int(num_file*test_ratio)*2]
          train_list = file_list[int(num_file*test_ratio)*2:]

          for i in test_list:
              label_name = i.split('/')[-1]
              shutil.copyfile(i, f'{test_root}/labels/{label_name}')
              img_name = i.split('/')[-1].replace('txt', 'jpg')
              img_path = f'{file_root}/images/{img_name}'
              shutil.copyfile(img_path, f'{test_root}/images/{img_name}')

          for i in valid_list:
              label_name = i.split('/')[-1]
              shutil.copyfile(i, f'{valid_root}/labels/{label_name}')
              img_name = i.split('/')[-1].replace('txt', 'jpg')
              img_path = f'{file_root}/images/{img_name}'
              shutil.copyfile(img_path, f'{valid_root}/images/{img_name}')

          for i in train_list:
              label_name = i.split('/')[-1]
              shutil.copyfile(i, f'{train_root}/labels/{label_name}')
              img_name = i.split('/')[-1].replace('txt', 'jpg')
              img_path = f'{file_root}/images/{img_name}'
              shutil.copyfile(img_path, f'{train_root}/images/{img_name}')


 

1. 파일 목록 가져오기 및 섞기

  • file_list = glob.glob(f'{file_root}/labels/*.txt'): file_root/labels/ 디렉토리 내의 모든 .txt 파일을 찾아서 file_list라는 리스트에 저장합니다.
  • random.shuffle(file_list): file_list에 있는 파일들의 순서를 무작위로 섞습니다.

2. 데이터셋을 테스트, 검증, 훈련 세트로 나누기

  • test_ratio = 0.1: 테스트 세트의 비율을 10%로 설정합니다.
  • num_file = len(file_list): file_list에 포함된 파일의 총 개수를 num_file 변수에 저장합니다.
  • test_list = file_list[:int(num_file*test_ratio)]: file_list에서 처음 10%에 해당하는 파일을 테스트 세트로 할당합니다.
  • valid_list = file_list[int(num_file*test_ratio):int(num_file*test_ratio)*2]: 다음 10%에 해당하는 파일을 검증 세트로 할당합니다.
  • train_list = file_list[int(num_file*test_ratio)*2:]: 나머지 80%의 파일을 훈련 세트로 할당합니다.

3. 파일을 테스트 세트 디렉토리로 복사

  • for i in test_list:: 테스트 세트에 있는 각 파일에 대해 반복합니다.
  • label_name = i.split('/')[-1]: 파일 경로에서 파일명만 추출합니다.
  • shutil.copyfile(i, f'{test_root}/labels/{label_name}'): 라벨 파일을 테스트 세트의 labels 폴더로 복사합니다.
  • img_name = i.split('/')[-1].replace('txt', 'jpg'): 라벨 파일명에서 확장자를 .txt에서 .jpg로 변경하여 이미지 파일명을 생성합니다.
  • img_path = f'{file_root}/images/{img_name}': 이미지 파일의 경로를 생성합니다.
  • shutil.copyfile(img_path, f'{test_root}/images/{img_name}'): 해당 이미지를 테스트 세트의 images 폴더로 복사합니다.

4. 파일을 검증 세트 디렉토리로 복사

  • 이 부분은 위의 테스트 세트 복사 작업과 동일한 작업을 검증 세트에 대해 수행합니다.

5. 파일을 훈련 세트 디렉토리로 복사

  • 이 부분은 위의 작업을 훈련 세트에 대해 수행합니다.
  • 주석
더보기

       

        # 라벨 파일들의 목록을 가져오고 무작위로 섞음
        file_list = glob.glob(f'{file_root}/labels/*.txt')
        random.shuffle(file_list)

        # 테스트 세트의 비율을 10%로 설정
        test_ratio = 0.1
        # 전체 라벨 파일의 개수를 계산
        num_file = len(file_list)

        # 파일 리스트의 처음 10%를 테스트 세트로 할당
        test_list = file_list[:int(num_file * test_ratio)]
        # 다음 10%를 검증 세트로 할당
        valid_list = file_list[int(num_file * test_ratio):int(num_file * test_ratio) * 2]
        # 나머지 80%를 훈련 세트로 할당
        train_list = file_list[int(num_file * test_ratio) * 2:]

        # 테스트 세트의 라벨 파일과 이미지 파일을 복사
        for i in test_list:
            # 파일 경로에서 파일명만 추출
            label_name = i.split('/')[-1]
            # 라벨 파일을 테스트 세트의 labels 폴더로 복사
            shutil.copyfile(i, f'{test_root}/labels/{label_name}')
           
            # 라벨 파일명에서 확장자를 'txt'에서 'jpg'로 변경하여 이미지 파일명 생성
            img_name = i.split('/')[-1].replace('txt', 'jpg')
            # 이미지 파일의 경로를 생성
            img_path = f'{file_root}/images/{img_name}'
            # 해당 이미지를 테스트 세트의 images 폴더로 복사
            shutil.copyfile(img_path, f'{test_root}/images/{img_name}')

        # 검증 세트의 라벨 파일과 이미지 파일을 복사
        for i in valid_list:
            # 파일 경로에서 파일명만 추출
            label_name = i.split('/')[-1]
            # 라벨 파일을 검증 세트의 labels 폴더로 복사
            shutil.copyfile(i, f'{valid_root}/labels/{label_name}')
           
            # 라벨 파일명에서 확장자를 'txt'에서 'jpg'로 변경하여 이미지 파일명 생성
            img_name = i.split('/')[-1].replace('txt', 'jpg')
            # 이미지 파일의 경로를 생성
            img_path = f'{file_root}/images/{img_name}'
            # 해당 이미지를 검증 세트의 images 폴더로 복사
            shutil.copyfile(img_path, f'{valid_root}/images/{img_name}')

        # 훈련 세트의 라벨 파일과 이미지 파일을 복사
        for i in train_list:
            # 파일 경로에서 파일명만 추출
            label_name = i.split('/')[-1]
            # 라벨 파일을 훈련 세트의 labels 폴더로 복사
            shutil.copyfile(i, f'{train_root}/labels/{label_name}')
           
            # 라벨 파일명에서 확장자를 'txt'에서 'jpg'로 변경하여 이미지 파일명 생성
            img_name = i.split('/')[-1].replace('txt', 'jpg')
            # 이미지 파일의 경로를 생성
            img_path = f'{file_root}/images/{img_name}'
            # 해당 이미지를 훈련 세트의 images 폴더로 복사
            shutil.copyfile(img_path, f'{train_root}/images/{img_name}')


 



 

프로젝트 루트 설정


     
          project_root = '/content/drive/MyDrive/1. KDT/8. 컴퓨터 비전/9. Segmentation'

 
 

 

 

Google Colab 환경에서 현재 작업 디렉토리를 Segmentation 폴더로 변경


       
        %cd /content/drive/MyDrive/1. KDT/8. 컴퓨터 비전/9. Segmentation


/content/drive/MyDrive/1. KDT/8. 컴퓨터 비전/9. Segmentation

 

 

 ultralytics 설치하기


      

      !pip install ultralytics


 

 

 

YOLOv8 모델 사용을 위해 import


       
        import yaml
        import ultralytics
        from ultralytics import YOLO

 
 

 

 

 버전확인


       
        ultralytics.checks()

 
 

 

 

 

Python에서 데이터를 YAML 형식으로 저장하기


     
        data = dict()
        data['train'] = train_root
        data['val'] = valid_root
        data['test'] = test_root
        data['nc'] = len(cls_list)
        data['names'] = cls_list

        with open(f'{project_root}/car_damage.yaml', 'w') as f:
            yaml.dump(data, f)


 

 

 

Google Colab 환경에서 현재 작업 디렉토리를 Segmentation 폴더로 변경


       

      %cd /content/drive/MyDrive/1. KDT/8. 컴퓨터 비전/9. Segmentation


 

 

 

YOLOv8 모델을 사용하여 훈련진행


       
        model = YOLO('yolov8s-seg.yaml')
        results = model.train(data='car_damage.yaml',epochs=100, batch=16, device=0, patience=30, name='yolo_s')


  • model = YOLO('yolov8s-seg.yaml'):
    • YOLO: ultralytics 라이브러리에서 제공하는 YOLO 모델 클래스를 사용하여 모델을 초기화합니다.
    • 'yolov8s-seg.yaml': YOLO 모델의 구성 파일을 지정합니다. 이 YAML 파일은 모델 아키텍처와 하이퍼파라미터를 설정하는 데 사용됩니다. 이 파일에는 모델의 종류(예: YOLOv8 small-segmentation)와 관련된 설정이 포함되어 있습니다.
  • results = model.train(data='car_damage.yaml', epochs=100, batch=16, device=0, patience=30, name='yolo_s'):
    • model.train: YOLO 모델의 train 메서드를 호출하여 모델 훈련을 시작합니다.
    • data='car_damage.yaml': 데이터 구성 파일의 경로를 지정합니다. 이 YAML 파일에는 데이터셋의 경로, 클래스 수, 클래스 이름 등이 포함되어 있습니다.
    • epochs=100: 모델을 100 에폭(epoch) 동안 훈련시킵니다. 에폭은 전체 데이터셋을 한 번 완전히 통과하는 것을 의미합니다.
    • batch=16: 배치 사이즈를 16으로 설정합니다. 이는 한 번에 모델에 입력되는 데이터의 수를 나타냅니다.
    • device=0: 모델 훈련을 수행할 장치를 지정합니다. 0은 첫 번째 GPU를 의미합니다. 만약 GPU가 없으면, device='cpu'로 설정할 수 있습니다.
    • patience=30: 조기 종료(early stopping)의 인내(patience) 값을 설정합니다. 만약 검증 성능이 30 에폭 동안 개선되지 않으면 훈련이 조기 종료됩니다.
    • name='yolo_s': 모델 훈련의 이름을 설정합니다. 이 이름은 훈련 결과와 체크포인트 파일에 사용될 수 있습니다.

 

 

YOLO 모델을 불러오기


      
        %cd /content/drive/MyDrive/1. KDT/8. 컴퓨터 비전/9. Segmentation

        project_root = '/content/drive/MyDrive/1. KDT/8. 컴퓨터 비전/9. Segmentation'
        result_folder = f'{project_root}/runs/segment'

        model = YOLO(f'{result_folder}/yolo_s/weights/best.pt')

 

 

 

 

 

성능 평가


     
      metrics = model.val(split='test')


 

 

테스트 이미지 파일 불러와서 섞은 후 예측진행


       
        %cd /content/drive/MyDrive/1. KDT/8. 컴퓨터 비전/9. Segmentation

        test_file_list = glob.glob(f'{test_root}/images/*')
        random.shuffle(test_file_list)

        test_img = cv2.imread(test_file_list[0])
        img_src = cv2.cvtColor(test_img, cv2.COLOR_BGR2RGB)
        result = model(img_src)[0]


0: 640x480 (no detections), 170.9ms
Speed: 8.1ms preprocess, 170.9ms inference, 0.9ms postprocess per image at shape (1, 3, 640, 480)



 

폴리곤을 마스크로 변환하는 데 사용되는 라이브러리 import


       
        from skimage.draw import polygon2mask


 

 

 

YOLO 모델의 예측 결과로부터 얻은 마스크를 활용하여,
     이미지에서 특정 영역을 마스킹하고 이를 시각화


     
          test_img = cv2.imread(test_file_list[11])
          img_src = cv2.cvtColor(test_img, cv2.COLOR_BGR2RGB)
          result = model(img_src)[0]

          result_mask = np.zeros(test_img.shape[:2])
          masks = result.masks

          for m in masks:
              polygon_coord = m.xy[0]
              # 주어진 이미지 크기와 폴리곤 좌표를 사용하여 해당 영역을 1로 채운 마스크를 생성
              # 나머지는 0으로 유지
              mask = polygon2mask(test_img.shape[:2], polygon_coord)
              # maximum(): 두 배열의 요소별 최대값을 반환하므로 여러 객체의 마스크가 겹치더라도 최대값을 유지
              result_mask = np.maximum(mask, result_mask)
              # 2D 마스크를 3D 배열로 변환하고 repeat() 사용해 동일한 값을 3개의 채널에 복사
          result_mask = np.repeat(result_mask[:, :, np.newaxis], 3, -1)

          plt.subplot(1, 2, 1)
          plt.imshow(img_src)
          plt.subplot(1, 2, 2)
          plt.imshow(result_mask)
          plt.show()



 

1번째 이미지 시각화


       
          project_root = '/content/drive/MyDrive/1. KDT/8. 컴퓨터 비전/9. Segmentation'
          result_folder = f'{project_root}/runs/segment'

          test_img = cv2.imread(test_file_list[0])
          img_src = cv2.cvtColor(test_img, cv2.COLOR_BGR2RGB)
          result = model(test_img)[0]

          result_mask = np.zeros(test_img.shape[:2])
          masks = result.masks

          for m in masks:
              polygon_coord = m.xy[0]
              # 주어진 이미지 크기와 폴리곤 좌표를 사용하여 해당 영역을 1로 채운 마스크를 생성
              # 나머지는 0으로 유지
              polygon_coord = np.array([[p[1], p[0]] for p in polygon_coord])
              mask = polygon2mask(test_img.shape[:2], polygon_coord)
              # maximum(): 두 배열의 요소별 최대값을 반환하므로 여러 객체의 마스크가 겹치더라도 최대값을 유지
              result_mask = np.maximum(mask, result_mask)
              # 2D 마스크를 3D 배열로 변환하고 repeat() 사용해 동일한 값을 3개의 채널에 복사
          result_mask = np.repeat(result_mask[:, :, np.newaxis], 3, -1)

          plt.subplot(1, 2, 1)
          plt.imshow(img_src)
          plt.subplot(1, 2, 2)
          plt.imshow(result_mask)
          plt.show()

 

 

 

 14번째 이미지 시각화


       
        %cd /content/drive/MyDrive/KDT 시즌3/8. 컴퓨터 비전/9. Segmentation

        project_root = '/content/drive/MyDrive/1. KDT/8. 컴퓨터 비전/9. Segmentation'
        result_folder = f'{project_root}/runs/segment'

        test_img = cv2.imread(test_file_list[13])
        img_src = cv2.cvtColor(test_img, cv2.COLOR_BGR2RGB)
        result = model(test_img)[0]

        result_mask = np.zeros(test_img.shape[:2])
        masks = result.masks

        for m in masks:
            polygon_coord = m.xy[0]
            # 주어진 이미지 크기와 폴리곤 좌표를 사용하여 해당 영역을 1로 채운 마스크를 생성
            # 나머지는 0으로 유지
            polygon_coord = np.array([[p[1], p[0]] for p in polygon_coord])
            mask = polygon2mask(test_img.shape[:2], polygon_coord)
            # maximum(): 두 배열의 요소별 최대값을 반환하므로 여러 객체의 마스크가 겹치더라도 최대값을 유지
            result_mask = np.maximum(mask, result_mask)
            # 2D 마스크를 3D 배열로 변환하고 repeat() 사용해 동일한 값을 3개의 채널에 복사
        result_mask = np.repeat(result_mask[:, :, np.newaxis], 3, -1)

        plt.subplot(1, 2, 1)
        plt.imshow(img_src)
        plt.subplot(1, 2, 2)
        plt.imshow(result_mask)
        plt.show()



 

 

 

폴리곤을 정의하는 좌표 목록 확인


       
      polygon_coord


 

 

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

17. YOLO v8을 이용한 이상행동 탐지  (0) 2024.08.12
16. YOLO v8를 활용한 안전모 탐지  (0) 2024.08.08
15. YOLO v8을 이용한 폐질환 분류  (0) 2024.08.07
14. YOLO | 객체탐지  (0) 2024.08.06
@. 과제  (0) 2024.08.05