728x90

학습데이터를 변형시켜 마치 다른 학습데이터처럼 만들기 : 한장의 사진으로 여러장의 학습데이터를 만들 수 있다.

 

import cv2
import matplotlib.pyplot as plt
import numpy as np

image = cv2.imread("image02.jpeg")
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
# #### rotation ####
# angle = 30

# h, w = image.shape[:2]
# center = (w//2, h//2)
# M = cv2.getRotationMatrix2D(center, angle, 1.0)
#     # getRotationMatrix2D(중심 좌표, 회전 각도, 크기 변환 비율)

# rotated_img = cv2.warpAffine(image, M, (w, h))
#                 # warpAffine(원본 이미지, 회전 행렬, 이미지 크기)

# plt.imshow(image)
# plt.show()

# plt.imshow(rotated_img)
# plt.show()
# #### rotation ####

#### zoom ####
# h, w = image.shape[:2]

# zoom_scale = 4 # 이미지 확대/축소 배율
# enlarged_img = cv2.resize(image, (w*zoom_scale, h*zoom_scale), interpolation=cv2.INTER_CUBIC)
#             # resize(원본 이미지, (최종 너비, 최종 높이), 이미지 보간 방법 (ex: cv2.INTER_CUBIC))
# center = [enlarged_img.shape[0] // 2, enlarged_img.shape[1] // 2]
# cut_half = 300
# zoomed_img = enlarged_img[center[0]-cut_half:center[0]+cut_half, center[1]-cut_half:center[1]+cut_half]
# plt.imshow(zoomed_img)
# plt.show()
#### zoom ####


#### shift ####

# shift = (0, 50)
# M = np.float32([
#     [1, 0, shift[0]],
#     [0, 1, shift[1]]
# ])
# # 이동 행렬: 좌측 2x2 -> 회전 행렬 (현재 단위행렬), 우측 1열: 이동 행렬 (x 변위, y 변위)

# shifted_img = cv2.warpAffine(image, M, (image.shape[1], image.shape[0]))
# plt.imshow(shifted_img)
# plt.show()
#### shift ####

#### flip ####
# flipped_img_updown = cv2.flip(image, 0) # 상하반전
# flipped_img_leftright = cv2.flip(image, 1) # 좌우반전
# flipped_img_lr_other = cv2.flip(image, -1) # 상하 & 좌우반전

# plt.imshow(image)
# plt.show()
# plt.imshow(flipped_img_updown)
# plt.show()
# plt.imshow(flipped_img_leftright)
# plt.show()
# plt.imshow(flipped_img_lr_other)
# plt.show()
#### flip ####

#### salt-and-pepper noise ####
# noise = np.zeros(image.shape, np.uint8) # uint8 = unsigned int 8-bit (부호 없는 1바이트 정수)
# cv2.randu(noise, 0, 255)
# black = noise < 30 # [True, True, False, False, False, ...] 형태의 Mask 생성
# white = noise > 225
# noise[black] = 0
# noise[white] = 255

# noise_b = noise[:, :, 0] # image.shape (h, w, c) -> h*w*c -> color channel : B, G, R
# noise_g = noise[:, :, 1]
# noise_r = noise[:, :, 2]
# noisy_img = cv2.merge([
#     cv2.add(image[:, :, 0], noise_b),
#     cv2.add(image[:, :, 1], noise_g),
#     cv2.add(image[:, :, 2], noise_r)
# ])

# plt.imshow(image)
# plt.show()
# plt.imshow(noisy_img)
# plt.show()
#### salt-and-pepper noise ####


#### Gaussian Noise ####
# mean = 0
# var = 100
# sigma = var ** 0.5

# gauss = np.random.normal(mean, sigma, image.shape)
# gauss = gauss.astype('uint8')

# noisy_img = cv2.add(image, gauss)

# plt.imshow(noisy_img)
# plt.show()
#### Gaussian Noise ####


#### 색조 변경 ####
# RGB , HSV 
# hsv_img = cv2.cvtColor(image, cv2.COLOR_RGB2HSV)
# hue_shift = 30
# hsv_img[:, :, 0] = (hsv_img[:, :, 0] + hue_shift) % 180
# rgb_img = cv2.cvtColor(hsv_img, cv2.COLOR_HSV2RGB)

# plt.imshow(image)
# plt.show()
# plt.imshow(rgb_img)
# plt.show()
#### 색조 변경 ####


#### 색상 변환 ####
# hsv_img = cv2.cvtColor(image, cv2.COLOR_RGB2HSV)

# # hsv[h, w, c]
# hsv_img[:, :, 0] += 50 # Hue -> 50도 증가
# hsv_img[:, :, 1] = np.uint8(hsv_img[:, :, 1] * 0.5)  # 채도
# hsv_img[:, :, 2] = np.uint8(hsv_img[:, :, 2] * 1.5)  # 밝기

# # imshow <- BGR / RGB 로 강제로 디코딩
# rgb_img = cv2.cvtColor(hsv_img, cv2.COLOR_HSV2RGB)
# plt.imshow(rgb_img)
# plt.show()
#### 색상 변환 ####


#### 이미지 크롭 ####
# x, y, w, h = 300, 300, 200, 200  # (100, 100) 좌표에서 (200 * 200) 크기로 자를 것임
# crop_img_wide = image[y-h:y+h, x-w:x+w] # (x, y) 를 중심으로 2w, 2h 크기로 자름
# crop_img_lt = image[y:y+h, x:x+w] # (x, y) 를 기점으로 (w, h) 만큼 오른쪽 아래로 간 크기로 자름

# plt.imshow(image)
# plt.show()
# plt.imshow(crop_img_wide)
# plt.show()
# plt.imshow(crop_img_lt)
# plt.show()
#### 이미지 크롭 ####

#### warpAffine ####
# x_diff = 50
# y_diff = 100
# h, w, c = image.shape
# M = np.float32([
#     [1, 0, x_diff],
#     [0, 1, y_diff]
# ]) # x축으로 50, y 축으로 100 이동하는 병진이동행렬
# shifted_img = cv2.warpAffine(image, M, (w, h))

# M = cv2.getRotationMatrix2D((w // 2, h // 2), 45, 1.0)
# rotated_img = cv2.warpAffine(image, M, (w, h))

# M = cv2.getRotationMatrix2D((w // 2, h // 2), 0, 0.5)
# halfed_img = cv2.warpAffine(image, M, (w, h), flags=cv2.INTER_AREA) # 가장자리를 검은색으로 칠한, 원본 이미지 크기와 같은 축소 이미지
# croped_img = halfed_img[h//2 - h//4 : h//2 + h//4, 
#                         w//2 - w//4 : w//2 + w//4] # 가장자리를 잘라낸 이미지

# resized_img = cv2.resize(image, (w//2, h//2), interpolation=cv2.INTER_AREA)
# plt.imshow(image)
# plt.show()
# plt.imshow(shifted_img)
# plt.show()
# plt.imshow(rotated_img)
# plt.show()
# plt.imshow(resized_img)
# plt.show()
# plt.imshow(halfed_img)
# plt.show()
# plt.imshow(croped_img)
# plt.show()
#### warpAffine ####

#### blurring ####
# blur_img = cv2.GaussianBlur(image, (5, 5), 5)

# plt.imshow(blur_img)
# plt.show()
#### blurring ####

#### adaptive threshold ####
# img_gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)

# thresh = cv2.adaptiveThreshold(img_gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 11, 2)
# # ADAPTIVE_THRESH_MEAN_C: 적응형 임계값 처리, 임계값 기준을 평균치를 사용함
# # 인자 11: 블록 크기, 11x11 블록으로 이미지를 나눈 후 해당 영역
# plt.imshow(img_gray, 'gray')
# plt.show()
# plt.imshow(thresh, 'gray')
# plt.show()
#### adaptive threshold ####


#### 색온도 보정 ####
# org_img = image.copy()
# balance = [0.8, 0.7, 0.8]

# for i, value in enumerate(balance):
#     if value != 1.0:
#         org_img[:, :, i] = cv2.addWeighted(org_img[:,:,i], value, 0, 0, 0)
#                             # addWeighted: src에 대해 value만큼의 가중치로 색온도 조절

# plt.imshow(org_img)
# plt.show()
#### 색온도 보정 ####


#### 모션 블러 ####
# kernal_size = 15
# kernal_direction = np.zeros((kernal_size, kernal_size))
# kernal_direction[int((kernal_size)//2), :] = np.ones(kernal_size)
# kernal_direction /= kernal_size # 커널의 합이 1이 되도록
# kernal_matrix = cv2.getRotationMatrix2D((kernal_size/2, kernal_size/2), 45, 1)
# kernal = np.hstack((kernal_matrix[:, :2], [[0], [0]]))
#         # kernal_matrix[:, :2] <- 회전 행렬에서 병진이동 벡터를 제외하고 회전 행렬 값만 가져옴
#         # [[0],[0]] <- 병진이동 벡터 (이동 X)
# kernal = cv2.warpAffine(kernal_direction, kernal, (kernal_size, kernal_size))

# motion_blur_img = cv2.filter2D(image, -1, kernal)
# plt.imshow(motion_blur_img)
# plt.show()
#### 모션 블러 ####


#### 난수 노이즈 ####
# gray_img = cv2.imread('image02.jpeg', cv2.IMREAD_GRAYSCALE)
# h, w = gray_img.shape

# mean = 0
# var = 100
# sigma = var ** 0.5

# gaussian = np.random.normal(mean, sigma, (h, w))
# noisy_image = gray_img + gaussian.astype(np.uint8)
# # uint8 -> 0 ~ 255
# cv2.imshow("", noisy_image)
# cv2.waitKey()
#### 난수 노이즈 ####

#### 채도 조정 ####
# img = cv2.imread('image02.jpeg')
# org_img = img.copy()

# img_hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
# saturation_factor = 1.5
# img_hsv[:, :, 1] = img_hsv[:, :, 1] * saturation_factor

# saturated_img = cv2.cvtColor(img_hsv, cv2.COLOR_HSV2BGR)

# cv2.imshow("", org_img)
# cv2.waitKey()
# cv2.imshow("", saturated_img)
# cv2.waitKey()
#### 채도 조정 ####


#### 밝기 조정 ####
# img = cv2.imread('image02.jpeg')
# org_img = img.copy()

# bright_diff = 50
# img_brighten = cv2.convertScaleAbs(img, alpha=1, beta=bright_diff)

