반응형

 

우선, 연예인 얼굴 이미지가 필요하니 네이버에서 연예인들 이미지를 다운로드하도록 한다.

일일이 받아도 되나, 우리는 이미 파이썬을 다룰 줄 알고, 크롤링을 할 줄 알기 때문에, 코드로 구현해보자.

 

내가 만든 이미지 다운 크롤링은 다음과 같다.

케라스 수업이 이기에, 코드를 복사 붙여 넣기 해서 사용하기를 추천한다.

from urllib.request import urlopen
from bs4 import BeautifulSoup as bs
from urllib.parse import quote_plus
import os

naver_img_url = "https://search.naver.com/search.naver?where=image&sm=tab_jum&query="
actors = ["강동원", "원빈", "장동건", "마동석"]
for actor in actors :
    print(f'{actor} 다운로드 시작')
    url = naver_img_url + quote_plus(actor)
    html = urlopen(url)
    soup = bs(html, "html.parser")
    img_all = soup.find_all(class_="_img")
    for i in range(len(img_all)):
        imgUrl = img_all[i]["data-source"]
        save_img_dir = f"./img/{actor}"
        with urlopen(imgUrl) as f:
            try:
                if not os.path.exists(save_img_dir) :
                    os.makedirs(save_img_dir)
            except OSError as e:
                print(e)
            with open(f"{save_img_dir}/{actor}_{i}.jpg","wb") as h:
                img = f.read()
                h.write(img)
    print(actor, "다운로드 완료")

actors 변수에 내가 생각나는 연예인들의 이름을 나열했다. 샘플을 만들 것이기 때문에 일부만 사용했다.

여러분들이 코드를 구현한다면, 여러분들이 좋아하는 연예인 이름을 나열하면 된다.

이미지 다운로드는, 현재 돌아가는 파이썬 폴더 경로에, 새로운 img 폴더를 만들고, 연예인 폴더를 만들고, 연예인명_번호.jpg로 저장시켜두게 하였다. 맘에 안 드시는 분들은 바꾸셔도 됩니다.

 

또한, 네이버 image에서 이미지에서 한 화면에서 50개까지밖에 출력되지 않기 때문에, 더 많은 사진을 갖고 싶으신 분들은, 셀리늄 스크롤바 내리기를 추가하시면 됩니다. 하지만 저는 30~50개면 충분하고 차라리 연예인들 이름을 더 추가하는 게 맞다고 생각이 들어서, 생략!

(가끔, 동명이인의 이름을 가진 사람이 다운로드하여지기도 하는데, 알아서 삭제하시면 됩니다.)

 

다운 완료된 강동원 님의 이미지를 확인해보자.

진짜 잘생기셨다.

만약 우리는 이 사진을 그대로 사용하게 된다면, 이미지 학습 시 강동원 님의 옷과 배경까지도 학습을 하게 될 것이기 때문에...

우리는 강동원 님의 얼굴만을 따올 것이다.

 

 

그렇다. 우리는 OpenCv를 다뤄봤다. OpenCV를 통해서 강동원 님의 얼굴만을 따오겠다.

 

쉽게 얼굴을 검출하기 위해, 하나의 xml 파일이 필요한데.. 바로..

haarcascade_frontalface_alt.xml

의 xml 파일이 필요하다. opencv에서 제공해주는 공식 xml 문서이며... 밑에 경로에서 직접 받으셔도 되나,

더 밑에 보시면, 바로 다운로드가 가능하게 파일을 올려두었습니다!

 

github.com/opencv/opencv/tree/master/data/haarcascades

 

opencv/opencv

Open Source Computer Vision Library. Contribute to opencv/opencv development by creating an account on GitHub.

github.com

haarcascade_frontalface_alt.xml
0.88MB

파일을 다운로드하셨으면, 현재 프로그램하는 경로에 붙여 넣으시길 바랍니다.

그럼 이렇게 모듈을 불러주시고, face_cascade 변수에 우리가 받은 파일을 불러옵니다!

import numpy as np
import cv2
import os
face_cascade = cv2.CascadeClassifier("haarcascade_frontalface_alt.xml")

이전에, 저장받은 파일 경로에 한글을 사용하였기 때문에, imread 함수를 사용하려다 보니

error: (-215:Assertion failed) VScn::contains(scn) && VDcn::contains(dcn) && VDepth::contains(depth) in function 'cv::CvtHelper<struct cv::Set<3,4,-1>,struct cv::Set<1,-1,-1>,struct cv::Set<0,2,5>,2>::CvtHelper'

다음과 같은 에러가 계속 났습니다.

(물론 모든 파일명을, 영어로 수정해서 사용하면 되나, 위에 코드 수정하기 귀찮아서, imread 함수에서 한글을 지원하는 새로운 imread function을 만들었다.)

def imread_korean(path):
    with open(path, "rb") as fp:
        bytes = bytearray(fp.read())
        numpy_array = np.asarray(bytes, dtype=np.uint8)
    return cv2.imdecode(numpy_array, cv2.IMREAD_UNCHANGED)

이렇게 함수를 만들었으니, cv2.imread 함수 대신, imread_korean 함수를 사용할 것이다.

 

def save_face(actor) :
    try :
        file_count = len([name for name in os.listdir(f"./img/{actor}/") if os.path.isfile(os.path.join(f"./img/{actor}/", name))])
        for i in range(file_count) :
            save_img_dir = f"./img/{actor}/{actor}_{i}.jpg"
            new_save_img_dir = f"./img/{actor}_face"
            img = imread_korean(f"{save_img_dir}")
            gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
            faces = face_cascade.detectMultiScale(gray, 1.3,5)
    
            for (x,y,w,h) in faces:
                actor_face = img[y:y+h, x:x+w]
                try:
                    if not os.path.exists(new_save_img_dir) :
                        os.makedirs(new_save_img_dir)
                except OSError as e:
                    print(e)
                _, im_write_korean = cv2.imencode(".jpg", actor_face)
                im_write_korean.tofile(f"{new_save_img_dir}/{actor}_{i}.jpg")
    except :
        pass

그럼, 다음과 같이 코드를 완성할 수 있을 것이고,

actors = ["강동원", "원빈", "장동건", "마동석"]
for actor in actors :
    save_face(actor)

 

구현된 코드를 실행시키면....

 

얼굴만 따온 파일은, 원본 파일과 다르게 정리를 해주기 위해서, 연예인_face라는 새로운 폴더에 저장하게 해 두었다.

 

이렇게 해서 저장된 얼굴을 확인해 보자!

음... 얼굴만 잘 따온 것 같다.

(가끔 모든 이미지가 잘 검출하지 않을 수도 있기 때문에, 확인 작업이 필요합니다. 하지만 저는 믿고 그냥 갑니다! 어차피 코드를 보면 아시겠지만, 얼굴 검출이 안되어지는 경우는 새로운 경로에 저장이 안 되기 때문... )

 

