새로새록

python - opencv: Filtering. KNN 본문

소프트웨어융합/파이썬 기타.py

python - opencv: Filtering. KNN

류지나 2021. 9. 28. 09:35

 

Filtering
  • 특정한 이미지에서 커널(Kernel)을 적용해 컨볼루션 계산하여 필터링을 수행할 수 있습니다.

직접 필터 적용하기

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

image = cv2.imread('Downloads/gray_image.png')

plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.show()

size =4
kernel= np.ones((size, size), np.float32)/ (size**2)
print(kernel)

dst =cv2.filter2D(image, -1, kernel)
plt.imshow(cv2.cvtColor(dst, cv2.COLOR_BGR2RGB))
plt.show()

 

직접 커널을 생성하여 필터 적용하기

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

image = cv2.imread('gray_image.jpg') 
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.show() 

size = 4 
kernel = np.ones((size, size), np.float32) / (size ** 2) 
print(kernel) dst = cv2.filter2D(image, -1, kernel) 
plt.imshow(cv2.cvtColor(dst, cv2.COLOR_BGR2RGB)) 
plt.show()

[[0.0625 0.0625 0.0625 0.0625] [0.0625 0.0625 0.0625 0.0625] [0.0625 0.0625 0.0625 0.0625] [0.0625 0.0625 0.0625 0.0625]]

Basic Blurring

import cv2 
import matplotlib.pyplot as plt
image = cv2.imread('gray_image.jpg') 
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB)) 
plt.show() 

dst = cv2.blur(image, (4, 4)) 
plt.imshow(cv2.cvtColor(dst, cv2.COLOR_BGR2RGB))
plt.show()

Gaussian Blur

import cv2 
image = cv2.imread('gray_image.jpg') 
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB)) 
plt.show() 

# kernel_size: 홀수
dst = cv2.GaussianBlur(image, (5, 5), 0)
plt.imshow(cv2.cvtColor(dst, cv2.COLOR_BGR2RGB)) 
plt.show()


KNN
import cv2
import numpy as np
from matplotlib import pyplot as plt

# 각 데이터의 위치: 25 X 2 크기에 각각 0 ~ 100
trainData = np.random.randint(0, 100, (25, 2)).astype(np.float32)
# 각 데이터는 0 or 1
response = np.random.randint(0, 2, (25, 1)).astype(np.float32)

# 값이 0인 데이터를 각각 (x, y) 위치에 빨간색으로 칠합니다.
red = trainData[response.ravel() == 0]
plt.scatter(red[:, 0], red[:, 1], 80, 'r', '^')
# 값이 1인 데이터를 각각 (x, y) 위치에 파란색으로 칠합니다.
blue = trainData[response.ravel() == 1]
plt.scatter(blue[:, 0], blue[:, 1], 80, 'b', 's')

# (0 ~ 100, 0 ~ 100) 위치의 데이터를 하나 생성해 칠합니다.
newcomer = np.random.randint(0, 100, (1, 2)).astype(np.float32)
plt.scatter(newcomer[:, 0], newcomer[:, 1], 80, 'g', 'o')

knn = cv2.ml.KNearest_create()
knn.train(trainData, cv2.ml.ROW_SAMPLE, response)
ret, results, neighbours, dist = knn.findNearest(newcomer, 3)

# 가까운 3개를 찾고, 거리를 고려하여 자신을 정합니다.
print("result : ", results)
print("neighbours :", neighbours)
print("distance: ", dist)

plt.show()

result : [[1.]] neighbours : [[1. 1. 0.]] distance: [[ 32. 452. 458.]]


KNN숫자인식

숫자 이미지 분류하여 저장하기

 

import cv2 
import numpy as np 

img = cv2.imread('digits.png') 
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 세로로 50줄, 가로로 100줄로 사진을 나눕니다.
cells = [np.hsplit(row, 100) for row in np.vsplit(gray, 50)] 
x = np.array(cells) 

# 각 (20 X 20) 크기의 사진을 한 줄(1 X 400)으로 바꿉니다.
train = x[:, :].reshape(-1, 400).astype(np.float32) 

# 0이 500개, 1이 500개, ... 로 총 5,000개가 들어가는 (1 x 5000) 배열을 만듭니다. 
k = np.arange(10)

train_labels = np.repeat(k, 500)[:, np.newaxis]
np.savez("trained.npz", train=train, train_labels=train_labels)

 

import matplotlib.pyplot as plt 

# 다음과 같이 하나씩 글자를 출력할 수 있습니다. 
plt.imshow(cv2.cvtColor(x[0, 0], cv2.COLOR_GRAY2RGB)) 
plt.show() 

# 다음과 같이 하나씩 글자를 저장할 수 있습니다.
cv2.imwrite('test_0.png', x[0, 0]) cv2.imwrite('test_1.png', x[5, 0])
cv2.imwrite('test_2.png', x[10, 0]) cv2.imwrite('test_3.png', x[15, 0])
cv2.imwrite('test_4.png', x[20, 0]) cv2.imwrite('test_5.png', x[25, 0]) 
cv2.imwrite('test_6.png', x[30, 0]) cv2.imwrite('test_7.png', x[35, 0]) 
cv2.imwrite('test_8.png', x[40, 0]) 
cv2.imwrite('test_9.png', x[45, 0])

Out[43]:

True

KNN 숫자 인식

 
import cv2
import numpy as np
import glob

FILE_NAME = 'trained.npz'

# 파일로부터 학습 데이터를 불러옵니다.
def load_train_data(file_name):
    with np.load(file_name) as data:
        train = data['train']
        train_labels = data['train_labels']
    return train, train_labels

# 손 글씨 이미지를 (20 x 20) 크기로 Scaling합니다.
def resize20(image):
    img = cv2.imread(image)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    gray_resize = cv2.resize(gray, (20, 20))
    plt.imshow(cv2.cvtColor(gray_resize, cv2.COLOR_GRAY2RGB))
    plt.show()

    # 최종적으로는 (1 x 400) 크기로 반환합니다.
    return gray_resize.reshape(-1, 400).astype(np.float32)

def check(test, train, train_labels):
    knn = cv2.ml.KNearest_create()
    knn.train(train, cv2.ml.ROW_SAMPLE, train_labels)
    # 가장 가까운 5개의 글자를 찾아, 어떤 숫자에 해당하는지 찾습니다.
    ret, result, neighbours, dist = knn.findNearest(test, k=5)
    return result

train, train_labels = load_train_data(FILE_NAME)

for file_name in glob.glob('./test_*.png'):
    test = resize20(file_name)
    result = check(test, train, train_labe

 

[[5.]]

[[3.]]

[[6.]]

[[8.]]

[[4.]]

[[2.]]

[[7.]]

[[0.]]

[[1.]]

[[9.]]

 

 

 

코드/소스참고: 나동빈