# cv2.imshow("org", org_img)
# cv2.imshow("brighten", img_brighten)
# cv2.waitKey()
#### 밝기 조정 ####

#### 노이즈 제거 ####
# img_filtered = cv2.medianBlur(image, 5)
# plt.imshow(image)
# plt.show()
# plt.imshow(img_filtered)
# plt.show()
#### 노이즈 제거 ####

#### 히스토그램 균일화 ####
# img_gray = cv2.imread("image02.jpeg", cv2.IMREAD_GRAYSCALE)
# img_equalized = cv2.equalizeHist(img_gray)

# cv2.imshow("org", img_gray)
# cv2.imshow("hist_equal", img_equalized)
# cv2.waitKey()
#### 히스토그램 균일화 ####
728x90
728x90

일반적으로 정사각형으로 만들면 화면비율이 깨짐

그런걸 방지하기 위해서 남는 부분은 다른 색으로 칠해버림

import matplotlib.pylab as plt
from PIL import Image

def expend2square(pil_img, background_color) :  # 배경이미지 크기계산
    width, heigth = pil_img.size
    
    if width == heigth :   # 이미 정사각형
        return pil_img
    
    elif width > heigth :  # 너비가 > 높이인 경우
        result = Image.new(pil_img.mode, (width, width), background_color)
        result.paste(pil_img, (0, (width - heigth) // 2))   # x 좌표는 0, y 좌표는 이미지 중앙에 이미지 붙임
        return result
    else :          # 높이가 > 너비인 경우
        result = Image.new(pil_img.mode, (heigth, heigth), background_color)
        result.paste(pil_img, ((heigth - width) //2,0))    # x 좌표는 이미지 중앙, y 좌표는 0 에 이미지 붙임
        return result
        

def resize_with_padding(pil_img, new_size, background_color) :  # 남는부분에 색칠하기
    img = expend2square(pil_img, background_color)
    img = img.resize((new_size[0], new_size[1]), Image.ANTIALIAS)
    
    return img
    
    
    
    
img = Image.open("./image01.jpeg")
img_new = resize_with_padding(img, (300,300), (0,0,255))  # 300, 300 : 사진 크기  # 0,0,255 : RGB 

plt.imshow(img)
plt.show()

plt.imshow(img_new)
plt.show()
728x90
728x90

XML Extensible Markup Language 어로, 데이터를 장하고 전하는 데 사용되는 마크업 언어입니다.

 

HTML과 매우 유사하 지만, XML은 데이터와 문서 구조를 설명하는 데 중점을 니다.

XML 스트 기반 형식이며, 데이터와 그 구조를 기하는 데 사용할 수 있는 여러가지 태그와 성을 제공합니다. 데이터는 요소(element)라고도 르는 태그를 사용하여 표시되며, 요소 는 (attribute) (value)을 가질 수 있습니다.

XML은 데이터를 계 구조로 구성할 수 있으, 다양한 소어 시스템 간에 데이터를 환하는 데 매우 유용합니다. , XML은 데이터의 검증  검색이 용이하며, 분의 로그래 어에서 XML 파 서를 지원하로 데이터를 게 처리할 수 있습니다.

 

 

import os 
import cv2
import matplotlib.pylab as plt
from xml.etree.ElementTree import parse

def xml_read(xml_path) :
    
    root = parse(xml_path).getroot()
    
    image_info = root.findall("image")
    
    for image in image_info :
        bbox = image.findall('box')
        # <image id="0" name="01.jpg" width="640" height="480">
        
        # image width height 
        image_width = image.attrib['width']
        image_heigth = image.attrib['height']
        
        # image name and path 
        image_name = image.attrib['name']
        image_name = os.path.join("./data/", image_name)
        
        # image read 
        image = cv2.imread(image_name)
        # image BGR -> RGB 
        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
        
        for box_info in bbox :
            label = box_info.attrib['label']
            
            # 값 -> string 타입 
            xtl = box_info.attrib['xtl']
            ytl = box_info.attrib['ytl']
            xbr = box_info.attrib['xbr']
            ybr = box_info.attrib['ybr']
            
            # 소수점이 포함이라 바로 int 값 변환 불가 하여 float 변환 
            xtl_f = float(xtl)
            ytl_f = float(ytl)
            xbr_f = float(xbr)
            ybr_f = float(ybr)
            
            # float -> int 변환 
            xtl_i = int(xtl_f)
            ytl_i = int(ytl_f)
            xbr_i = int(xbr_f)
            ybr_i = int(ybr_f)
            
            print(xtl_i, ytl_i, xbr_i, ybr_i, label)
            ### xtl="468.94" ytl="92.01" xbr="640.00" ybr="340.46"
            
            ### 이미지 시각화 
            image = cv2.rectangle(image, (xtl_i, ytl_i), (xbr_i, ybr_i), (0,255,0), 2)
            
            ### 라벨 추가 
            image = cv2.putText(image, label, (xtl_i, ytl_i-10), 
                  cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 255), 2, cv2.LINE_AA)
         
        plt.imshow(image)
        plt.show()
    
xml_read("./data/annotations.xml")
 

xml to yolo format 변경하기 

 

import os 
import cv2
import matplotlib.pylab as plt
from xml.etree.ElementTree import parse

label_number_dict = {'cat':0, 'dog':1}

def xml_read(xml_path) :
    
    root = parse(xml_path).getroot()
    
    image_info = root.findall("image")
    
    for image in image_info :
        bbox = image.findall('box')
        # <image id="0" name="01.jpg" width="640" height="480">
        
        # image width height 
        image_width = image.attrib['width']
        image_heigth = image.attrib['height']
        
        # image name and path 
        image_name = image.attrib['name']
        image_name_temp = image_name
        image_name = os.path.join("./data/", image_name)
        
        # image read 
        image = cv2.imread(image_name)
        # image BGR -> RGB 
        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
        
        for box_info in bbox :
            label = box_info.attrib['label']
            
            # 값 -> string 타입 
            xtl = box_info.attrib['xtl']
            ytl = box_info.attrib['ytl']
            xbr = box_info.attrib['xbr']
            ybr = box_info.attrib['ybr']
            
            # 소수점이 포함이라 바로 int 값 변환 불가 하여 float 변환 
            xtl_f = float(xtl)
            ytl_f = float(ytl)
            xbr_f = float(xbr)
            ybr_f = float(ybr)
            
            # float -> int 변환 
            x1_i = int(xtl_f)
            y1_i = int(ytl_f)
            x2_i = int(xbr_f)
            y2_i = int(ybr_f)
            
            ### xtl="468.94" ytl="92.01" xbr="640.00" ybr="340.46"
            
            # 이미지 사이즈가 필요 위에 있는 image_width, image_heigth 경우는 string 타입 형변환 필요 int 
            img_width_i = int(image_width)
            img_height_i = int(image_heigth)
            
            # Pascal_xyxy to YOlO center_x center_y yolo_w yolo_h 
            
            center_x = ((x2_i + x1_i)/(2*img_width_i))
            center_y = ((y2_i + y1_i)/(2*img_height_i))
            yolo_w = (x2_i - x1_i)/img_width_i
            yolo_h = (y2_i - y1_i)/img_height_i
                                    
            # file_name 
            image_name_temp = image_name_temp.replace('.jpg', '')
            
            # label cat, dog -> 0, 1 로 변경하기 
            label_number = label_number_dict[label]
            
            print("Pascal_xyxy to YOLO >> ", label_number,center_x, center_y, yolo_w, yolo_h)
    
            # 텍스트로 저장하기 
            with open(f"{image_name_temp}.txt", "a") as f:
                f.write(f"{label_number} {center_x} {center_y} {yolo_w} {yolo_h} \n")
    
xml_read("./data/annotations.xml")

Pascal_xyxy to YOLO >> 1 / 0.865625 / 0.45 / 0.26875 / 0.5166666666666667

Pascal_xyxy to YOLO >> 0 / 0.16171875 / 0.6041666666666666 / 0.3140625 / 0.44583333333333336

728x90
728x90

JSON(JavaScript Object Notation)은 경의 데이터 환 형식 입니다.

 

JSON은 사이 읽고 기에 용이하고, 기계가 분석하고 생성 하기도 쉬워 많이 사용됩니다.

특히 웹에서 데이터를 많이 사용되며, 분의 로그래어에서 JSON 형식을 다수 있습니다.

JSON은 키-값 쌍으로 이루어진 데이터 오브젝트를 장합니다. (key)는 문자이며, (value)은 문자, , 불리, , 객체 등이 수 있습니다. 이러한 데이터 오브젝트들은 중수 있어 복한 데이터도 표현할 수 있습니다.

 

 

import json

# json 파일을 가져와야합니다.
json_data_path ="./data/instances_default.json"

with open(json_data_path, 'r', encoding="utf-8") as j :  # 'r' read
    json_data = json.load(j)
    
print(f"json type : {type(json_data)}")
print("json_data : ", json_data )  # 키, 밸류로 반환

다차원 딕셔너리 형태라 원하는 정보를 위해선 한차원 더 들어가야합니다.

# 변수 선언
categories_info = json_data['categories']
# [{'id': 1, 'name': 'cat', 'supercategory': ''}, {'id': 2, 'name': 'dog', 'supercategory': ''}]

images_info = json_data['images']
# [{'id': 1, 'width': 640, 'height': 480, 'file_name': '01.jpg', 'license': 0, 'flickr_url': '', 'coco_url': '', 'date_captured': 0}]

 

 

위의 정보를 이용하여 이미지 시각화 실습

 

import json 
import os
import cv2
import matplotlib.pylab as plt

# json_path 경로 지정 
json_path = "./data/instances_default.json"

# json 읽기
with open(json_path, 'r', encoding='utf-8') as j : # 'r' : read
    json_data = json.load(j)
    
category_info = json_data['categories']
images_info = json_data['images']
annotations_info = json_data['annotations']

# 라벨 딕셔너리 선언 
label_dict = {1: "cat", 2:"dog"}  # 0 은 배경임

for image_json in images_info : 
    print(image_json)
    # {'id': 1, 'width': 640, 'height': 480, 'file_name': '01.jpg', 'license': 0, 'flickr_url': '', 'coco_url': '', 'date_captured': 0}

    file_name = image_json['file_name']
    image_path = os.path.join("./data/", file_name)
    image_id = image_json['id']
    print(image_path)
    # ./data/01.jpg
    
    # image read 
    image = cv2.imread(image_path)
    # iamge BGR -> RGB 
    image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
    
    # bbox info 
    for anno_json in annotations_info : 
        if image_id == anno_json['image_id'] :
            bbox = anno_json['bbox']
            # 좌표 변수에 박스 좌표 저장 (int 형 변환 이유 : cv2.rectangle 좌표 값은 int 형태만 가능)
            x = int(bbox[0])
            y = int(bbox[1])
            w = int(bbox[2])
            h = int(bbox[3])
            # 박스 좌표 확인 
            print("bbox 좌표 >> " , x, y, w, h)
            # bbox 좌표 >>  468 92 171 248
            # bbox 좌표 >>  3 183 200 214 
            
            
            # 박스 그리기 
            cv2.rectangle(image, (x,y), (x+w, y+h), (0,255,0),2)
            
            # 라벨 표시 
            category_id = anno_json['category_id']
            label_name = label_dict[category_id]
            print(label_name)
            # dog
            # cat 
            
            image = cv2.putText(image, label_name, (x, y-10),  # 위에 글자두려고 -10 
                  cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 255), 2, cv2.LINE_AA)
            
            
    plt.imshow(image)
    plt.show()

 

 

json format -> Yolo format 으로 변경하고 텍스트 파일로 저장하기

import json 
import os
import cv2
import matplotlib.pylab as plt

# json_path 경로 지정 
json_path = "./data/instances_default.json"

# json 읽기
with open(json_path, 'r', encoding='utf-8') as j : 
    json_data = json.load(j)
    
category_info = json_data['categories']
images_info = json_data['images']
annotations_info = json_data['annotations']

# 라벨 딕셔너리 선언 
# 0 -> cat , 1 -> dog
label_dict = {1: 0, 2: 1}

for image_json in images_info : 
    print(image_json)
    file_name = image_json['file_name']
    image_path = os.path.join("./data/", file_name)
    image_id = image_json['id']
    print(image_path)
    print("file name ", file_name)
    
    # image read 
    image = cv2.imread(image_path)
    # iamge BGR -> RGB 
    image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
    
    # image size 
    img_height, img_width, img_channel = image.shape
    
    # bbox info 
    for anno_json in annotations_info : 
        if image_id == anno_json['image_id'] :
            bbox = anno_json['bbox']
            # 좌표 변수에 박스 좌표 저장 (int 형 변환 이유 : cv2.rectangle 좌표 값은 int 형태만 가능)
            x = int(bbox[0])
            y = int(bbox[1])
            w = int(bbox[2])
            h = int(bbox[3])
            
            # 박스 그리기 
            cv2.rectangle(image, (x,y), (x+w, y+h), (0,255,0),2)
            
            # 라벨 표시 
            category_id = anno_json['category_id']
            label_number = label_dict[category_id]
            
            # xywh -> center_x, center_y, w, h 변경 하기 
            center_x = ((2*x + w)/(2*img_width))
            center_y = ((2*y + h)/(2*img_height))
            yolo_w = w/img_width
            yolo_h = h/img_height
            
            print("yolo 좌표 변경 값 >> ",label_number,center_x, center_y, yolo_w, yolo_h)
            # 이미지 명과 라벨 파일 명이 동일해야합니다. 
            # 위에 file_name 경우는 01.jpg 우리가 필요한것은 01 이라는 이름 입니다. 
            #file_name_tmep = os.path.splitext(file_name)[0]
            file_name_temp = file_name.replace(".jpg", "")
            
            # 텍스트 파일 쓰기 
        with open(f"{file_name_temp}.txt", "a") as f:  # "a" 는 덮어쓰기 말고 새로만듬
            f.write(f"{label_number} {center_x} {center_y} {yolo_w} {yolo_h} \n")
728x90
728x90

학습을  위해 대량의 사진을 가져오기 위한 코드

 

 

일반적으로 사진을 그냥 막 가져와버리면 정렬이 제대로 안됨

 

우선 사과라는 폴더안에 있는 사진들을 가져오고 싶을때

# os listdir
import os
# 이미지가 저장된 디렉토리 경로
img_dir = './사과/'

# 디렉토리 내 모든 파일 목록 가져오기
file_list = os.listdir(img_dir)
print(file_list)

# 단점 정렬 되지 않습니다.

 

sorted를 써도 마찬가지

# 만약 정렬 하고 싶다면 sort 함수 사용 
# os listdir
import os
# 이미지가 저장된 디렉토리 경로
img_dir = './사과/'

# 디렉토리 내 모든 파일 목록 가져오기
file_list = sorted(os.listdir(img_dir))
print(file_list)

 

 

import glob
import os 

file_list = glob.glob(os.path.join("./사과/", "*.jpg"))
print(file_list)

# 을 활용해야 제대로 정렬된 상태로 가져옴

 

 

폴더안의 폴더도 for문으로 가능함

#### os.walk 를 이용한 폴더에서 이미지 파일 가져오기 함수 구현

os.walk() 하위의 폴더들을 for문으로 탐색할 수 있게 해줍니다. 인자로 전달된 path에 대해서 다음 3개의 값이 있는 tuple을 넘겨줍니다.

- root : dir과 files가 있는 path
- dirs : root 아래에 있는 폴더들
- files : root 아래에 있는 파일들

 

def get_img_paths(root_path): # 하위에 있는 경로 모두 탐색
    file_paths = []
    for (path, dir, files) in os.walk(root_path):
        for file in files:
            ext = os.path.splitext(file)[-1].lower()
            formats = ['.bmp', '.jpg', '.jpeg', '.png', '.tif', '.tiff', '.dng']
            if ext in formats:
                file_path = os.path.join(path, file)
                file_paths.append(file_path)
    return file_paths

file_paths = get_img_paths("./사과/")
print(file_paths)

# 정렬 하고 싶다면 natsort.natsorted 이용
# file_paths_sort = natsort.natsorted(file_paths)
# print(file_list_sort)
728x90
728x90

알고리즘은 컴퓨터 전 및 이미지 처리에서 주요한 역할을 합니다.

 

 

ORB (Oriented FAST and Rotated BRIEF):

 

 

1. FAST(FeaturesfromAcceleratedSegmentTest)기와BRIEF(BinaryRobustIndependent Elementary Features) 자의 합입니다.

2. FAST를 사하여 르게 특점을 하고, BRIEF를 사하여 특점 주변의 특설명합니다.

3. 회전에 변한 특설명을 제공합니다.
4. ORB
SIFT SURF더 빠르지만, 적으로 한 결과를 제공합니다.

 

import cv2

# 동영상 파일 열기
cap = cv2.VideoCapture("MS/CV/0612 객체탐지,추적/data/vtest.avi")

# ORB 객체 생성
orb = cv2.ORB_create()

while True:
    # 프레임 읽기
    ret, frame = cap.read()
    if not ret:
        break
        
    # 그레이스케일로 변환
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    # 특징점 검출
    keypoints = orb.detect(gray, None)

    # 특징점 그리기
    frame = cv2.drawKeypoints(frame, keypoints, None, (0, 150, 220), flags=0)

    # 출력
    cv2.imshow("ORB", frame)
    if cv2.waitKey(30) & 0xFF == ord("q"):
        break

cap.release()
cv2.destroyAllWindows()

를 쓰면 불필요한 특징점도 많이 나온다.

 

Mask를 활용하여 특징점 제거하기 2

 

 

import cv2
import numpy as np

# 동영상 파일 읽기
cap = cv2.VideoCapture("MS/CV/0612 객체탐지,추적/data/vtest.avi")

# ORB 객체 생성
orb = cv2.ORB_create()

# 특징점 최소 크기 설정
min_keypoint_size = 10

# 중복 특징점 제거 기준거리
duplicate_threshold = 10

while True:
    # 프레임 읽기
    ret, frame = cap.read()
    if not ret:
        break

    # 그레이스케일로 변환
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    # 특징점 검출
    keypoints = orb.detect(gray, None)

    # 특징점 크기가 일정 크기 이상인 것만 남기기
    keypoints = [kp for kp in keypoints if kp.size > min_keypoint_size]  # 리스트 컴프리헨션(파이썬문법)

    # 중복된 특징점 제거
    mask = np.ones(len(keypoints), dtype=bool)  # 1차원 배열
    for i, kp1 in enumerate(keypoints):
        if mask[i]:
            for j, kp2 in enumerate(keypoints[i + 1:]):
                if (
                    mask[ i + j + 1]
                    and np.linalg.norm(np.array(kp1.pt) - np.array(kp2.pt)) < duplicate_threshold  # .pt : OpenCV의 KeyPoint 객체의 속성중 하나
                ):
                    mask[ i + j + 1] = False
    
    # kp1.pt와 kp2.pt는 각각 두 개의 키포인트 객체인 kp1과 kp2의 위치 좌표를 나타냅니다.
    """
 먼저, mask라는 길이가 keypoints의 길이와 동일한 불리언 배열을 생성합니다. 이 배열은 모든 원소를 True로 초기 화합니다.
그런 다음, keypoints 리스트를 반복하면서 현재 키포인트와 나머지 키포인트들 간의 거리를 계산하여 중복된 키포 인트를 확인합니다. 
중복된 키포인트인 경우에는 해당 키포인트에 해당하는 mask의 원소를 False로 설정합니다.
마지막으로, mask를 기반으로 중복되지 않은 키포인트들만을 새로운 리스트로 필터링하여 keypoints를 업데이트 합니다.
이를 통해 중복된 특징점을 제거하고 유니크한 특징점만을 남기는 작업을 수행합니다.
    
    """
    keypoints = [kp for i, kp in enumerate(keypoints) if mask[i]]

    # 특징점 그리기
    frame = cv2.drawKeypoints(frame, keypoints, None, (0, 200, 150), flags=0)

    cv2.imshow("ORB", frame)


    # 'q'를 누르면 종료
    if cv2.waitKey(60) == ord('q'):
        break

# 해제
cap.release()
cv2.destroyAllWindows()

 

 

 

728x90
728x90

 

알고리즘은 컴퓨터 전 및 이미지 처리에서 주요한 역할을 합니다.

SIFT (Scale-Invariant Feature Transform):

 

1. 크기 및 회전에 변한 특설명 알고리즘입니다.

2. 다양한 크기와 회전에서 특점을 하고,점 주변의 지역 특을 기합니다.

3. 점 간의 일기 위해 특점 기자를 사합니다.
4. SIFT
우 강력한 특및 일알고리즘으로 알져 있습니다.

 

 

import cv2

# 동영상 파읽 열기
cap = cv2.VideoCapture("MS/CV/0612 객체탐지,추적/data/slow_traffic_small.mp4")

# sift 객체 생성
sift = cv2.SIFT_create()

while True:
    # 프레임 읽기
    ret, frame = cap.read()
    if not ret:
        break

    # 그레이스케일로 변환
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    # 특징점 검출
    keypoints, descriptors = sift.detectAndCompute(gray, None)

    # 특징점 그리기
    frame = cv2.drawKeypoints(frame, keypoints, None,
                              flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)

    # 화면에 출력
    cv2.imshow("frame", frame)

    # 'q'를 누르면 종료
    if cv2.waitKey(60) == ord('q'):
        break

# 해제
cap.release()
cv2.destroyAllWindows()

 

 

개수제한 >>>

 

1. 이미지 대비 밝기 일정이상의 차이가 있을때만 보이게 하면서

2. 포인터를 수를 일정 수로 제한해서 포인터의 개수를 특정 객체에만 나타나게 설정

 

import cv2

cap = cv2.VideoCapture("MS/CV/0612 객체탐지,추적/data/slow_traffic_small.mp4")

# SIFT 객체 생성
sift = cv2.SIFT_create(contrastThreshold=0.02)   # 이미지 대비의 밝기 차이

# 특지점 개수 제한 설정
max_keypoints = 100  # 100개의 특징점만 검출

while True:
    # 프레임 읽기
    ret, frame = cap.read()
    if not ret:
        break

    # 그레이스케일로 변환
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    # 특징점 검출
    keypoints, descriptors = sift.detectAndCompute(gray, None)

    # 특징점 제한
    if len(keypoints) > max_keypoints:
        keypoints = sorted(keypoints, key=lambda x: -
                           x.response)[:max_keypoints]


    """
    keypoints = sorted(keypoints, key=lambda x: -x.response): 
    keypoints 리스트를 x.response를 기준으로 내림차순으로 정렬
    이는 키포인트의 response 값을 기준으로 정렬하겠다는 의미
    response 값이 큰 키포인트일수록 우선순위를 가지게 됩니다

    [:max_keypoints]: 정렬된 keypoints 리스트에서 처음부터 max_keypoints까지의 키포인트만 선택 
    이를 통해 최대 키포인트 수를 제한합니다.
    """
    
    
    # 특징점 그리기
    frame = cv2.drawKeypoints(frame, keypoints, None,
                              flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)

    # 프레임 출력
    cv2.imshow("frame", frame)

    # 'q'를 누르면 종료
    if cv2.waitKey(60) == ord('q'):
        break

# 해제
cap.release()
cv2.destroyAllWindows()

 

 

728x90
728x90

# 객체 추적 알고리즘 소

움직이는 객체식별하고, 그 위적하는 방법을 의미합니다. 이를 해 동상이나 실시간 스트리데 이터에서 객체움직지하고, 객체적하는데 사됩니다. 다음은 일적으로 사되는 몇 가지 객 체 추적 알고리즘입니다.

 

점 기반 추(Feature-based Tracking):

  1. 점기반 추적은객 체의 특점을 하고, 이를 기으로 객체적합니다.
  2. SIFT (Scale-Invariant Feature Transform), SURF (Speeded-Up Robust Features), ORB (Oriented FAST and Rotated BRIEF) 등의 알고리즘을 사하여 특점을 합니다.
  3. 이 특점들은 다음 프에서 아지며, 객체움직적합니다.
  4. 점의 일도와 거리를 기으로 가장 좋은는 알고리즘을 사합니다.

 

# 점 기반 추

점 기반 추(Feature-based Tracking)에서 일적으로 르는 서는 다음과 같습니다

기화 :
1.
이미지로 변합니다.
2. Shi-Tomasi
기 또는 다방법을 사하여 적 지점을합니다.

3. 적할 특점의 기위를 저장합니다.

 

 

import cv2
import numpy as np

# 동영상 파일 읽기
cap = cv2.VideoCapture("MS/CV/0612 객체탐지,추적/data/slow_traffic_small.mp4")

# 코너 검출기 파라미터 설정
feature_params = dict(maxCorners=100, qualityLevel=0.3,
                      minDistance=7, blockSize=7)
"""
maxCorners: 검출할 최대 특징점 수를 지정. 여기서는 최대 100개의 특징점을 검출하도록 설정
qualityLevel: 특징점으로 인정되기 위한 품질 기준. 0과 1 사이의 값,높을수록 특징점으로 인정되기 위한 조건이 엄격
minDistance: 검출된 특징점들 간의 최소 거리를 나타냄 이 거리보다 가까운 특징점은 제거
blockSize: 특징점 검출 시 사용되는 이웃 픽셀 블록의 크기. 특징점 검출 알고리즘에서 사용되는 계산에 영향을 미치는 요소
"""


# 광학 흐름 파라미터 설정
lk_params = dict(winSize=(30, 30), maxLevel=2, criteria=( # 알고리즘 중지기준
    cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03))  # eps정확도가 criteria[0]보다 작을때까지 or count는 반복회수가 criteria[1]보다 작을때 까지 추적
"""
winSize=(30, 30): 이동 벡터를 추정하기 위해 사용되는 윈도우(window)의 크기
윈도우 크기는 광학 흐름 알고리즘에서 이웃 픽셀들 간의 관계를 분석하는 데 사용되는 영역의 크기를 조절 

maxLevel=2: 피라미드 계층의 수
광학 흐름 알고리즘은 다단계의 피라미드 구조를 사용하여 이미지의 해상도를 다양하게 처리


"""
    

# 첫 프레임 읽기
ret, next_frame = cap.read()
prev_gray = cv2.cvtColor(next_frame, cv2.COLOR_BGR2GRAY)

# 초기 추적 지점 선택
prev_corners = cv2.goodFeaturesToTrack(prev_gray, mask=None, **feature_params)
prev_points = prev_corners.squeeze()

# 추적 결과를 표시하기위한 색상 설정
color = (0, 200, 0)

while True:
    # 다음 프레임 읽기
    ret, next_frame = cap.read()
    if not ret:
        break

    # 현재 프레임 변환
    gray = cv2.cvtColor(next_frame, cv2.COLOR_BGR2GRAY)

    # 옵티컬 플로우 계산
    next_points, status, err = cv2.calcOpticalFlowPyrLK(
        prev_gray, gray, prev_points, None, **lk_params)

    # 추적 결과를 좋은 포인트로 필터링
    for i, (prev_point, next_point) in enumerate(zip(prev_points, next_points)):
        x_prev, y_prev = prev_point.astype(np.int32)
        x_next, y_next = next_point.astype(np.int32)

        # cv2.line(prev_frame, (x_prev, y_prev), (x_next, y_next), color, 2)
        cv2.circle(next_frame, (x_next, y_next), 3, color, 3)

    # 화면에 출력
    cv2.imshow("OpticalFlow-LK", next_frame)

    # 다음 프레임을 위한 프레임과 포인트 저장
    prev_gray = gray.copy()
    prev_points = next_points

    # 'q'를 누르면 종료
    if cv2.waitKey(60) == ord('q'):
        break

# 해제
cap.release()
cv2.destroyAllWindows()

728x90
728x90

# 객체 추적 알고리즘 소

움직이는 객체식별하고, 그 위적하는 방법을 의미합니다. 이를 해 동상이나 실시간 스트리데 이터에서 객체움직지하고, 객체적하는데 사됩니다. 다음은 일적으로 사되는 몇 가지 객 체 추적 알고리즘입니다.

 

만 필터 (Kalman Filter Tracking):


1.
만필터는 상태정에 사되는 필터, 객체추적에도 적됩니다.
2.
예측과 실제관을 기으로 객체의 위와 속도를 정합니다.
3.
예측과 관간의 오를 고하여 정한 위를 업데이트합니다.
4.
이를 움직이는 객체의 경로를 적하고, 예측불확실성을 줄입니다.

 

측정 행렬(Measurement Matrix): 측정 행렬은 시스템의 상태를 측정값으로 변환하는 역할을 합니다. 측정 행렬은 상태 벡터와 측정 벡터 사이의 선형 변환을 정의합니다. 일반적으로 센서로부터 얻은 측정값을 상태 벡터의 선형 조합으로 표현하는 데 사용됩니다. 측정 행렬은 시스템의 동작과 측정 방식에 따라 결정되며, 변하지 않는 고정된 행렬입니다.

전이 행렬(Transition Matrix): 전이 행렬은 시스템의 상태를 현재 상태에서 다음 상태로 변환하는 역할을 합니다. 전이 행렬은 시스템의 동적 모델을 반영하여 상태 벡터를 현재 상태에서 다음 상태로 예측하는 데 사용됩니다. 전이 행렬은 시간에 따라 변할 수 있으며, 시스템의 동작을 모델링하는 데 사용되는 다른 행렬들과 연결되어 시스템의 상태 추정에 영향을 미칩니다.

 

import cv2
import numpy as np

# kalman filter
kalman = cv2.KalmanFilter(4,2)  # 상태백터(위치와 속도 등)를 4차원으로 지정, 측정벡터(센서신호) 2차원으로 세팅) 

# 측정 행렬을 설정합니다. 이 행렬은 측정 벡터를 상태 벡터로 변환하는 역할
kalman.measurementMatrix = np.array([[1,0,0,0],[0,1,0,0]],np.float32)  
# 전이 행렬을 설정합니다. 이 행 렬은 시간에 따라 상태 벡터가 어떻게 변화하는지를 나타냄
kalman.transitionMatrix = np.array([[1,0,1,0],[0,1,0,1],[0,0,1,0],[0,0,0,1]],np.float32) 
# 프로세스 잡음 공분산 행렬을 설정합니다. 이 값은 시스템의 불확실성을 모델링
kalman.processNoiseCov = np.array([[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]],np.float32) * 0.05


# 칼만 필터 추적 실습
# 영상 파일 열기
cap = cv2.VideoCapture("MS/데이터전처리/0612/data/slow_traffic_small.mp4")

# 첫 프레임에서 추적할 객체 선택
ret, frame = cap.read()
print(ret, frame) # 경로가 잘못된 경우 ret = False, frame = None / 정상일경우 ret = True, frame = 영상프레임

x, y, w, h = cv2.selectROI(frame, False, False)

"""
"Select Object": 객체를 선택할 때 표시될 창의 제목입니다.
frame: 이미지나 비디오 프레임을 나타내는 변수입니다.
False: 선택한 영역을 자동으로 크롭하지 않고, 선택한 영역의 좌표와 크기를 반환합니다.
False: 마우스 이벤트를 사용하여 객체의 영역을 선택할 수 있도록 합니다.
"""
print("선택한 박스의 좌표 >>", x, y, w, h)

# 객체 추적을 위한 초기 추정 위치 설정
# 객체의 x,y,x방향속도(초기0), y방향속도(초기0)로 지정  # 일단 속도를 알 수 없으니 0으로 초기화
kalman.statePre = np.array([[x],[y],[0],[0]],np.float32)

while True:
    # 프레임 읽기
    ret, frame = cap.read()
    if not ret:
        break

    # 칼만 필터로 예측한 위치 계산
    kalman.correct(np.array([[np.float32(x)+w/2],[np.float32(y)+h/2]]))
    kalman.predict()

    # 칼만 필터로 추정된 객체 위치
    predicted_bbox = tuple(map(int, kalman.statePost[:2,0]))
    """
    map(int, kalman.statePost[:2,0]): 상태 벡터의 값들을 int 함수를 사용하여 정수로 변환 
    map 함수는 시퀀스의 모든 요소에 함수를 적용하여 새로운 시퀀스를 생성 
    여기서는 상태 벡터의 값을 int 함수를 사용하여 정수로 변환
    """

    # 추정된 위치에 사각형 그리기
    cv2.rectangle(frame, (predicted_bbox[0]-w//2, predicted_bbox[1]-h//2), 
                        (predicted_bbox[0]+w//2, predicted_bbox[1]+h//2), 
                        (0,255,255), 2)

    # 화면에 출력
    cv2.imshow("frame", frame)


    # 'q'를 누르면 종료
    if cv2.waitKey(60) == ord('q'):
        break

# 해제
cap.release()
cv2.destroyAllWindows()

 

 

 

import cv2
import numpy as np

# kalman filter
kalman = cv2.KalmanFilter(4,2)
kalman.measurementMatrix = np.array([[1,0,0,0],
                                    [0,1,0,0]],np.float32)
kalman.transitionMatrix = np.array([[1,0,1,0],[0,1,0,1],[0,0,1,0],[0,0,0,1]],np.float32)
kalman.processNoiseCov = np.array([[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]],np.float32) * 0.05

# 칼만 필터 추적 실습
# 영상 파일 열기
cap = cv2.VideoCapture("MS/데이터전처리/0612/data/slow_traffic_small.mp4")

# 첫 프레임에서 추적할 객체 선택
ret, frame = cap.read()
print(ret, frame) # 경로가 잘못된 경우 ret = False, frame = None / 정상일경우 ret = True, frame = 영상프레임

x, y, w, h = cv2.selectROI(frame, False, False)
print("선택한 박스의 좌표 >>", x, y, w, h)

# 객체 추적을 위한 초기 추정 위치 설정
# 객체의 x,y,x방향속도(초기0), y방향속도(초기0)
kalman.statePre = np.array([[x],[y],[0],[0]],np.float32)

while True:
    # 프레임 읽기
    ret, frame = cap.read()
    if not ret:
        break

    # 칼만 필터로 예측한 위치 계산
    kalman.correct(np.array([[np.float32(x)+w/2],[np.float32(y)+h/2]]))
    kalman.predict()

    # 칼만 필터로 추정된 객체 위치
    predicted_bbox = tuple(map(int, kalman.statePost[:2,0]))

    # 추정된 위치에 사각형 그리기
    cv2.rectangle(frame, (predicted_bbox[0]-w//2, predicted_bbox[1]-h//2), 
                        (predicted_bbox[0]+w//2, predicted_bbox[1]+h//2), 
                        (0,255,255), 2)

    # 화면에 출력
    cv2.imshow("frame", frame)


    # 'q'를 누르면 종료
    if cv2.waitKey(60) == ord('q'):
        break

# 해제
cap.release()
cv2.destroyAllWindows()

 

728x90
728x90

# 객체 추적 알고리즘 소

움직이는 객체식별하고, 그 위적하는 방법을 의미합니다. 이를 해 동상이나 실시간 스트리데 이터에서 객체움직지하고, 객체적하는데 사됩니다. 다음은 일적으로 사되는 몇 가지 객 체 추적 알고리즘입니다.

 

평균 이동 추적 (Mean Shift Tracking):

1. 평균 이동추적은 객체의 히스토그램을 기반으로 추적하는 알고리즘입니다.
2. 초기위치를 선택하고, 해당 위치의 픽셀분포를 히스토그램으로 계산합니다.
3. 다음 프레임에서 히스토그램 유사도를 측정하여 객체의 새로운 위치를 찾습니다.

4. 이 과정을 반복하여 객체움직적합니다.

우선 전체 코드

 

import cv2

# 평균 이동 추적을 위한 초기 사각형 설정
track_window = None  # 객체의 위치 정보 저장할 변수
roi_hist = None  # 히스토그램을 저장할 변수
trem_crit = (cv2.TERM_CRITERIA_EPS|cv2.TERM_CRITERIA_COUNT, 10,1)  # 반복횟수 10

"""
cv2.TERM_CRITERIA_EPS: 반복 알고리즘의 정지 기준 중 하나로, 
주어진 정지 기준 오차(epsilon)를 충족하는 경우 알고리즘을 중지합니다.
cv2.TERM_CRITERIA_COUNT: 반복 알고리즘의 정지 기준 중 하나로, 
주어진 반복 횟수(count)를 충족하는 경우 알고리즘을 중지합니다.
따라서 cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT는 이 두 가지 정지 기준을 모두 사용하겠다는 의미입니다. 
이러한 정지 기준을 설정한 후에는 알고리즘이 주어진 정지 기준에 도달하면 반복을 중지하게 됩니다.

또한, (10, 1)은 알고리즘의 최대 반복 횟수와 정지 기준 오차(epsilon) 값을 나타냅니다. 
예를 들어, 여기서는 최대 10번의 반복과 1의 정지 기준 오차를 설정하였습니다. 
따라서 알고리즘은 최대 10번 반복하거나 주어진 오차가 1 이하로 감소할 때까지 실행됩니다.
"""


# 영상 파일 열기 
cap = cv2.VideoCapture("MS/데이터전처리/0612/data/slow_traffic_small.mp4")

# 첫 프레임에서 추적할 객체 선택
ret, frame = cap.read()  # 영상 있냐없냐 T/F가 ret , Frame 저장
x, y, w, h = cv2.selectROI("selectROI", frame, False, False)
print("선택한 박스의 좌표 >>", x, y, w, h)


# 추적할 객체 초기 히스토그램 계산
roi = frame[y:y+h, x:x+w]  # 관심구역
hsv_roi = cv2.cvtColor(roi, cv2.COLOR_BGR2HSV) # (Hue 색상, Saturation 채도, Value 명도)
roi_hist = cv2.calcHist([hsv_roi], [0], None, [180], [0,180]) # 히스토그램 계산
cv2.normalize(roi_hist, roi_hist, 0, 255, cv2.NORM_MINMAX) # 히스토그램을 0부터 255로 정규화 (정확도 높일려고)

# 추적할 객체의 초기 윈도우 설정 
track_window = (x, y, w, h)
# cv2.imshow("roi test", roi)
# cv2.waitKey(0)

# 평균 이동 추적
while True:
    # 프레임 읽기
    ret, frame = cap.read()
    if not ret:  
        break

    # 추적할 객체에 대한 채도 히스토그램 역투영계산
    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
    backproj = cv2.calcBackProject([hsv], [0], roi_hist, [0,180], 1)
    """
    [hsv]: 역투영을 계산할 대상 이미지의 HSV 채널입니다. HSV 채널은 색상 정보를 갖고 있어 역투영에 활용됩니다.
    [0]: 역투영에 사용할 채널 인덱스입니다. 여기서는 색상 채널(Hue)인 0번 인덱스를 사용합니다.
    roi_hist: ROI(Region of Interest)의 히스토그램입니다. 이 히스토그램은 역투영에 사용됩니다.
    [0,180]: 히스토그램의 범위를 나타냅니다. 여기서는 Hue 채널의 범위가 0부터 180까지로 설정되었습니다.
    1: 확대 비율(scale)입니다. 픽셀의 값을 히스토그램의 값으로 나누어 정규화합니다.
    """
    

    # 평균 이동으로 새 위치 검색
    ret, track_window = cv2.meanShift(backproj, track_window, trem_crit)

    # 검색된 새 위치에 사각형 그리기
    x, y, w, h = track_window
    print("새 위치 좌표 >>", x, y, w, h)
    cv2.rectangle(frame, (x,y), (x+w, y+h), (0,255,0), 2)
    """
    frame: 이미지 또는 비디오 프레임을 나타내는 변수입니다.
    (x, y): 사각형의 왼쪽 위 모서리의 좌표입니다.
    (x + w, y + h): 사각형의 오른쪽 아래 모서리의 좌표입니다. 여기서 w는 사각형의 너비, h는 사각형의 높이입니다.
    (0, 255, 0): 사각형의 선 색상을 나타내는 RGB 값입니다. (R, G, B) 형식으로 표현됩니다. 여기서 (0, 255, 0)은 녹색을 나타냅니다.
    2: 사각형 선의 두께를 나타냅니다.
    """
    

    # 화면에 출력
    cv2.imshow("backproj", backproj)
    cv2.imshow("frame", frame)

    # 'q'를 누르면 종료
    if cv2.waitKey(60) == ord('q'):
        exit()

# 해제
cap.release()
cv2.destroyAllWindows()

 

import cv2

# 평균 이동 추적을 위한 초기 사각형 설정
track_window = None  # 객체의 위치 정보 저장할 변수
roi_hist = None  # 히스토그램을 저장할 변수
trem_crit = (cv2.TERM_CRITERIA_EPS|cv2.TERM_CRITERIA_COUNT, 10,1)  # 반복횟수 10

# 영상 파일 열기 
cap = cv2.VideoCapture("MS/데이터전처리/0612/data/slow_traffic_small.mp4")

# 첫 프레임에서 추적할 객체 선택
ret, frame = cap.read()
x, y, w, h = cv2.selectROI("selectROI", frame, False, False)
print("선택한 박스의 좌표 >>", x, y, w, h)


# 추적할 객체 초기 히스토그램 계산
roi = frame[y:y+h, x:x+w]
hsv_roi = cv2.cvtColor(roi, cv2.COLOR_BGR2HSV) # (Hue, Saturation, Value)
roi_hist = cv2.calcHist([hsv_roi], [0], None, [180], [0,180]) # 히스토그램 계산
cv2.normalize(roi_hist, roi_hist, 0, 255, cv2.NORM_MINMAX) # 히스토그램을 0부터 255로 정규화 (정확도 높일려고)

# 추적할 객체의 초기 윈도우 설정 
track_window = (x, y, w, h)
# cv2.imshow("roi test", roi)
# cv2.waitKey(0)

# 평균 이동 추적
while True:
    # 프레임 읽기
    ret, frame = cap.read()
    if not ret:
        break

    # 추적할 객체에 대한 채도 히스토그램 역투영계산
    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
    backproj = cv2.calcBackProject([hsv], [0], roi_hist, [0,180], 1)

    # 평균 이동으로 새 위치 검색
    ret, track_window = cv2.meanShift(backproj, track_window, trem_crit)

    # 검색된 새 위치에 사각형 그리기
    x, y, w, h = track_window
    print("새 위치 좌표 >>", x, y, w, h)
    cv2.rectangle(frame, (x,y), (x+w, y+h), (0,0,255), 2)

    # 화면에 출력
    cv2.imshow("backproj", backproj)
    cv2.imshow("frame", frame)

    # 'q'를 누르면 종료
    if cv2.waitKey(60) == ord('q'):
        break

# 해제
cap.release()
cv2.destroyAllWindows()

 

 

 

728x90
728x90

https://webnautes.tistory.com/1257

 

OpenCV Python 강좌 - 모폴로지 연산 (Morphological Operations)

OpenCV에서 제공하는 Erosion, Dilation, Opening, Closing 연산하는 함수들을 다룹니다. 보통 바이너리 이미지(Binary Image)에서 흰색으로 표현된 오브젝트의 형태를 개선하기 위해 사용됩니다. 마지막 업데

webnautes.tistory.com

을 먼저보고오는게 이해가 더 잘됨

1.  threshold 

경계면 구분을 원활하게 진행함

 

import cv2
import matplotlib.pyplot as plt
import numpy as np

image_path= "./data/a.png"

image = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)
"""
230보다 큰 값은 모두 255로 설정되고 작은값은 0으로 (흰색으로 바뀜)
"""

_, mask = cv2.threshold(image, 230, 255, cv2.THRESH_BINARY_INV)

image_list = np.hstack([
    image,
    mask
])

plt.imshow(image_list, 'gray')
plt.show()

 

 

 

2. 확장 침식 실험 - 02

import cv2
import matplotlib.pyplot as plt
import numpy as np

image_path= "./data/a.png"

image = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)
_, mask = cv2.threshold(image, 230, 255, cv2.THRESH_BINARY_INV)

                        
kernel = np.ones((3,3), np.uint8)
dilation = cv2.dilate(mask, kernel, iterations=2) # iterations 반복횟수
erosion = cv2.erode(mask, kernel)                     

image_list = np.hstack([
    image,
    mask,
    dilation,  # 팽창
    erosion   # 침식
])

plt.imshow(image_list, 'gray')
plt.title('org img to mask, dilation, erosion')
plt.show()

 

 

image_path= "./data/a.png"

image = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)
_, mask = cv2.threshold(image, 230, 255, cv2.THRESH_BINARY_INV)

                        
kernel = np.ones((3,3), np.uint8)
dilation = cv2.dilate(mask, kernel, iterations=2) # iterations 반복횟수
erosion = cv2.erode(mask, kernel)
opening = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel)
closing = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel)

image_list = np.hstack([
    image,
    mask,
    dilation, 
    erosion,  
    opening,  
    closing
])

plt.imshow(image_list, 'gray')
plt.title('org img to mask, dilation, erosion, opening, closing')
plt.show()

 

3. 확장 침식 실험 - 03

 

image_path= "./data/a.png"

image = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)
_, mask = cv2.threshold(image, 230, 255, cv2.THRESH_BINARY_INV)

                        
kernel = np.ones((3,3), np.uint8)
dilation = cv2.dilate(mask, kernel, iterations=2) # iterations 반복횟수
erosion = cv2.erode(mask, kernel)
opening = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel)
closing = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel)