우리는 인제 데이터 셋이 준비되었으니,

 

남은 과정을 설명드리도록 하겠습니다.

1. 변경된 사이즈 하나로 통일하기.

2. 클래스 지정하기.

3. 훈련/학습용 데이터 선별하기.

4. RNN 코드 만들기 - 참고하기 (CIFAR-10)

CIFAR-10

아마 CIFAR에 관련된 코드는 여러분들 책에도 나와 있고, 인터넷에서 널려 있을 것입니다.

 

(github.com/GRuuuuu/GRuuuuu.github.io/blob/master/assets/resources/machine-learning/CNN-CIFAR10/cifar10%20dropout%20test%20notebook-s.ipynb)

 

비행기, 자동차, 새, 고양이..... 클래스를 우리의 연예인 이름으로 바꿔주면 되고...

사진들은 우리가 변환하였던 사진들로 대처하면 됩니다.

 

지금 포스팅에 첨부하면 아마 넓은 스크롤바가 엄청 조금 해질 것입니다.

 

하지만... 이런 귀찮은 작업들을 더 빠르고 간편하게 해주는 사이트가 있습니다.

 

teachablemachine.withgoogle.com

 

Teachable Machine

Train a computer to recognize your own images, sounds, & poses. A fast, easy way to create machine learning models for your sites, apps, and more – no expertise or coding required.

teachablemachine.withgoogle.com

이라는 사이트인데요... 

우리는 이 사이트의 도움을 받아, 더 빠르고 간편하게 학습된 모델을 만들어 보도록 하겠습니다.

 

다음 포스팅으로...

 

반응형

주가 관련 데이터셋 받기

finance.yahoo.com/

 

Yahoo Finance - Stock Market Live, Quotes, Business & Finance News

At Yahoo Finance, you get free stock quotes, up-to-date news, portfolio management resources, international market data, social interaction and mortgage rates that help you manage your financial life.

finance.yahoo.com

으로 접속하셔서, 원하는 종목을 검색한다.

 

검색 결과 페이지 내에서, Historical Data를 클릭한다.

1. Time Period를 클릭하여

2. 원하는 기간을 설정 후, (5Y : 5년, Max : 최대 추천)

3. Apply 버튼을 누른다.

4. 다운로드한다.

 

다운로드한 데이터는, 파일명으로 바꾸어 파이썬 환경에 저장을 해둔다.

다운로드하기 귀찮으신 분들은 아래 데이터를 사용하시면 됩니다.

첫 번째는 5년 치, 두 번째 꺼는 10년 치 카카오 주식 정보 데이터입니다.

 

kakao.csv
0.10MB
kakao_max.csv
0.41MB

 

 

필요 모듈 호출

import pandas as pd
import numpy as np
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import LSTM, Dropout, Dense, Activation
from pandas.io.parsers import read_csv

 

파일 업로드 (구글 코랩 사용자만, 다른 환경 사용 시 생략)

from google.colab import files
uploaded = files.upload()

파일 선택 후, 등록

예제에서는 kakao.csv를 이용

 

CSV 파일 읽기 (파일 이름)

data = pd.read_csv('kakao.csv')

구글 코랩 사용자가 아닐 경우, 현재 실행하는 파이썬 프로그램 디렉토리 내에 csv파일 저장할 것! 다른 디렉토리에서 사용 시,

data = pd.read_csv('{파일경로}/kakao.csv')

 

데이터 확인

data.head()

 

데이터 중 Null 값 제거하기

주가 관련 파일을 보면 다음과 같이 Null 값이 종종 있습니다.

dropna 함수를 사용하여 null을 가진 행 (axis=0) 삭제

data = data.dropna(axis=0)

제거를 안 하면, model 훈련 중, 에러를 유발합니다.

 

고가와 저가의 중간 값으로, mid price 구하기

고가와 저가를 변수로 이용해도 되지만, 예제에서는 중간값으로 접근

high_price = data['High'].values
low_price = data['Low'].values
mid_price = (high_price + low_price) / 2

 

50일씩 나누어 분리

데이터들을 첫날부터, 50일씩 끊어서 저장

예) [ [0~50일], [1~51일], [2~52일], [3~53일]....... ]

 

(why? 50일 치 데이터를 가지고 51일째 되는 날의 주가를 예측하기 위해서)

 

day_divided = 50
day_length = day_divided + 1
day_result = []
for i in range(len(mid_price) - day_length):
    day_result.append(mid_price[i: i + day_length])

 

분리된 데이터 확인

print("전체 데이터 Length : ", len(data))
print("나눈 데이터 Length : ", len(day_result))
print("나눈 데이터 0번째 : ")
print(day_result[0])
print(day_result[1])

 

데이터 정규화(Normalized)

50일씩 나누었던 데이터들을 첫날 기준으로 정규화 진행

(첫날을 0으로 만들고, 나머지 날들은 그 비율로 나누어 정규화)

norm_result = []
for section in day_result:
    norm_section = [((float(p) / float(section[0])) - 1) for p in section]
    norm_result.append(norm_section)
day_result = np.array(norm_result)

 

분리된 데이터 정규화 결과 확인

print(day_result[0])

 

데이터셋 정의하기

전체 데이터중 학습 데이터(train_data)는 90%, 테스트 데이터(test_data)는 10% 로 나눔.

데이터가 많지 않아 학습 데이터 비중을 높임.(검증 데이터 사용 x)

train_data_rate = 0.9
boundary = round(day_result.shape[0] * train_data_rate)
train_data = day_result[:boundary, :]
test_data = day_result[boundary:, :]

 

데이터셋 분리하기

위에서 설정한 train data와 test data를 1차원으로 바꾸고, 각 데이터 0~49번째 가격정보는 x_data, 마지막 50번째는 y_data로 설정

(why? 각 데이터 0~49번째 가격 정보를 가지고, 50번째 가격 정보를 예측하기 위해)

x_train = train_data[:, :-1]
x_train = np.reshape(x_train, (x_train.shape[0], x_train.shape[1], 1))
y_train = train_data[:, -1]

x_test = test_data[:, :-1]
x_test = np.reshape(x_test, (x_test.shape[0], x_test.shape[1], 1))
y_test = test_data[:, -1]

 

데이터셋 확인하기

x_train.shape, x_test.shape
((1054, 50, 1), (117, 50, 1))

 

모델 만들기

LSTM, 순환 신경망(RNN) - 순서가 있는 데이터(소리, 언어, 날씨, 주가)처럼 시간의 변화에 함께 변화하면서 그 영향을 받을 때 사용.

(첫 번째 인자 : 메모리 셀의 개수)

(return_sequences=True : 모든 입력에 대해 출력을 내놓게 한다. return_sequences=False : time sep 마지막에서만 결과를 출력)

