이미지나 영상을 분석하고 유의미한 정보를 생성하는 기술
물체 - Object
전경 - Foreground
배경 - Background
실시간 영상처리에 중점을 둔 영상처리 라이브러리
OpenCV 설치
1. opencv사이트에서 최신 버전 opencv 설치
pip install opencv-python
입력
주피터에 import cv2
입력하니 error가 없다. 제대로 설치가 되었다는 뜻
2. ㅇㅇㅇ
이미지 데이터에서 유의미한 데이터를 얻기 위해 가공 필요
전처리, 노이즈&디노이즈, 특징&유사성 검출
이미지 - 너비(width), 높이(height)
IDE
색상 표현 정밀도(비트) = 비트 깊이 = 색상 깊이 = 색상 심도
이진화 이미지 - 1bit 이미지
그레이 스케일 이미지 - 8bit 이미지
채널(색상 채널)
OpenCV(python) 채널 표현
(row, column, 채널 수)
color = np.zeros((height, width, 3), np.uint8)
gray = np.zeros((rows, cols, 1), np.uint8)
ROI(Region Of Interest)
OpenCV 에서는 N차원 배열을 사용
1920x1280 배율의 3채널 색상 이미지를 사용할 경우 처리해야 할 데이터 공간은
1920x1280x3임 너무크다!
그래서 ROI영역으로 Matching 필요한 부분만 잘라서 사용한다.
COI(Channel Of Interest)
관심 채널을 설정하여 데이터의 양 1/3으로 감축
Blue, Green, Red 셋중에 하나
그레이 스케일과 COI는 다르다.
그레이 스케일은 각 컬러 채널별 가중치를 다르게 주어서 계산
Gray = 0.299 x R + 0.578 x G + 0.114 x B
히스토그램
막대그래프로 나타내는 것
x축 : 픽셀 값(0~255)
y축 : 픽셀 개수
빈도수 : x축 간격...
리스트(List)의 특징 [값1, 값2,...값n]
파이썬은 배열이 없다.
생성
a = []
b = [1,2,3]
c = ['Life', 'is', 'too', 'short']
d = [1,2, 'Life', 'is']
e = [1,2,['Life', 'is']]
리스트 끼리 더하면 리스트가 이어진다.
리스트를 곱하면 곱한 수 만큼 나열한다.
인덱싱
인덱스 값으로 음수가 가능하다.
슬라이싱
값 수정
요소 삭제
요소 추출
위치 반환
요소 삽입
요소 추가
key | value |
---|---|
name | hello |
phone | 01000001111 |
birth | 1229 |
추가
a={1:'a'}
print(a)
a[2]='b'
print(a)
key중복
a={1:'a',1:'b'}
print(a)
key리스트
a = {'name' : 'hello', 'phone':'01000001111','birth':'1229'}
a_keys=a.keys()
print(a_keys)
list형태가 아니라 dict_keys라는 객체로 반환됨.
리스트 형태로 쓰고 싶다면 (list(a.keys())로 쓸것
print(a_keys[0] -> 에러for name in a.keys():
print(name)
a = {'name' : 'hello', 'phone':'01000001111','birth':'1229'}
a_keys=list(a.keys())
print(a_keys)
list(a.keys())에 커서를 올려놓고 shift+TAP
을 누루면 설명이 나온다.
아래와 같이 출력
for name in a.keys():
print(name)
value 리스트
key, value 쌍 얻기
a_items = a.items()
print(a_items)
print(a.get('name'))
# a['name']과 같은 동작
print(a.get('nope')) # -> None 반환
print(a.['nope'] # -> Error 발생
print(a.get('name','default_value'))
# 키가 없는 경우(name)이 없는경우, default값 반환
print('name' in a)
print('nope' in a)
Container
Mutable
Set - 중복 불가, 순서에 영향 받지 않음
*생성
s0 = set() # 비어있는 집합
s1 = set([1,2,3])
print(s1)
s1=set([1,2,3,1,2])
print(s1)
s1 = set([1,2,3])
l1 = list(s1)
print(l1[0])
s1 = set([1,2,3])
t1 = tuple(s1)
print(t1[0])
&
s1 = set([1,2,3,4,5,6])
s2 = set([4,5,6,7,8,9])
print(s1 & s2)
print(s1.intersection(s2))
|
print(s1 | s2)
print(s1.union(s2))
-
print(s1-s2)
print(s1.difference(s2))
s1 = set([1,2,3])
s1.add(4)
print(s1)
s1 = set([1,2,3])
s1.update([4,5,6])
print(s1)
s1 = set([1,2,3])
s1.remove(2)
print(s1)
영상처리에서는 이미지 데이터를 행렬로 표한함
파이썬에서는 행렬을 표현하는 기본 자료형이 없음
->Numpy 라이브러리 사용
import numpy as np
array = np.array([[1,2,3],[4,5,6]])
print(array.ndim) # 차원 개수
print(array.shape) # 차원의 크기(모양)
print(array.dtype) # 자료형
import numpy as np
array1 = np.array([[1,2,3],[4,5,6]])
array2 = np.array([1,2,3],dtype = complex, ndmin=3)
# complex 복소수 형 ndim>????
array3 = np.array(array1, copy=False)
# array3은 array1의 메모리 주소값을 참조하고 있다.
# copy=true는 defalut이며, 최초 값을 가지고 있는다.
array1[0] = [4,5,6]
print(array1)
print(array2)
print(array3)
import numpy as np
a= np.arange(6)
print(a)
import numpy as np
a= np.arange(2,6)
print(a)
import numpy as np
a= np.arange(2,6,2) #2에서 시작 6에서 끝 스텝은 2씩 증가
print(a)
import numpy as np
a= np.arange(2,6.5,0.5)
print(a)
a = np.zeros([3,3])
print(a)
a = np.ones([3,3])
print(a)
a = np.full([3,3],2.5)
print(a)
array1 = np.array([1,2,3])
array2 = np.array([[1,2],[3,4]])
array3 = np.array([[[1,2,],[3,4],[5,6],[7,8]]])
print(array1[-1]
print(array2[0][1])
print(array3[0][1][1])
import numpy as np
array = np.array([[[1,2],[3,4],[5,6],[7,8]]])
for i in array [0]:
for j in i:
if j % 2 == 0:
print(j)
import numpy as np
array = np.array([[1,2,3,4,5,],[6,7,8,9,10],[11,12,13,14,15],[16,17,18,19,20]])
print(array[1:3])
print(array[::2])
print(array[2:, 1::2])
내용 출처 사이트
Wonkyung's blog Python array[::] 용법
간단한 파이썬 팁입니다.
arr[::], arr[1:2:3], arr[::-1] 등으로 배열의 index에 접근하는 방법을 Extended Slices 라고 부릅니다.
설명
arr[A:B:C]의 의미는, index A 부터 index B 까지 C의 간격으로 배열을 만들어라는 말입니다.
만약 A가 None 이라면, 처음부터 라는 뜻이고
B가 None 이라면, 할 수 있는 데까지 (C가 양수라면 마지막 index까지, C가 음수라면 첫 index까지가 되겠습니다.)라는 뜻입니다.
마지막으로 C가 None 이라면 한 칸 간격으로 라는 뜻입니다.
>> arr = range(10)
>> arr
[0,1,2,3,4,5,6,7,8,9]
>> arr[::2] # 처음부터 끝까지 두 칸 간격으로
[0,2,4,6,8]
>> arr[1::2] # index 1 부터 끝까지 두 칸 간격으로
[1,3,5,7,9]
>> arr[::-1] # 처음부터 끝까지 -1칸 간격으로 ( == 역순으로)
[9,8,7,6,5,4,3,2,1,0] >> arr[::-2] # 처음부터 끝까지 -2칸 간격으로 ( == 역순, 두 칸 간격으로)
[9,7,5,3,1] >> arr[3::-1] # index 3 부터 끝까지 -1칸 간격으로 ( == 역순으로)
[3,2,1,0]
>> arr[1:6:2] # index 1 부터 index 6 까지 두 칸 간격으로
[1,3,5]
참고 사이트
잡다한 지식/CS 베이스의 blog
A=[a11a12a13 a21a22a23 a31a32a33] 일 경우,
행 우선
[a11 a12 a13 a21 a22 a23 a31 a32 a33]
열 우선
[a11 a21 a31 a12 a22 a32 a13 a23 a33]
import numpy as np
array = np.arange(12)
reshape1 = array.reshape(2,3,2)
#(a,b,c) a-3차원 개수
# b-2차원 개수
# c-1차원 개수
reshape2 = np.reshape(array, (2,-1), order='F')
# -1을 하면 요소 개수에 맞게 알아서 넣준다.
# reshape함수가 알아서 해라! 라는 뜻
print(reshape1)
print(reshape2)
order='F'는
google에 검색 포트란 구조
열우선??
행우선??
np.newaxis :
-> 기존 차원 앞에
차원 추가: np.newaxis
-> 기존 차원 뒤에
차원 추가import numpy as np
array = np.arange(4)
# [0,1,2,3]
axis1 = array[np.newaxis]
# == array[np.newaxis: ]
axis2 = array[:, np.newaxis]
print(axis1)
# (1,4) [[0,1,2,3]]
print(axis2)
# (4,1) [[0],[1],[2],[3]]
axis1.shape
# (1,4)
import numpy as np
array = np.arange(12).reshape(3,-1)
print(array)
flat1 = array.flatten(order='F')
flat2 = array.ravel()
print(flat1)
print(flat2)
import numpy as np
array1 = np.arange(6).reshape(2,3)
array2 = np.arange(6,12).reshape(2,3)
merge1 = np.stack([array1, array2], axis=0)
merge2 = np.stack([array1, array2], axis-1)
print(merge1)
print(merge2)
import numpy as np
a = np.arange(10).reshape(2,5)
b = np.arange(6).reshape(2,3)
print(a)
print(b)
c = np.hstack((a,b))
print(c)
# or c = np.hstack([a,b])
print(c)
import numpy as np
a = np.arange(10).reshape(2,5)
b = np.arange(15).reshape(3,5)
print(a)
print(b)
c = np.vstack((a,b))
print(c)
# or c = np.vstack([a,b])
print(c)
import cv2
import numpy as np
image = cv2.imread("mountain.jpg")
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
result = np.zeros((image.shape[0], 256), dtype = np.uint8)
hist = cv2.calcHist([image], [0], None, [256], [0, 256])
# 원본image의 0으로 감쌌다?
# [0]은 분석 채널(x축의 대상) 이미지가 graysacale이면 [0], color면[0],[0,1](형태1:blue, 2:green, 3:red)
# None은 mask(분석 영역)
# 256은 hist size이다. 0~255
# [0,256] 중 0은
cv.2normalize(hist, hist, 0, 255, cv2.NORM_MINMAX)
# 원본 변수
# output 변수
# 0,255 압축 사이즈?
for x, y in enumerate(hist):
cv2.line(result, (int(x), image.shape[0]), (int(x), image.shape[0] - int(y)), 255)
#
dst = np.hstack([image[:,:,0], result])
cv2.imshow("dst",dst)
cv2.waitKey(0)
cv2.destroyAllWindows()
import numpy as np
array = np.arange(10).reshape(2,5)
detach1 = np.split(array, 2, axis=0)
detach2 = np.split(array, [2,3], axis=1)
print(detach1)
print(detach2)
import numpy as np
array1 = np.array([1,2,3,4]).reshape(2,2)
array2 = np.array([1.5,2.5])
add = array1 + array2
print(add)
import numpy as np
array = np.zeros((1280, 1920, 3), np.uint8)
x, y, w, h = 100, 100, 300, 300
roi = array[a:x+w, y:y+h]
print(array.shape)
print(roi.shape)
import cv2
src = cv2.imread("OpenCV_Logo.png", cv2.IMREAD_GRAYSCALE)
print(src.ndim, src.shape, src.dtype)
import cv2
src = cv2.imread("OpenCV_Logo.png", cv2.IMREAD_GRAYSCALE)
cv2.namedWindow("src", flags=cv2.WINDOW_FREERATIO)
cv2.resizeWindow("src", 400, 200)
cv2.imshow("src", src)
cv2.waitKey(0)
sv2.destroyWindow("src")
아래와 같이 출력하고 이미지 종료시 누른 버튼은 ASC코드로 출력된다. 여기서는 'q'
를 입력했다.
import cv2
capture = cv2.VideoCapture("Star.mp4")
while True:
ret, frame = capture.read()
if(capture.get(cv2.CAP_PROP_POS_FRAMES) == capture.get(cv2.CAP_PROP_FRAME_COUNT)):
capture.open("Star.mp4")
# CAP_PROP_POS_FRAMES - > 다음 프레임 값
# CAP_PROP_FRAME_COUNT -> 입력 영상의 프레임 수
cv2.imshow("VideoFrame", frame)
if cv2.waitKey(33) == ord('q'): break
# 33 ms를 기다린다. ord는 뒤의 'q'에 해당하는 ASC값을 가져온다.
capture.release()
cv2.destroyAllWindows()
import cv2
capture = cv2.VideoCapture("Star.mp4")
while True:
ret, frame = capture.read()
if ret == False:
break
cv2.imshow("VideoFrame", frame)
if cv2.waitKey(33) == ord('q'): break
capture.release()
cv2.destroyAllWindows()
이렇게 하면 동영상이 전체 이미지를 show하고나서 종료된다. 즉, 1회 출력
import cv2
capture = cv2.VideoCapture(0)
capture.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
capture.set(cv2.CAP_PROP_FRAME_HEIGHT, 640)
while True:
ret, frame = capture.read()
if ret == True:
cv2.imshow("VideosFrame", frame)
if cv2.waitKey(33) == ord('q'): break
else :
break
capture.release()
cv2.destroyAllWindows()
작업중인 노트북 카메라가 출력한다!
import cv2
import numpy as np
one = cv2.imread("one.jpg")
two = cv2.imread("two.jpg")
three = cv2.imread("three.jpg")
four = cv2.imread("four.jpg")
horizontal1 = np.full((50, one.shape[1],3), [0,0,0], dtype = np.uint8)
# 높이 50, one이미지의 x길이 만큼의 이미지를 0으로 채우겠다. [0,0,0]은 RGB값임
horizontal2 = np.full((50, two.shape[1],3), (0,0,0), dtype = np.uint8)
left = cv2.vconcat((one, horizontal1, three))
right = np.vstack((two, horizontal2, four))
vertical = np.full((left.shape[0], 50, 3), 0, dtype = np.uint8)
dst = cv2.hconcat((left, vertical, right))
cv2.imshow("dst", dst)
cv2.waitKey()
cv2.destroyAllWindow()
import numpy as np
import cv2
img = np.zeros((768, 1366, 3), dtype = np.uint8)
cv2.line(img, (100, 100), (1200, 100), (0, 0, 255), 3, cv2.LINE_AA)
cv2.circle(img, (300, 300), 50, (0, 255, 0), cv2.FILLED, cv2.LINE_4)
cv2.rectangle(img, (500, 200), (1000, 400), (255, 0, 0), 5, cv2.LINE_8)
cv2.ellipse(img, (1200, 300), (100, 50), 0, 90, 180, (255, 255, 0), 2)
pts1 = np.array([[[100, 500], [300, 500], [200, 600]], [[400, 500], [500, 500], [600, 700]]])
pts2 = np.array([[700, 500], [800, 500], [700, 600]])
cv2.polylines(img, pts1, True, (0, 255, 255), 10)
cv2.fillPoly(img, [pts2], (255, 0, 255), cv2.LINE_AA)
cv2.putText(img, "OpenCV", (900, 600), cv2.FONT_HERSHEY_COMPLEX | cv2.FONT_ITALIC, 2, (255, 255, 255), 3)
cv2.imshow("img", img)
cv2.waitKey(0)
cv2.destroyAllWindows()
import cv2
import numpy as np
def onChangeBlue(pos):
global b # b 전역 변수
b = pos # pos 지역 변수
cv2.imshow("Palette", createImage(b, g, r))
def createImage(b, g, r):
return np.full((500, 500, 3), (b, g, r), dtype=np.uint8)
# 500 x 500 x 3사이즈 이미지에 b,g,r 순서로 full하겠다.
b, g, r = 0, 0, 0
cv2.namedWindow("Palette")
cv2.createTrackbar("Blue", "Palette", 100, 255, onChangeBlue)
# 콜백함수 onChangeBlue 트랙바 값이 변할때마다 on...ue함수에 입력
cv2.createTrackbar("Green", "Palette", 0, 255, lambda x:x)
# lambda 식.. 아무것도 안하겠다라는 뜻의 익명 함수
cv2.createTrackbar("Red", "Palette", 0, 255, lambda x:x)
while True:
g = cv2.getTrackbarPos("Green", "Palette")
# Palette의 Green에서 값을 받아오겠다. 받아서 g에 넣는다.(트랙바의 위치값)
r = cv2.getTrackbarPos("Red", "Palette")
cv2.imshow("Palette", createImage(b, g, r))
# 팔레트에 그린다.
if cv2.waitKey(33) & 0xFF == ord('q'):
break
cv2.destroyAllWindows()
트랙바를 생성하고 부착하기 위해서는 먼저 윈도우가 정의되어야 한다.
cv2.NamedWindow()
함수를 사용해 Window 이름을 갖는 윈도우를 생성한다.
blue
만 onchangeBlue 함수를 사용하고 있는데 blue
도 while
문에 넣어도 사용 가능하다.
import numpy as np
import cv2
img = np.zeros((480, 640, 3), dtype = np.uint8)
save = cv2.imwrite("CV.jpeg", img, (cv2.IMWRITE_JPEG_QUALITY, 100, cv2.IMWRITE_JPEG_PROGRESSIVE, 1))
print(save)
p174
import cv2
src = cv2.imread("crow.jpg")
dst = cv2.cvtColor(src, cv2.COLOR_BGR2HSV)
cv2.imshow("dst", dst)
cv2.imshow("src", src)
cv2.waitKey(0)
cv2.destroyAllWindows()
Hue, Saturation, Value
mv = cv2.split(src)
# mv배열에 src 분리하여 채널별 정보저장
c0, c1, c2 = cv2.split(src)
# c0, c1, c2 각 변수에 단일 채널 정보 저장
import cv2
src = cv2.imread('tomato.jpg')
mv = cv2.split(src)
cv2.imshow('ch0', mv[0])
cv2.imshow('ch1', mv[1])
cv2.imshow('ch2', mv[2])
cv2.waitKey(0)
cv2.destroyAllWindows()
import cv2
src = cv2.imread("tomato.jpg")
hsv = cv2.cvtColor(src, cv2.COLOR_BGR2HSV)
h, s, v = cv2.split(hsv)
h_red = cv2.inRange(h, 0, 5)
dst = cv2.bitwise_and(hsv, hsv, mask = h_red)
# mask에 값이 있는 것들만 연산한다.
dst = cv2.cvtColor(dst, cv2.COLOR_HSV2BGR)
# HSV -> BGR 변환
cv2.imshow("dst", dst)
cv2.waitKey(0)
cv2.destroyAllWindows()
조금더 잘 구분해 보자
import cv2
src = cv2.imread("tomato.jpg")
hsv = cv2.cvtColor(src, cv2.COLOR_BGR2HSV)
# h, s, v = cv2.split(hsv)
# h_red = cv2.inRange(h, 0, 5)
lower_red = cv2.inRange(hsv, (0,100,100),(5,255,255))
upper_red = cv2.inRange(hsv, (170,100,100),(179,255,255))
complete_red = cv2.addWeighted(lower_red, 1.0, upper_red, 1.0, 0.0)
dst = cv2.bitwise_and(hsv, hsv, mask = complete_red)
dst = cv2.cvtColor(dst, cv2.COLOR_HSV2BGR)
cv2.imshow("dst", dst)
cv2.waitKey(0)
cv2.destroyAllWindows()
다른 색상을 추출하고 싶다면?
P201 표5.3 HSV 색상 파라미터 참조
import cv2
src = cv2.imread("swan.jpg")
src = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
# 바로위 코드에 유무에 따라 gray적용이 다르다.
_, binary = cv2.threshold(src, 127, 255, cv2.THRESH_BINARY)
# 필요없는 변수들은 _를 사용해서 버릴 수 있다.
# 127은 기준값
# 기법은 cv2.THRESH_BINARY
cv2.imshow("origin", src)
cv2.imshow("binary", binary)
cv2.waitKey(0)
cv2.destroyAllWindows()
원본 코드
GRAYSCALE적용시
src = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
BINARY -> OTSU
import cv2
src = cv2.imread("swan.jpg")
gray = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
binary = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 33, -5)
# 33은 BLOCK SIZE 3X3 이고 주위에 몇개를 볼것이냐 요런 것
cv2.imshow("binary", binary)
cv2.waitKey(0)
cv2.destroyAllWindows()
ADAPTIVE_THRESH_MEAN(적응형)
otsu
hue 값을 트랙바 사용하여 전체 컬러 추출하도록