mg = cv2.morphologyEx(mask, cv2.MORPH_GRADIENT, kernel)   # 팽창과 침식의 차  / 경계, 윤곽선, 테두리 등을 추출에 주로 쓰임
th = cv2.morphologyEx(mask, cv2.MORPH_TOPHAT, kernel)     #                 이미지의 밝은 영역에서 뚜렷한 경계를 강조

image_list = np.hstack([
    image,
    mask,
    dilation, 
    erosion,  
    opening,  
    closing
])

image_list_01 = np.hstack([
    mg,
    th
])

plt.imshow(image_list, 'gray')
plt.title('org img to mask, dilation, erosion, opening, closing')
plt.show()

plt.imshow(image_list_01, 'gray')
plt.title('org img to mg, th')
plt.show()

728x90
728x90

 

1.  커스텀 필터로 data폴더안에 있는 모든 .png파일 불러오기

import cv2
import matplotlib.pyplot as plt
import numpy as np
import os
import glob


image_path = "./data"
image_list = glob.glob(os.path.join(image_path, "*.png"))  # data 폴더안에 .png를 모두 불러옴

for path in image_list :
    print(path)
    image = cv2.imread(path, 1)
    image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
    
    # custom filter 
    filter = np.array([[3,-2, -2 ], [-3, 7, -5], [5, -1, 0]])
    
    """
    각각의 a, b, c는 필터의 가중치  값을 나타냅니다. 이 값은 이미지의 각 픽셀과 이웃한 픽셀 간의 계산에 사용됩니다. 
    필터는 이미지의 각 픽셀에 적용되며, 
    필터 윈도우 내의 픽셀 값과 필터의 가중치를 곱한 후 합산합니다.
    """
    
    # custom filter 적용 
    custom_filter_img = cv2.filter2D(image, -1, filter)  # -1 : 출력이미지의 뎁스를 입력이미지와 동일하게
    
    plt.imshow(custom_filter_img)
    plt.show()