(imput_shape : 입력 값)

model = Sequential()
model.add(LSTM(50, return_sequences=True, input_shape=(50, 1)))
model.add(LSTM(64, return_sequences=False))
model.add(Dense(1, activation='relu'))
model.compile(loss='mse', optimizer='sgd')

 

모델 확인하기

model.summary()
Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
lstm (LSTM)                  (None, 50, 50)            10400     
_________________________________________________________________
lstm_1 (LSTM)                (None, 64)                29440     
_________________________________________________________________
dense (Dense)                (None, 1)                 65        
=================================================================
Total params: 39,905
Trainable params: 39,905
Non-trainable params: 0
_________________________________________________________________

 

모델 훈련하기

구글 코랩 사용자는 모델 훈련 시, 런타임 환경을 GPU 환경으로 바꾸어 주면 빠르게 처리

model.fit(x_train, y_train,
    validation_data=(x_test, y_test),
    batch_size=10,
    epochs=15)
Epoch 1/20
106/106 [==============================] - 4s 42ms/step - loss: 0.0080 - val_loss: 0.0551
Epoch 2/20
106/106 [==============================] - 4s 41ms/step - loss: 0.0078 - val_loss: 0.0483
Epoch 3/20
106/106 [==============================] - 5s 43ms/step - loss: 0.0077 - val_loss: 0.0451
Epoch 4/20
106/106 [==============================] - 4s 42ms/step - loss: 0.0075 - val_loss: 0.0411
Epoch 5/20
106/106 [==============================] - 4s 42ms/step - loss: 0.0074 - val_loss: 0.0375
Epoch 6/20
106/106 [==============================] - 5s 43ms/step - loss: 0.0073 - val_loss: 0.0359
Epoch 7/20
106/106 [==============================] - 4s 41ms/step - loss: 0.0073 - val_loss: 0.0310
Epoch 8/20
106/106 [==============================] - 4s 40ms/step - loss: 0.0072 - val_loss: 0.0284
Epoch 9/20
106/106 [==============================] - 4s 40ms/step - loss: 0.0072 - val_loss: 0.0274
Epoch 10/20
106/106 [==============================] - 4s 40ms/step - loss: 0.0071 - val_loss: 0.0286
Epoch 11/20
106/106 [==============================] - 4s 40ms/step - loss: 0.0071 - val_loss: 0.0256
Epoch 12/20
106/106 [==============================] - 4s 40ms/step - loss: 0.0071 - val_loss: 0.0240
Epoch 13/20
106/106 [==============================] - 4s 41ms/step - loss: 0.0070 - val_loss: 0.0228
Epoch 14/20
106/106 [==============================] - 4s 40ms/step - loss: 0.0070 - val_loss: 0.0216
Epoch 15/20
106/106 [==============================] - 4s 41ms/step - loss: 0.0070 - val_loss: 0.0223
Epoch 16/20
106/106 [==============================] - 4s 40ms/step - loss: 0.0070 - val_loss: 0.0200
Epoch 17/20
106/106 [==============================] - 4s 42ms/step - loss: 0.0070 - val_loss: 0.0194
Epoch 18/20
106/106 [==============================] - 5s 47ms/step - loss: 0.0070 - val_loss: 0.0213
Epoch 19/20
106/106 [==============================] - 5s 47ms/step - loss: 0.0070 - val_loss: 0.0190
Epoch 20/20
106/106 [==============================] - 5s 46ms/step - loss: 0.0069 - val_loss: 0.0192

 

모델 예측하기

pred = model.predict(x_test)

 

예측값과 실제값 비교(with plot)

import matplotlib.pyplot as plt

plot_figure = plt.figure(figsize=(30, 10))
plot_rst = plot_figure.add_subplot(111)
plot_rst.plot(y_test, label='Real')
plot_rst.plot(pred, label='Predict')
plot_rst.legend()
plt.show()

얼추 비슷해 보이지만, 이것을 가지고 주가 예측을 하기에는 리스크가 크다.

아무래도 주가에 영향을 주는 변수는 많이 있기 때문이다. 주식에 관심 있으신 분들은 자신만의 전략을 만들고,

여러 정보를 변수화를 하여 모델을 만들어야 할 것이다.

 

물론 모든 게 참고 사항이며, 주식은 남들이 주는 고급 정보로 조심스럽게 접근하는 것이 최고인 듯싶다ㅜㅜ!

반응형

텐서플로 및 케라스 모듈 설정

import numpy as np
from matplotlib import pyplot as plt
from tensorflow.keras.datasets import mnist
from tensorflow.keras import models, layers
from tensorflow.keras.utils import to_categorical

데이터 설정

(train_images, train_labels), (test_images, test_labels) = mnist.load_data()
check_image = test_images[24]
checking_img = check_image.reshape((1, 28*28))
train_images = train_images.reshape((60000, 28*28))
train_images = train_images.astype('float32')/255
test_images = test_images.reshape((10000, 28*28))
test_images = test_images.astype('float32')/255
train_labels = to_categorical(train_labels)
test_labels = to_categorical(test_labels)

모델 구성

model = models.Sequential()
model.add(layers.Dense(512, activation='relu', input_shape=(28*28, )))
model.add(layers.Dense(256, activation='relu'))
model.add(layers.Dense(128, activation='relu'))
model.add(layers.Dense(64, activation='relu'))
model.add(layers.Dense(10, activation='softmax'))

모델 컴파일

model.compile(optimizer = 'rmsprop',
              loss = 'categorical_crossentropy',
              metrics = ['accuracy'])

모델 학습

model.fit(train_images, train_labels, epochs=5, batch_size=128)

모델 평가

test_loss, test_acc = model.evaluate(test_images, test_labels)

모델 예측

output = model.predict(checking_img)
반응형

이미지 스캐너 만들기

예제 이미지 : 

(직접 찍은 사진을 올려서 테스트 진행하는 것을 추천 드립니다. 없는 분들은 다운로드해서 사용 가능)

예제 코드 :

import numpy as np
import cv2


def draw_borderline(img, corners):
    copy_image = img.copy()
    for pt in corners:
        cv2.circle(copy_image, tuple(pt), 20, (0, 255, 255), -1, 1)
    cv2.line(copy_image, tuple(corners[0]), tuple(corners[1]), (0, 255, 255), 4, 5)
    cv2.line(copy_image, tuple(corners[1]), tuple(corners[2]), (0, 255, 255), 4, 5)
    cv2.line(copy_image, tuple(corners[2]), tuple(corners[3]), (0, 255, 255), 4, 5)
    cv2.line(copy_image, tuple(corners[3]), tuple(corners[0]), (0, 255, 255), 4, 5)
    return copy_image