2.  세피아 필터적용

image_path = "./data"
image_list = glob.glob(os.path.join(image_path, "*.png"))

for path in image_list :
    print(path)
    image = cv2.imread(path, 1)
    
    # 효과필터 적용
    filter_ = np.array([[0.272, 0.534, 0.131], [0.119,0.686, 0.168], [0.393, 0.769, 0.189]])
    sepia_img = cv2.transform(image, filter_)
    
    plt.imshow(sepia_img)
    plt.show()
    
    
    """
    cv2.transform 함수는 이미지의 전체적인 변환 작업에 사용되며, 
    cv2.filter2D 함수는 이미지 필터링 작업을 통해 픽셀 값을 변형하는 데 사용됩니다.
    """

 

 

3. 엠보스효과

 

import cv2
import matplotlib.pyplot as plt
import numpy as np
import os
import glob

image_path = "./data"
image_list = glob.glob(os.path.join(image_path, "*.png"))

for path in image_list :
    print(path)
    image = cv2.imread(path, 1)
    
    # 엠보스 효과
    filter_temp = np.array([[0, 1, 0], [0, 0, 0], [0, -1, 0]])
    
    emboss_img = cv2.filter2D(image, -1, filter_temp)
    emboss_img = emboss_img + 128
    
    plt.imshow(emboss_img)
    plt.show()

728x90
728x90

학습을 시키기위해 이미지 데이터를 1차원 벡터로 변환하는  과정

 

import cv2
import matplotlib.pyplot as plt

image_path = "./data/box.png"

### 경계선 찾기
# 1. 픽셀 강도의 중간값을 계산
image_gray = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)

image_10x10 = cv2.resize(image_gray, (10,10)) # image 10x10 픽셀 크기로 변환 
image_10x10.flatten()  # 이미지 데이터를 1차원 벡터로 변환

plt.imshow(image_10x10, 'gray')
plt.show()

 

 

#### 머신러닝 특성 컬러 이미지 처리 결과


image_color = cv2.imread("./data/iamge01.png")
image_color = cv2.cvtColor(image_color, cv2.COLOR_BGR2RGB)

# image size 10 x 10
image_10x10_temp = cv2.resize(image_color, (10,10)) # image 10x10 픽셀 크기로 변환 
a = image_10x10_temp.flatten() # 이미지 데이터를 1차원 백터로 변환
print(a, a.shape)

# image size 100 x 100
image_100x100_temp = cv2.resize(image_color, (100,100)) # image 10x10 픽셀 크기로 변환 
b = image_255x255_temp.flatten() # 이미지 데이터를 1차원 백터로 변환


plt.imshow(image_10x10_temp)
plt.show()