def onMouse(event, x, y, flags, param):
    global points
    if event == cv2.EVENT_LBUTTONDOWN:
        for i in range(4):
            if cv2.norm(start_points[i] - (x, y)) < 20:
                drag_points[i] = True
                points = (x, y)
                break

    if event == cv2.EVENT_LBUTTONUP:
        for i in range(4):
            drag_points[i] = False

    if event == cv2.EVENT_MOUSEMOVE:
        for i in range(4):
            if drag_points[i]:
                dx = x - points[0]
                dy = y - points[1]
                start_points[i] += (dx, dy)
                cpy = draw_borderline(image, start_points)
                cv2.imshow('image', cpy)
                points = (x, y)
                break


# 불러올 이미지 지정
image = cv2.imread('choco.jpg')

# 이미지 세로와 너비 추출
h, w = image.shape[:2]

result_w = 210 * 3
result_h = 297 * 3

# 모서리 점들의 좌표, 드래그 상태 여부
start_points = np.array([[50, 50], [50, h-50], [w-50, h-50], [w-50, 50]], np.float32)
end_points = np.array([[0, 0], [0, result_h-1], [result_w-1, result_h-1], [result_w-1, 0]], np.float32)

# 현재 드래그 하는 포인트를 기억하는 함수, 눌러지게 되면 True로 변경됨, 놓으면 다시 False
drag_points = [False, False, False, False]

# 모서리점, 사각형 그리기
borderline = draw_borderline(image, start_points)
# cv2.namedWindow('image',cv2.WINDOW_NORMAL)
cv2.imshow('image', borderline)
cv2.setMouseCallback('image', onMouse)

while True:
    key = cv2.waitKey()

실습내용 :

1. 예제 코드 해석 : 함수 이해 (draw_borderline , onMouse)

2. 파일 이미지가 너무 크면, 창 크기를 조절할 수 있는 함수 사용할 것. (주석 처리)

3. enter 키를 누르면, 결과가 출력되고, esc 키를 누르면 종료되게끔 작동을 한다.

4. 결과 : 변환 함수를 사용하여 결과 이미지를 출력한다.

 

힌트 :

(OpenCV - 영상(이미지) 다루기(9)_(이미지 변환 응용))

 

OpenCV - 영상(이미지) 다루기(9)_(이미지 변환 응용)

이전 포스팅에서, 이미지 변환(회전)에 대해서 알아보았는데요, 영상처리에서 가장 중요한 부분이기도 하기 때문에 따로 포스팅을 해두었습니다. 이미지 회전에서는 어파인(Affine) 변환과 투시(P

dk-kang.tistory.com

이 문서를 참고하시면 됩니다.

* 마우스 커서 움직이는 좌표는 start_points의 기록됨. 출력된 결과를 나타내줄 좌표는 end_points (미리 선언함)

적절한 변환 함수만 추가하여 이미지를 변환 후, 그 이미지를 출력하면 됩니다.

 

참고 :

원 또는 line 설정(크기, 색깔)을 원하는 형태로 바꾸셔도 무방.

 

응용 :

완성된 이미지를 저장하여 스캐너 프래그램으로 사용 가능.

그레이스케일 처리 하면, 카피본으로 사용 가능.

이진처리를 하면, 문서 스캐너로도 활용 가능.

 

 

반응형
import numpy as np
import cv2


def draw_borderline(img, corners):
    copy_image = img.copy()
    for pt in corners:
        cv2.circle(copy_image, tuple(pt), 20, (0, 255, 255), -1, 1)
    cv2.line(copy_image, tuple(corners[0]), tuple(corners[1]), (0, 255, 255), 4, 5)
    cv2.line(copy_image, tuple(corners[1]), tuple(corners[2]), (0, 255, 255), 4, 5)
    cv2.line(copy_image, tuple(corners[2]), tuple(corners[3]), (0, 255, 255), 4, 5)
    cv2.line(copy_image, tuple(corners[3]), tuple(corners[0]), (0, 255, 255), 4, 5)
    return copy_image


def onMouse(event, x, y, flags, param):
    global points
    if event == cv2.EVENT_LBUTTONDOWN:
        for i in range(4):
            if cv2.norm(start_points[i] - (x, y)) < 20:
                drag_points[i] = True
                points = (x, y)
                break

    if event == cv2.EVENT_LBUTTONUP:
        for i in range(4):
            drag_points[i] = False

    if event == cv2.EVENT_MOUSEMOVE:
        for i in range(4):
            if drag_points[i]:
                dx = x - points[0]
                dy = y - points[1]
                start_points[i] += (dx, dy)
                cpy = draw_borderline(image, start_points)
                cv2.imshow('image', cpy)
                points = (x, y)
                break


# 불러올 이미지 지정

image = cv2.imread('text_book.jpg')
print(image.shape)
# 이미지 세로와 너비 추출
h, w = image.shape[:2]

# 결과 영상 화면 세팅 (210 * 297) a4 용지 규격으로 설정함.
result_w = 210 * 3
result_h = 297 * 3

# 모서리 점들의 좌표, 드래그 상태 여부
start_points = np.array([[50, 50], [50, h-50], [w-50, h-50], [w-50, 50]], np.float32)
end_points = np.array([[0, 0], [0, result_h-1], [result_w-1, result_h-1], [result_w-1, 0]], np.float32)

# 현재 드래그 하는 포인트를 기억하는 함수, 눌러지게 되면 True로 변경됨, 놓으면 다시 False
drag_points = [False, False, False, False]

# 모서리점, 사각형 그리기
borderline = draw_borderline(image, start_points)
cv2.namedWindow('image',cv2.WINDOW_NORMAL)
# cv2.resizeWindow('image', int(h/4), int(w/4))
cv2.imshow('image', borderline)
cv2.setMouseCallback('image', onMouse)

while True:
    key = cv2.waitKey()
    if key == 13:
        break
    elif key == 27:
        cv2.destroyWindow('image')

# 투시 변환
perspective_transform = cv2.getPerspectiveTransform(start_points, end_points)
final_result = cv2.warpPerspective(image, perspective_transform, (result_w, result_h), flags=cv2.INTER_CUBIC)

# 결과 영상 출력
cv2.imshow('dst', final_result)
cv2.waitKey()
cv2.destroyAllWindows()
반응형

이전 포스팅에서, 이미지 변환(회전)에 대해서 알아보았는데요, 영상처리에서 가장 중요한 부분이기도 하기 때문에 따로 포스팅을 해두었습니다.

 

이미지 회전에서는 어파인(Affine) 변환과 투시(Perspective) 변환을 사용합니다.

 

어파인 변환은 원본 모양 및 비율을 유지하거나 사각형의 모양(사다리꼴 형태가 아닌)으로 변환을 뜻합니다.

어파인 변환은 행렬 값으로 변환 시킬 수 있는데 이 때, 변환된 수치를 나타내주는 행렬(변환 행렬)은 2x3 형태로 나타날 수 있습니다.

(일반 사각형 모양을 유지해주기 때문에, 우리는 점 3개의 변화량만 알면 되기 때문)

 

투시 변환은 다음과 같이 변환을 하면서 평행사변형이나 사다리꼴 형태로 변환이 되는 것을 뜻합니다.

투시 변환은 행렬 값으로 변환 시킬 때, 3x3 행렬의 형태로 나타날 수 있습니다.

(일반 사각형 모양이 아니기 때문에, 우리는 점 4개의 변화량을 다 알아야 함. 8개의 값을 알아야 하기 때문에, 변환 행렬은 3x3행렬 사용)

 

사실, 우리는 정확한 이론은 몰라도 됩니다. 행렬이 어떻게 구성되고 어떻게 표현되는지 모르셔도 상관 없습니다. (open cv에서 제공 되는 함수를 사용할 것이기 때문)

그냥 어파인 변환은 언제 쓰이고, 투시 변환은 언제 쓰이는지만 알면 됩니다.

 

그럼 혹시라도, 원본 이미지를 특정한 모양으로 변환 시켜주거나, 변환된 이미지를 원본으로 되돌리고 싶을 때 변환행렬 값을 알아야 되는데요...

 

어파인 변환이 일어났다면, cv2.getAffineTransform 으로 변환행렬을 구하면 되고,

투시 변환이 일어났다면, cv2.getPerspectiveTransform 으로 변환행렬을 구하면 됩니다.

 

cv2.getAffineTransform 함수를 사용하여 변환행렬을 알기 위해서는, 3개의 원본 좌표(3x2행렬)과 3개의 변화될 좌표(3x2행렬)를 알면 됩니다.

cv2.getAffineTransform(원본 좌표(3x2행렬), 변화될 좌표(3x2행렬))

 

cv2.getPerspectiveTransform 함수도 마찬가지로 변환행렬을 알기 위해서는, 4개의 원본 좌표(3x3행렬)과 4개의 변화될 좌표(3x3행렬)를 알면 됩니다.

 

cv2.getPerspectiveTransform (원본 좌표(3x3행렬), 변화될 좌표(3x3행렬))

변환 행렬을 알았다면, 우리는 변환행렬에 맞게 영상을 회전시킬 수가 있는데요.. 이 때 사용할 수 있는 함수는

 

wrapAffine 함수와, wrapPerspective 함수입니다.

 

wrapAffine 함수는 이전 포스팅에서 말씀 드렸다시피, cv2.warpAffine(원본 이미지, 변환 행렬(2x3), (width, height))) 로 나타내면 됩니다.