plt.imshow(image_100x100_temp)
plt.show()

 

 

728x90
728x90

1. 이미지회전 

- cv2.rotate() 함수활용

- 옵션(이미지, cv2.ROTATE_{각도}_(COUNTER)CLOCKWISE)

import cv2
import matplotlib.pyplot as plt
import numpy as np

image_path = "./data/cat.png"
image = cv2.imread(image_path)

# RGB 타입으로 변경 
image_org_ = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

# 이미지 회전
image_90 = cv2.rotate(image_org_, cv2.ROTATE_90_CLOCKWISE)
image_180 = cv2.rotate(image_org_, cv2.ROTATE_180)
image_270 = cv2.rotate(image_org_, cv2.ROTATE_90_COUNTERCLOCKWISE)

plt.imshow(image_90)
plt.show()

plt.imshow(image_180)
plt.show()

plt.imshow(image_270)
plt.show()

 

2. 상하좌우 반전 

- cv2.flip()

- cv2.flip(이미지, 1 or 0)  1은 좌우반전, 0은 상하반전

 

import cv2
import matplotlib.pyplot as plt
import numpy as np

image_path = "./data/cat.png"
image = cv2.imread(image_path)

# RGB 타입으로 변경 
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

# 1은 좌우 반전 / 0번은 상하 반전
dst_1 = cv2.flip(image, 1)
dst_2 = cv2.flip(image, 0)

plt.imshow(dst_1)
plt.show()

plt.imshow(dst_2)
plt.show()

728x90
728x90

1. 블러처리 (이미지블러, 가우시안블러)

1. 이미지블러 cv2.blur() 함수활용

import cv2
import matplotlib.pyplot as plt

image_path = "./data/cat.png"
image = cv2.imread(image_path)
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

image_blurry = cv2.blur(image, (5,5)) # cv2.blur() 를 활용함
# 33 55 77   # 블러강도를 나타냄  

plt.imshow(image)
plt.show()

plt.imshow(image_blurry)
plt.show()

 

 

2. 가우시안블러 cv2.Gaussianblur() 함수활용 

이걸 더 많이씀

import cv2
import matplotlib.pyplot as plt
import numpy as np

image_path = "./data/cat.png"
image = cv2.imread(image_path)
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

image_g = cv2.GaussianBlur(image, (9,9), 0)   # cv2.GaussianBlur() 를 사용함  
# (9,9): 주변 커널수-> 세기조절이 됨
# 0 : 표준편차

plt.imshow(image)
plt.show()

plt.imshow(image_g)
plt.show()

 

 

 

 

2. 이미지 선명하게하기

import cv2
import matplotlib.pyplot as plt
import numpy as np

image_path = "./data/cat.png"
image = cv2.imread(image_path)
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

kernel_ = np.array([[0,-1,0],
                    [-1,5,-1],
                    [0,-1,0]
                   ])

image_sharp = cv2.filter2D(image, -1, kernel_)

plt.imshow(image)
plt.show()

plt.imshow(image_sharp)
plt.show()

 

3. 이미지 대비높이기

1 . 그레이스케일 일때  : 히스토그램 평활화 cv2.equalizeHist()에 BGR2Gray 활용 : 

import cv2
import matplotlib.pyplot as plt
import numpy as np

image_path = "./data/cat.png"
image = cv2.imread(image_path)
image_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# 단일 이미지에서만 적용가능!
image_enhanced = cv2.equalizeHist(image_gray)

plt.imshow(image_gray, 'gray')
plt.show()

plt.imshow(image_enhanced, 'gray')
plt.show()

 

2. 컬러일때 : RGB에 YUV를 추가함

import cv2
import matplotlib.pyplot as plt
import numpy as np

image_path = "./data/cat.png"
image = cv2.imread(image_path)

# RGB 타입으로 변경 
image_org = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

# YUV 타입으로 변경 
image_yuv = cv2.cvtColor(image, cv2.COLOR_BGR2YUV)

# 히스토그램 평활화 적용 
image_yuv[:,:,0] = cv2.equalizeHist(image_yuv[:,:,0])

# YUV > RGB 
image_rgb = cv2.cvtColor(image_yuv , cv2.COLOR_YUV2RGB)


plt.imshow(image_yuv)
plt.show()

plt.imshow(image_org)
plt.show()

plt.imshow(image_rgb)
plt.show()

4. 이진화(흑백)

 

import cv2
import matplotlib.pyplot as plt
import numpy as np

image_path = "./data/cat.png"
image = cv2.imread(image_path)

image_gray_01 = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# 이미지 이진화 
max_output_value = 255 
neighborhood_size = 99
subtract_from_mean = 10
image_binarized = cv2.adaptiveThreshold(
                                image_gray_01,
                                max_output_value,
                                cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
                                cv2.THRESH_BINARY, # cv2.THRESH_BINARY_INV(반전)
                                neighborhood_size,
                                subtract_from_mean
)

plt.imshow(image_binarized, 'gray')
plt.show()

728x90
728x90

1.  이미지 타입, 크기 확인하기

import cv2
image_path = "./data/cat.png"

# image read 
image = cv2.imread(image_path)

# image 타입 
image_type = type(image)
print("이미지 타입 >> " , image_type)

# 이미지 크기 확인 
image_height, image_width, image_channel = image.shape
print(image_height, image_width, image_channel)

# 이미지 타입 >>  <class 'numpy.ndarray'>
# 162 310 3

 

2. 이미지 리사이징

import cv2
import matplotlib.pyplot as plt

image_path = "./data/cat.png"

image = cv2.imread(image_path)

image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)  # cv2로 불러오면  BGR을 RGB로 바꿔줘야함
# https://itcreator.tistory.com/141 에 적어둠

# 이미지 크기 조절 
image_resize = cv2.resize(image, (244,244))

# 이미지 크기 확인 
image_height_, image_width_, _ = image_resize.shape


# 원본 이미지 
plt.imshow(image)
plt.show()

 

# 리사이즈 이미지 
print(image_height_, image_width_)
# 244 244

plt.imshow(image_resize)
plt.show()

# 저장하기

import cv2
image_resize = cv2.cvtColor(image_resize, cv2.COLOR_BGR2RGB)  
cv2.imwrite("./data/resize_image.png", image_resize)  # cv2.imwrite로 저장하기

# True라고 뜨면 저장된거

 

3. 이미지 자르기(슬라이싱)

import cv2
import matplotlib.pyplot as plt

image_path = "./data/cat.png"
image = cv2.imread(image_path)
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

image_cropped = image[10:,:200]   #  [행시작:행끝, 열시작:열끝]

plt.imshow(image)
plt.show()

 

plt.imshow(image_cropped)
plt.show()

 

 

3-1. 이미지자르기(좌표)

import cv2
import matplotlib.pyplot as plt

image_path = "./data/cat.png"
image = cv2.imread(image_path)
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)


x1, y1 = 50, 50 # 좌측 상단 모서리 좌표 
x2, y2 = 150,150 # 우측 하단 모서리 좌표 

cropped_image_test = image[y1:y2, x1:x2]   # y가 먼저인 이유는 좌표평면에서 행렬의 행은 y값임
plt.imshow(cropped_image_test)
plt.show()

 

 

 

 

 

 

2. 변환하기

3. 리사이즈

4. 크롭  (슬라이싱,좌표)

 

728x90
728x90

1.  이미지 불러오기 (png파일)

# !pip install opencv-python==4.5.5.64
import cv2
from matplotlib import pyplot as plt 


img = cv2.imread("./data/cat.png")    # cv2 라이브러리의 imread() 함수로 불러옴

# 색상의 문제 발생 -> BGR -> RGB 
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

plt.imshow(img)
plt.show()

2. 이미지 저장하기(.npy)

넘파이를 이용하여 배열로 저장하기

.npy 파일로 저장하는 방법

import numpy as np
np.save("./data/image.npy", img)  #  현재위치에 있는 data 폴더에 image.npy로 이미지만들기


# 만약에 해당폴더가 없으면 폴더생성하는 파이썬 코드
import os

def createDirectory(directory):
    try:
        if not os.path.exists(directory):
            os.makedirs(directory)
    except OSError:
        print("Error: Failed to create the directory.")

2-1. 이미지 저장하기(PIL)

PIL은 간단한 이미지 처리와 변환 작업에 사용하기 좋음 / 컴퓨터 비전 작업에서는 OpenCV를 쓰는게 맞음

#!pip install Pillow
import numpy as np
from PIL import Image

# 이미지 불러오기 
img = Image.open("./data/cat.png").convert('L') # 그레이 스케일 변환
print(img)

img_array = np.array(img)

np.save("./data/pil_image.npy", img_array)  # .npy로 저장
img_array1 = np.load("./data/pil_image.npy")  # .npy 불러오기

# 다시 PIL 이미지로 변환 
img = Image.fromarray(np.uint8(img_array1))    # pil의 Image라이브러리 fromarray()로 변환
img.save("./data/image_numpy.png")            # pil로 png로 변환       


org_size = os.path.getsize("./data/cat.png")
np_save_size = os.path.getsize("./data/pil_image.npy")
pil_save_size = os.path.getsize("./data/image_numpy.png")

# 용량차이 확인하기 
print(org_size, "bytes")
print(np_save_size, "bytes")
print(pil_save_size, "bytes")


# 원본 : 6468 bytes
# .npy로 저장 : 50348 bytes   
# PIL를 활용하여 png로 저장 26808 bytes

 

3. 이미지 불러오기 (.npy)

img_data = np.load("./data/image.npy")  # 넘파이의 load()로 불러옴

plt.imshow(img_data)
plt.show()

 

 

728x90
728x90

 

728x90
728x90

1. 순서가 없는 범주형 데이터

import numpy as np 
from sklearn.preprocessing import LabelBinarizer, MultiLabelBinarizer

feature = np.array((['가나다라'],
                    ['가나다라'],
                    ['아바하자'],
                    ['카나다사']))

print(feature)

# 원-핫 인코더 생성
one_hot = LabelBinarizer()
one_hot.fit_transform(feature) # 특성을 원-핫 인코딩 변환 
# 특성 클래스 확인 
print(one_hot.classes_)

"""
[['가나다라']
 ['가나다라']
 ['아바하자']
 ['카나다사']]
['가나다라' '아바하자' '카나다사']
"""

 

2.  다중 클래스 특성에 대한 처리

multiclass_feature = [('가나다라마','아자바하나'),
                     ('자다가나라','자다나타하'),
                     ('가나다라마','아자바하나'),
                     ('아마자나가','아카나다하'),
                     ('가나다라마','아자바하나'),
                     ]
one_hot_mult = MultiLabelBinarizer()
one_hot_mult.fit_transform(multiclass_feature)
print(one_hot_mult.classes_)

# ['가나다라마' '아마자나가' '아자바하나' '아카나다하' '자다가나라' '자다나타하']

 

3. 문자 타깃 데이터 원-핫 인코딩

from sklearn.preprocessing import OneHotEncoder

str_feature = ([['안녕', 1],
                ['저녁', 2],
                ['안녕', 1],
                ['점심', 3],
               ])

one_hot_encoder = OneHotEncoder(sparse=False)

# One hot encoder -> 입력 특성 배열을 모두 범주형
one_hot_encoder.fit_transform(str_feature)
print(one_hot_encoder.categories_)

# [array(['안녕', '저녁', '점심'], dtype=object), array([1, 2, 3], dtype=object)]

4. 순서가 있는 범주형 특성 인코딩

- 순서가 있는 클래스는 순서 개념을 가진 수치값으로 변환 
- 딕셔너리 사용해서 -> 특성 

import pandas as pd 
# 특성 데이터 생성
dataframe = pd.DataFrame({
    'Score' : ["Low", "Low", "Medium", "Medium", "High"]
})

print(dataframe)

"""
    Score
0     Low
1     Low
2  Medium
3  Medium
4    High
"""


# 매핑 딕셔너리 생성
scale_mapper = {
    "Low" : 1,
    "Medium" : 2,
    "High" : 3
}