그러면 원본 이미지가 변환행렬에 나와있는 행렬값에 따라서 지정된 너비와 높이갚으로 이미지를 변환 시켜줍니다.

 

wrapPerspective 도 마찬가지로 cv2.wrapPerspective(원본 이미지, 변환 행렬(3x3), (width, height))) 을 사용해주면 됩니다.

마찬가지로, 원본 이미지가 변환행렬에 나와있는 행렬값에 따라서 지정된 너비와 높이갚으로 이미지를 변환 시켜줍니다.

 

코드 예제를 통해서 확인해보도록 하겠습니다.

실습에 사용할 이미지는 다음과 같습니다. 이미지를 다운 받으셔서 실습 환경에 저장 시켜두면 됩니다.

text_book.jpg

설명한 내용 토대로, 사진에서 실전 딥러닝 책만 추출하여 반듯한 이미지로 나타내보도록 하겠습니다.

import cv2
import numpy as np

img = cv2.imread('text_book.jpg')
w = 300
h = 400
location = np.array([[723, 477], [976, 374], [1177, 722], [908, 855]], np.float32)
location2 = np.array([[0, 0], [w, 0], [w, h], [0, h]], np.float32)
pers = cv2.getPerspectiveTransform(location, location2)
dst = cv2.warpPerspective(img, pers, (w,h))
cv2.imshow('origin', img)
cv2.imshow('result', dst)
cv2.waitKey()

결과 값은 다음과 같습니다.

 

반응형

예제 영상 파일

choco.jpg

예제 파일은 아무 이미지 파일로 사용하셔도 됩니다. 저는 귀여운 강아지 초코로 진행해볼 예정입니다.

파일을 다운받으셔서 같은 환경(실행하는 파이썬 디렉터리)에 저장을 시켜 둡니다.

(만약 다른 곳에 있다면 경로를 아셔야 합니다)

 

이미지 변환 함수

- flip

flip 함수는 영상에 회전을 줄 때, 사용합니다.

flip 코드가 0 이면, 상하 방향 대칭

img = cv2.imread('choco.jpg')
img = cv2.flip(img, flipCode=0)

 

flip 코드가 1이면 좌우 방향으로 대칭이 됩니다.

img = cv2.imread('choco.jpg')
flp_img = cv2.flip(img, flipCode=1)
cv2.imshow('image', flp_img)
cv2.waitKey()

 

(Tip, flip -1을 넣으면 좌우 및 상하 대칭)

- getRotationMatrix2D

getRotationMatrix2D 함수는 중심점(X좌표, Y좌표), 각도, 스케일을 설정하여 회전시킬 수 있습니다.

(함수 사용 예시 : cv2.getRotationMatrix2D(중심점, 각도, 스케일))

중심점 : 튜플 형태로 사진의 기준점

각도 : 회전할 각도

스케일 : 이미지 확대 비율

실행 결과값은, 변환된 행렬 값으로 나타나 집니다.

- wrapAffine

getRotationMatrix2D는 돌려만 주는 함수이기 때문에, warpAffine함수를 통해서 다시 정의해줍니다.

warpAffine은 이미지를 변환한 행렬 값을 바꿔주는 함수입니다.

(함수 사용 예시 : cv2.warpAffine(원본 이미지, 변환 행렬, (width, height)))

 

다음 코드는 이미지 중심으로부터 90도를 회전한 후, wrapAffine함수를 통해서 이미지를 나타낸 것입니다.

img = cv2.imread('choco.jpg')
height, width = img.shape[:2]
print(height, width)
rotate = cv2.getRotationMatrix2D((width/2, height/2), 90, 1)
rotate_img = cv2.warpAffine(img, rotate, (width, height))
cv2.imshow('image', rotate_img)
cv2.waitKey()

(tip, img.shape()를 통해서 이미지 크기를 알아낸 후, 2로 나누면 중심점을 쉽게 잡을 수 있습니다.)

 

- resize

이미지 크기를 조절할 때, 사용합니다. 두 가지 방법이 있습니다.

하나는, 원하는 사이즈로 변환을 할 경우입니다.