print(scale_mapper)
# {'Low': 1, 'Medium': 2, 'High': 3}

data = dataframe["Score"].replace(scale_mapper)
print(data)
"""
0    1
1    1
2    2
3    2
4    3
Name: Score, dtype: int64
"""

4-2. 순서가 있는 범주형 특성 인코딩

from sklearn.preprocessing import OrdinalEncoder

feature_array = np.array((['Low', 10],
                    ['High', 40],
                    ['Medium',3],))

ordinal_encoder = OrdinalEncoder() 
ordinal_encoder.fit_transform(feature_array)
print(ordinal_encoder.categories_)
# [array(['High', 'Low', 'Medium'], dtype='<U21'), array(['10', '3', '40'], dtype='<U21')]

4-3. 순서가 있는 범주형 특성 인코딩

- 특성 딕셔너리 인코딩

from sklearn.feature_extraction import DictVectorizer
# 딕셔너리 생성 
data_dict =[{"Red" : 2 , "Blue" : 4},
            {"Red" : 4 , "Blue" : 3},
            {"Red" : 1 , "Yellow" : 2 },
            {"Red" : 1 , "Yellow" : 2}]


dictVectorizer = DictVectorizer(sparse=False)

feature_dict = dictVectorizer.fit_transform(data_dict)
print(feature_dict)

feature_dict_name = dictVectorizer.get_feature_names()
print(feature_dict_name)

dict_data = pd.DataFrame(feature_dict,  columns=feature_dict_name)
print(dict_data)


"""
[[4. 2. 0.]
 [3. 4. 0.]
 [0. 1. 2.]
 [0. 1. 2.]]
['Blue', 'Red', 'Yellow']
   Blue  Red  Yellow
0   4.0  2.0     0.0
1   3.0  4.0     0.0
2   0.0  1.0     2.0
3   0.0  1.0     2.0
"""

 

 


범주형 데이터 - 누락된 클래스값 대처하기 1

- knn으로 주변 그룹을 활용하여 nan의 값 예측함

from sklearn.neighbors import KNeighborsClassifier
x = np.array([[0, 2.10, 1.48],
             [1,1.18,1.33],
             [0,1.22,1.27],
             [1, -0.20, -1.15]])

x_with_nan = np.array([[np.nan, 0.87, 1.33], [np.nan, -0.67, -0.22]]) # 일부러 nan 생성

clf = KNeighborsClassifier(3, weights='distance')

print(x[:,1:])
print(x[:,0])

"""
[[  nan  0.87  1.33]
 [  nan -0.67 -0.22]]
[[ 2.1   1.48]
 [ 1.18  1.33]
 [ 1.22  1.27]
 [-0.2  -1.15]]
[0. 1. 0. 1.]
"""
train_model = clf.fit(x[:,1:], x[:,0])
imputer_values = train_model.predict(x_with_nan[:,1:]) # 누락된 값의 클래스 예측 

x_with_imputer = np.hstack((imputer_values.reshape(-1,1), x_with_nan[:,1:]))
data = np.vstack((x_with_imputer, x)) # 두 특성 행렬을 연결 
print(data)
"""
[[ 0.    0.87  1.33]
 [ 1.   -0.67 -0.22]
 [ 0.    2.1   1.48]
 [ 1.    1.18  1.33]
 [ 0.    1.22  1.27]
 [ 1.   -0.2  -1.15]]
 """

 

근처의 값을 비교해서 주변 그룹에 많이 있는 라벨을 따라감 

 

 

범주형 데이터 - 누락된 클래스값 대처하기 2

- 누락된 값을 특성에서 가장 자주 등장하는 값으로 채우기

from sklearn.impute import SimpleImputer
x_complete = np.vstack((x_with_nan, x))
print("전")
print(x_complete)

impute = SimpleImputer(strategy='most_frequent')
data_impute = impute.fit_transform(x_complete)
print("후")
print(data_impute)
"""
전
[[  nan  0.87  1.33]
 [  nan -0.67 -0.22]
 [ 0.    2.1   1.48]
 [ 1.    1.18  1.33]
 [ 0.    1.22  1.27]
 [ 1.   -0.2  -1.15]]
후
[[ 0.    0.87  1.33]
 [ 0.   -0.67 -0.22]
 [ 0.    2.1   1.48]
 [ 1.    1.18  1.33]
 [ 0.    1.22  1.27]
 [ 1.   -0.2  -1.15]]
 """
728x90
728x90

PCA 클래스: Scikit-learn의 decomposition 모듈에서 제공되는 클래스 중 하나입니다. PCA는 데이터셋의 차원을 감소시키는 기술로, 데이터셋에서 가장 중요한 특성만 추출하여 새로운 차원 축으로 변환합니다. 이를 통해 데이터셋의 노이즈(noise)를 제거하고, 더욱 빠르고 효율적인 학습이 가능해집니다.

n_components: PCA 클래스의 인자 중 하나로, 추출할 주성분(principal component)의 수를 지정합니다. 여기서는 99%의 분산(variance)을 유지하도록 설정되어 있습니다. 이는 데이터셋에서 99%의 정보가 유지되도록 차원을 축소하는 것을 의미합니다.

whiten: PCA 클래스의 인자 중 하나로, True로 설정할 경우 PCA의 결과로 나오는 주성분들이 서로 독립적인 값이 되도록 백색화(whitening)를 수행합니다. 백색화를 하면 각 주성분의 분산이 1이 되고, 상관 관계가 없는 성분들로 구성된 새로운 특성 공간이 만들어집니다.

fit_transform(): PCA 클래스에는 fit()과 transform() 메서드가 있습니다. fit() 메서드는 PCA 모델을 학습하고, transform() 메서드는 학습된 모델을 사용하여 데이터를 변환합니다. fit_transform() 메서드는 이 두 단계를 한 번에 수행합니다.

위의 같이 PCA이용하면 99%의 분산을 유지하도록 새로운 특성(feature) 공간으로 변환하고 있습니다. 결과적으로, 원본 데이터셋의 특성 개수는 features.shape[1]으로 확인할 수 있고, PCA를 수행하여 감소된 특성 개수는 features_pca.shape[1]으로 확인할 수 있습니다. 이렇게 차원 축소를 수행하면, 모델의 학습 시간을 단축시키고, 과적합(overfitting)을 방지할 수 있습니다.

 

 

from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA
from sklearn import datasets

digits = datasets.load_digits() # 8x8 크기의 손글씨 숫자 데이터 로드 
feature = StandardScaler().fit_transform(digits.data) # 특성 행렬을 표준화 처리 

print(feature)
 [[ 0.         -0.33501649 -0.04308102 ... -1.14664746 -0.5056698
  -0.19600752]
 [ 0.         -0.33501649 -1.09493684 ...  0.54856067 -0.5056698
  -0.19600752]
 [ 0.         -0.33501649 -1.09493684 ...  1.56568555  1.6951369
  -0.19600752]
 ...
 [ 0.         -0.33501649 -0.88456568 ... -0.12952258 -0.5056698
  -0.19600752]
 [ 0.         -0.33501649 -0.67419451 ...  0.8876023  -0.5056698
  -0.19600752]
 [ 0.         -0.33501649  1.00877481 ...  0.8876023  -0.26113572
  -0.19600752]]

pca = PCA(n_components=0.99, whiten=True)  # 99% 분산을 유지하도록 PCA객체 생성 / whiten=True 평균을 0, 표준편차를 1로변경
features_pca = pca.fit_transform(feature) # PCA 수행

print("원본 특성 개수 >> " , feature.shape[1])
print("줄어든 특성 개수 >> " , features_pca.shape[1])

# 원본 특성 개수 >>  64
# 줄어든 특성 개수 >>  54

1. StandardScaler() 
 >> Scikit-learn의 전처리(preprocessing) 모듈에서 제공되는 클래스 중 하나입니다. 이 클래스는 데이터를 평균이 0, 분산이 1인 가우시안 정규 분포(standard normal distribution)로 변환합니다.

2. digits.data : digits 데이터셋에서 숫자 이미지의 각 픽셀 값을 포함하는 배열 

3. fit_transform() 메서드 
 >> StandardScaler 클래스에는 데이터를 변환하는 두 가지 단계가 있습니다. 첫째, 모델을 학습(fit)하고, 둘째, 학습된 모델을 사용하여 데이터를 변환(transform)합니다. fit_transform() 메서드는 이 두 단계를 한 번에 수행합니다. 즉, 데이터를 표준화(normalize)하고, 변환된 값을 반환합니다.
 
따라서 위의 코드는 digits 데이터셋의 특성을 가우시안 정규 분포로 변환한 후, 변환된 값을 featuress 변수에 할당 이렇게 정규화를 수행하면, 모델이 데이터를 더 잘 이해하고, 모델의 예측 성능을 향상 시킬 수 있습니다.

 

 

 

 


 

 

 

 

결과값 비교

 

1. 데이터불러오기

from sklearn.datasets import load_digits
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score

digits = load_digits()

# 진짜 차이가 있는지 체크 하기 위해서 -> 정규화 하지 않은 데이터로 분류 모델 훈련
print(len(digits.data))   
print(len(digits.target))
x_train, x_test, y_train, y_test = train_test_split(digits.data, digits.target , random_state=777)

print(len(x_train), len(x_test))
print(len(y_train), len(y_test))


"""
8 : 2 
2 -> 1 : 1 
8 : 1 : 1


1. 폴더 생성 (이미지 100개)
2. 폴더 읽고 -> train val test 나눠서 폴더 생성해서 거기에 이미지 저장
"""

# 1797
# 1797
# 1347 450
# 1347 450​

 

2. 모델불러오기

model = LogisticRegression(max_iter=10000)
model.fit(x_train, y_train)
y_pred = model.predict(x_test)

no_standardScaler_acc_score = accuracy_score(y_test, y_pred) # 정답지 예측치
print(no_standardScaler_acc_score)

# 0.9533333333333334

 

3. StandardScaler 적용후 -> ACC

from sklearn.preprocessing import StandardScaler

scaler = StandardScaler()
x_train_norm = scaler.fit_transform(x_train)
x_test_norm = scaler.transform(x_test)
model_norm = LogisticRegression(max_iter=10000)
model_norm.fit(x_train_norm, y_train)
y_pred_norm = model_norm.predict(x_test_norm)

standardScale_acc_score = accuracy_score(y_test, y_pred_norm)
print(standardScale_acc_score)

# 0.9555555555555556 값 상승함
728x90

+ Recent posts