(함수 예시 : cv2.resize(원본 이미지, dsize(변환할 너비, 변환할 높이) )

img = cv2.imread('choco.jpg')
dist_img = cv2.resize(img, dsize=(640, 480))
cv2.imshow('image', dist_img)
cv2.waitKey()

두 번째로는, 원하는 비율로 변환할 경우입니다.

(함수 예시 : cv2.resize(원본 이미지, dsize(0, 0), fx=가로축 비율, fx 세로축 비율 )

img = cv2.imread('choco.jpg')
rate_img = cv2.resize(img, dsize=(0, 0), fx=0.5, fy=0.5)
cv2.imshow('image2', rate_img)
cv2.waitKey()

(Tip, 비율 사용 시, dsize의 값이 있을 경우, 해당 값에서의 비율로 반영이 됩니다.)

또한 추가적으로, interpolation이라는 옵션이 있는데, 보통 cv2.INTER_LINEAR(쌍 선형 보간법)을 주로 사용하고, default 값입니다. 현재 코드에서도 interpolation 옵션을 사용하지 않았기 때문에 INTER_LINEAR이 자동 적용되었습니다.

 

속성에 종류로는

속성 의미 주로 사용 하는 경우
cv2.INTER_NEAREST 이웃 보간법  
cv2.INTER_LINEAR 쌍 선형 보간법 기본 (이미지 확대)
cv2.INTER_LINEAR_EXACT 비트 쌍 선형 보간법  
cv2.INTER_CUBIC 바이큐빅 보간법 이미지를 확대할 경우
(느리지만 확대시
깨지는 것 방지)
cv2.INTER_AREA 영역 보간법 이미지를 축소할 경우
cv2.INTER_LANCZOS4 Lanczos 보간법 이미지를 확대할 경우
(정말 느리지만 확대시
깨지는 것 방지)

사용 예시 :

img = cv2.imread('choco.jpg')
rate_img = cv2.resize(src, dsize=(0, 0), fx=0.5, fy=0.5, interpolation=cv2.INTER_LINEAR)
cv2.imshow('image2', rate_img)
cv2.waitKey()

 

 

 

 

 

반응형

예제 영상 파일

choco.jpg

예제 파일은 아무 이미지 파일로 사용하셔도 됩니다. 저는 귀여운 강아지 초코로 진행해볼 예정입니다.

파일을 다운받으셔서 같은 환경(실행하는 파이썬 디렉터리)에 저장을 시켜 둡니다.

(만약 다른 곳에 있다면 경로를 아셔야 합니다)

 

트랙 바 사용

이번에 알아볼 것은 트랙 바라는 일종의 스크롤 바입니다. 이 스크롤바는 슬라이더 형태를 갖고 있으며, 일정 범위 내의 값들의 수치를 변경할 수 있습니다.

이번 실습은, 그레이스케일 이미지에서 이진화 처리를 해주는 트랙 바를 만들어 보겠습니다. 이진화는 영상을 흑과 백으로 분류하여 나타 내주는 것입니다. 이 때, 어떤 기준으로 흑인지 백인지 나눠주는 경곗값이 필요한데, 우리는 이러한 경곗값을 임계값이라고 합니다. 즉 임계값보다 작으면 흑, 크면 백이라고 생각하시면 됩니다. 우리는 임계값을 조절해주는 트랙 바를 만들어서 이미지를 흑과 백으로 나누어 보는 트랙 바를 만들어 보겠습니다.

 

먼저 트랙바의 필요한 변수를 살펴보도록 하겠습니다.

- createTrackbar

트랙 바를 사용하기 위해서는 createTracbar로 windows창을 띄운 후에 설정을 해주셔야 합니다. 트랙 바 변수를 살펴보면...

 

cv2.createTrackbar(trackBarName, windowsName, 최솟값, 최댓값, 콜백 함수)

 

trackBarName 은, 트랙바 생성 시, 트랙 바의 이름을 지정

windowsName은 트랙바를 나타낼 윈도 창의 이름

최솟값은 트랙바 범위의 시작 값

최댓값은 트랙 바 범위의 마지막 값

콜백 함수는 트랙 바 바를 조절 시, 위치한 값을 전달해 주는 것 (특별한 이벤트를 처리하지 않더라도, 필수적으로 함수는 만들 것)

 

우리는 그레이 스케일 이미지에서 밝기만 바꿔주면서 이미지를 확인할 것이며, 다른 특별한 처리를 하지 않을 것이기 때문에 콜백 함수는 아무것도 작동을 안 하는 fake function을 다음과 같이 정의하도록 하겠습니다.

def call_back(x) :
    pass

windowsName은 image라고 정의를 한 후에, 그레이 스케일이 적용된 초코 이미지를 설정해두겠습니다.

img = cv2.imread("choco.jpg", cv2.IMREAD_GRAYSCALE)
cv2.imshow('image', img)

그럼, 트랙 바 생성에 필요한 변수 설정은 다 되었습니다. (이미지 밝기 0~255이기 때문에 최솟값=0, 최댓값=255)

cv2.createTrackbar('threshold', 'image', 0, 255, call_back)

트랙 바가 생성 시, 초기 임계값을 몇에 둘 것인지를 세팅해줍니다. (예제 코드는, 중간값인 127로 설정)

cv2.setTrackbarPos('threshold', 'image', 127)

- threshold

threshold 함수는, 이진화 처리를 해주는 함수로써, 특정한 임계값을 기준으로 흑과 백으로 구분해줍니다.

그럼 threshold의 변수를 살펴보도록 하겠습니다.

 

cv2.threshold(image, thresh, maxval, type)

 

image는 우리가 이진화 처리할 이미지이고,

thresh는 흑과 백을 나눠줄 임계값이고,

maxval - 임계값을 넘었을 때, 어떻게 처리할 것인지..

type은 thresholding type입니다.(THRESH_BINARY, THRESH_BINARY_INV, THRESH_TRUNC, THRESH_TOZERO, THRESH_TOZERO_INV)

 

임계값을 정해줄 low라는 변수를 만들었습니다. getTrackbarPos는 트랙 바에서 우리가 스크롤로 설정한 값을 받아 오는 것입니다.

우리는 그레이 스케일 초코 이미지(img)를 image 변수에 넣고, 임계값을 초과하면 255로 되도록 지정을 해주었습니다. (255가 max값이기 때문). 그리고 타입은 이진 처리를 위해 THRESH_BINARY를 사용하였습니다. 임계값이 움직일 때마다 현재 이미지에 보이도록 imshow함수를 바로 불러줍니다.

low = cv2.getTrackbarPos('threshold', 'image')
cv2.threshold(img, low, 255, cv2.THRESH_BINARY)
cv2.imshow('image', img_binary)

우리는 1초에 한 번씩 waitKey값이 27 즉 esc를 눌렀는지 안 눌렀는지 체크를 해주는 구문을 만들어서 threshold 함수에 따른 이미지 변화를 보여주도록 세팅을 해두었습니다.

while True :
    low = cv2.getTrackbarPos('threshold', 'image')
    ret, img_binary = cv2.threshold(img, low, 255, cv2.THRESH_BINARY)
    cv2.imshow('image', img_binary)
    if cv2.waitKey(1) == 27 :
        break

 

완성된 코드는 다음과 같습니다.

 

def call_back(pos) :
    pass

img = cv2.imread("choco.jpg", cv2.IMREAD_GRAYSCALE)
cv2.imshow('image', img)
cv2.createTrackbar('threshold', 'image', 0, 255, call_back)
cv2.setTrackbarPos('threshold', 'image', 127)

while True :
    low = cv2.getTrackbarPos('threshold', 'image')
    ret, img_binary = cv2.threshold(img, low, 255, cv2.THRESH_BINARY)
    cv2.imshow('image', img_binary)
    if cv2.waitKey(1) == 27 :
        break
반응형

예제 영상 파일

choco.jpg

예제 파일은 아무 이미지 파일로 사용하셔도 됩니다. 저는 귀여운 강아지 초코로 진행해볼 예정입니다.

파일을 다운받으셔서 같은 환경(실행하는 파이썬 디렉터리)에 저장을 시켜 둡니다.

(만약 다른 곳에 있다면 경로를 아셔야 합니다)

 

마우스 함수

이번에는 마우스를 통해서 cv2를 활용할 수 있는 방법에 대해서 알아보도록 하겠습니다.

(실습을 하시면서 이해하시는게 빠릅니다)

cv2.setMouseCallback(windowName, onMouse, param=None)

기본적으로 마우스 함수는 이런식으로 사용이 가능합니다. windowName 변수가 있듯이 이 함수는 새로운 윈도우창을 띄우기 때문에, 윈도우 환경에서만 사용이 가능합니다.

windowName 변수는 마우스 이벤트를 처리할 윈도우창 이름이고,

onMouse 는 우리가 어떻게 이벤트 처리를 할지 지정하는 함수를 부르는 것입니다. (밑에 설명)

param 값은 이벤트 발생시 주고받을 값이 있으면 지정해주는 값입니다.

 

onMouse(event, x, y, flags, param)

onMouse 함수는, 우리가 세팅을 할 함수 입니다.

event 는 마우스 이벤트 종류(밑에 설명)

x 는 마우스 이벤트가 발생한 x좌표,

y 는 마우스 이벤트가 발생한 y좌표 입니다.

flags는 마우스 이벤트 발생 시 나타나는 종류(밑에 설명) 입니다.

 

event 는 마우스 이벤트 종류

설명

EVENT_MOUSEMOVE

마우스가 창 위에서 움직이는 경우

EVENT_LBUTTONDOWN

왼쪽 버튼이 눌려지는 경우

EVENT_RBUTTONDOWN

오른쪽 버튼이 눌려지는 경우

EVENT_MBUTTONDOWN

가운데 버튼이 눌려지는 경우

EVENT_LBUTTONUP

왼쪽 버튼이 떼어지는 경우

EVENT_RBUTTONUP

오른쪽 버튼이 떼어지는 경우

EVENT_MBUTTONUP

가운데 버튼이 떼어지는 경우

EVENT_LBUTTONDBLCLK

왼쪽 버튼을 더블클릭하는 경우

EVENT_RBUTTONDBLCLK

오른쪽 버튼을 더블클릭하는 경우

EVENT_MBUTTONDBLCLK

가운데 버튼을 더블클릭하는 경우

EVENT_MOUSEWHEEL

휠을 앞뒤로 돌리는 경우

EVENT_MOUSEHWHEEL

휠을 좌우로 움직이는 경우

MouseEventFlags 이벤트 종류

설명

EVENT_FLAG_LBUTTON

왼쪽 버튼이 눌려져 있음

EVENT_FLAG_RBUTTON

오른쪽 버튼이 눌려져 있음

EVENT_FLAG_MBUTTON

가운데 버튼이 눌려져 있음

EVENT_FLAG_CTRLKEY

CTRL 키가 눌려져 있음

EVENT_FLAG_SHIFTKEY

SHIFT 키가 눌려져 있음

EVENT_FLAG_ALTKEY

ALT 키가 눌려져 있음

 

다음 예제는 초코 이미지에서

왼쪽 마우스 클릭 했을 때, 클릭을 때어낼 때, 마우스를 이동할 때 좌표를 출력하고,

왼쪽 마우스로 드래그 시, 원모양의 라인을 그릴 수 있는 코드입니다.

`

import cv2

def onMouse(event, x, y, flags, param) :
    if event == cv2.EVENT_LBUTTONDOWN :
        print('왼쪽 마우스 클릭 했을 때 좌표 : ', x, y)
    elif event == cv2.EVENT_LBUTTONUP :
        print('왼쪽 마우스 클릭 땠을 때 좌표 : ', x, y)
    elif event == cv2.EVENT_MOUSEMOVE:
        print('현재 이동하는 좌표 : ', x, y)
        if flags & cv2.EVENT_FLAG_LBUTTON :
            cv2.circle(img, (x,y), 5, (0,0,255), -1)
            cv2.imshow('image', img)

img = cv2.imread('choco.jpg')
cv2.imshow('image', img)
cv2.setMouseCallback('image', onMouse)
cv2.waitKey()

(tip, flags & cv2.EVENT_FLAG_LBUTTON 라고 표현을 하였습니다. 사실 & 대신 == 을, 사용해도 정상 작동은 되나, 보통 flag 함수 사용시 & 연산자를 이용)

 

파이썬 출력 결과 값

현재 이동하는 좌표 :  191 414
현재 이동하는 좌표 :  192 414
왼쪽 마우스 클릭 했을 때 좌표 :  192 414
왼쪽 마우스 클릭 땠을 때 좌표 :  192 414
현재 이동하는 좌표 :  192 414
왼쪽 마우스 클릭 땠을 때 좌표 :  192 414
현재 이동하는 좌표 :  193 414
현재 이동하는 좌표 :  194 414
현재 이동하는 좌표 :  195 414
현재 이동하는 좌표 :  196 414
현재 이동하는 좌표 :  197 414
현재 이동하는 좌표 :  198 414

 

 

반응형

예제 영상 파일

choco.jpg

예제 파일은 아무 이미지 파일로 사용하셔도 됩니다. 저는 귀여운 강아지 초코로 진행해볼 예정입니다.

파일을 다운받으셔서 같은 환경(실행하는 파이썬 디렉터리)에 저장을 시켜 둡니다.

(만약 다른 곳에 있다면 경로를 아셔야 합니다)

 

이미지 그리기 함수

이미지를 다루게 되면, 수정을 하는 경우가 발생하는데요, 원본 이미지랑 분리를 시키기 위해서 copy함수를 사용합니다.

img = cv2.imread('choco.jpg')
copy_img = img.copy()

다음과 같이 사용을하면, copy_img를 생성할 수 있습니다.

 

copy 된 이미지에서 원하는 부분만 잘라보도록 하겠습니다. 이때 우리는, 일부 이미지를 자르기 위해서 파이썬 기본 문법인 리스트 슬라이싱을 사용합니다. 이미지에서 세로 부분과 가로 부분의 범위를 주어서 이미지를 잘라 낼 수 있습니다.

img = cv2.imread('choco.jpg')
copy_img = img.copy()
img2 = copy_img[20:500, 300:600]
cv2.imshow('image2', img2)
cv2.waitKey()

우리는 이렇게, 지정된 범위를 잘라내서, 초코만을 뽑아 낼 수 있었습니다. copy함수를 사용하였기 때문에, 원본(img)은 보존되고, 새로운 img를 얻어낼 수 있습니다.

- line

line 함수는 이미지에, 선을 넣는(그리는) 함수 입니다.

사용법은 cv2.line(원본 이미지, 시작점(x, y) 좌표 끝점(x, y) 좌표, (B, G, R), 두께, 선형 굵기)입니다.

다음 예제는, 제가 정한 사각형에, BGR 중 GREEN 컬러로 두께가 2인 사각형을 그리는 예제입니다.

img = cv2.imread('choco.jpg')
copy_img = img.copy()
img2 = copy_img[20:500, 300:600]
cv2.line(img2, (120,135), (150,160), (0,255,0), 2)
cv2.imshow('image2', img2)
cv2.waitKey()

-rectangle

circle 함수는 이미지에, 사각형을 넣는(그리는) 함수입니다. line함수와 비슷한데, line의 대각선을 갖도록 하는 사각형을 그려주는 함수 입니다.

사용법은 cv2.rectangle(원본 이미지, 시작점(x, y) 종료점(x, y), (B, G, R), 두께, 선형 굵기)입니다.

다음 예제는, 제가 정한 사각형에, BGR 중 GREEN 컬러로 두께가 2인 사각형을 그리는 예제입니다.

img = cv2.imread('choco.jpg')
copy_img = img.copy()
img2 = copy_img[20:500, 300:600]
cv2.rectangle(img2, (120,135), (150,160), (0,255,0), 2)
cv2.imshow('image2', img2)
cv2.waitKey()

-circle

circle 함수는 이미지에, 원을 넣는(그리는) 함수입니다.

사용법은 cv2.circle(원본 이미지, 좌표 (x, y), 반지름, (B, G, R), 두께, 선형 굵기)입니다.

 

다음 예제는, 제가 정한 x, y 좌표에 반지름이 20이고, BGR 중 RED 컬러로 두께가 2인 원을 두 개 그리는 예제입니다.

img = cv2.imread('choco.jpg')
copy_img = img.copy()
img2 = copy_img[20:500, 300:600]
cv2.circle(img2, (115,120), 20, (0,0,255), 2)
cv2.circle(img2, (175,120), 20, (0,0,255), 2)
cv2.imshow('image2', img3)
cv2.waitKey()

-ellipse

ellipse함수는 호를 그려주는 함수입니다.

사용법은 cv2.ellipse(원본 이미지, 중심점(x, y), (lr, sr), 각도, 시작 각도, 종료 각도, (B, G, R), 두께, 선형 굵기)

lr은 가장 먼 거리를 지나는 점이고, sr은 가장 가까운 거리를 가지는 지점입니다.

 

다음 예제는, 제가 정한 x, y 좌표에 45도에서 가까운 (30~50) 정도 떨어져 있고 45도~135도 사이에 있는 호를,

BGR 중 RED 컬러로 두께가 2인 원을 두 개 그리는 예제입니다.

img = cv2.imread('choco.jpg')
copy_img = img.copy()
img2 = copy_img[20:500, 300:600]
cv2.ellipse(img2, (140, 120), (30, 50), 0, 45, 135, (0, 0, 255), 2)
cv2.imshow('image2', img2)
cv2.waitKey()

-polylines, fillPoly

poly함수는 다각형을 그려주는 함수입니다. polylines는 다각형 외곽만 표시해주는 함수이고, fillPoly는 색상이 채워진 다각형을 그려주는 함수입니다.

poly 함수를 사용하는 경우, numpy로 지정한 위치 좌표를 설정해주셔야 합니다.

 

함수 사용법은

cv2.polylines(원본 이미지, [numpy로 설정한 위치 좌표], 닫힘 유/무, (B, G, R), 두께, 선형 굵기)

cv2.fillPoly(원본 이미지, [numpy로 설정한 위치 좌표], (B, G, R), 두께, 선형 굵기)

입니다.

img = cv2.imread('choco.jpg')
copy_img = img.copy()
img2 = copy_img[20:500, 300:600]
import numpy as np
polly1_np = np.array([[90, 100], [200, 100], [145, 180]])
polly2_np = np.array([[90, 250], [200, 250], [145, 180]])
cv2.polylines(img2, [polly1_np], True, (0, 255, 255), 2)
cv2.fillPoly(img2, [polly2_np], (255, 0, 255), cv2.LINE_AA)
cv2.imshow('image2', img2)
cv2.waitKey()

-putText

putText함수는 이미지에 글자를 넣어주는 함수입니다.

함수 사용법은 cv2.putText(원본 이미지, 원하는 글자, 글자 위치 (x, y), 글꼴, 글자 크기, (B, G, R), 글자 굵기)

입니다.

img = cv2.imread('choco.jpg')
copy_img = img.copy()
img2 = copy_img[20:500, 300:600]
cv2.putText(img2, "CHOCO", (90, 300), cv2.FONT_HERSHEY_COMPLEX, 1, (0, 255, 0), 2)
cv2.imshow('image2', img2)
cv2.waitKey()

Tip. 선형 굵기 대신, 선형 타입을 넣어도 됩니다.

선형 종류에는 (cv2.FILLED(내부 채움), cv2.LINE_4(4점 연결), cv2.LINE_8(8점 연결), cv2.LINE_AA(AntiAlias)) 가 있습니다.

 

또한, 사용할 수 있는 글자 종류에는

 

cv2.FONT_HERSHEY_SIMPLEX
cv2.FONT_HERSHEY_PLAIN
cv2.FONT_HERSHEY_DUPLEX
cv2.FONT_HERSHEY_COMPLEX
cv2.FONT_HERSHEY_TRIPLEX
cv2.FONT_HERSHEY_COMPLEX_SMALL
cv2.FONT_HERSHEY_SCRIPT_SIMPLEX
cv2.FONT_HERSHEY_SCRIPT_COMPLEX
cv2.FONT_ITALIC

 

순서대로, 표현해두었습니다. 확인하고 마음에 드는 글꼴을 선택하시면 됩니다.

 

반응형

+ Recent posts