-opencv 파일 불러오기 및 webcam 사용 및 띄우기
# -*- coding: utf-8 -*-
import cv2
'''
cap = cv2.VideoCapture("Resources/test.video.mp4") # 파일 불러오는 방법
'''
cap = cv2.VideoCapture(0) # webcam 쓰는 방법
cap.set(3,640) #가로 640 으로 설정
cap.set(4,480) #세로 480 으로 설정
cap.set(10,100) #밝기 100 으로 설정
while True:
success, img = cap.read() # success 에서는 treu 나 false 가 들어가고 , img 에 image 전달
cv2.imshow("video", img)
if cv2.waitKey(1) & 0xFF ==ord('q'): # 1초 지나고 키보드 q 누르면 꺼짐
break
-Basic Function
Erode 연산 = 필터 내부의 가장 낮은(어두운) 값으로 변환(and) - 침식연산
Dilate 연산 = 필터 내부의 가장 높은(밝은) 값으로 변환(or) - 팽창연산
Erode - Dilate = Opening 연산 : 주로 작은 노이즈들을 제거하는데 사용한다.
Dilate - Erode = Closing 연산 : 보통 한 객체를 추출했을 때 두개 이상의 작은 부분으로 나올 경우 큰 객체로 합칠 때 사용한다.
# -*- coding: utf-8 -*-
import cv2
import numpy as np
img = cv2.imread("Resources/lena.png") #이미지 불러오기
imgGray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) # 이미지 gray 스케일로 바꾸기
# opencv 에선 BGR 순으로 컬러 설정
imgBlur = cv2.GaussianBlur(imgGray, (7,7),0) # blur 추가 (7,7) 은 커널 사이즈
imgCanny = cv2.Canny(img,150,200) # edge detection 하는 함수, threshold 값이 클수록 edge 적게 뽑음
kernel = np.ones((5,5), np.uint8) # 5x5 크기의 숫자 1인 행렬 타입은 uint8 이라서 0~255까지 사용가능
imgDialation = cv2.dilate(imgCanny,kernel,iterations=1) # dialation 팽창 연산 iteration 많을수록 더 굵게 변함
imgEroded = cv2.erode(imgDialation,kernel,iterations=1) # erode 침식 연산
cv2.imshow("GRAY IMAGE", imgGray)
cv2.imshow("GRAY IMAGE", imgBlur)
cv2.imshow("GRAY IMAGE", imgCanny)
cv2.imshow("GRAY IMAGE1", imgDialation)
cv2.imshow("GRAY IMAGE2", imgEroded)
cv2.waitKey(0) # imshow 사용할때는 뒤에 waitkey 항상 같이 따라와야함
150,2000 일때 dege detection 100,100 일때 edge detection
dialation iter = 5 일때
-Resize and Crop
import cv2
import numpy as np
img = cv2.imread("Resources/lambo.png")
print(img.shape) # (482,623,3) 이렇게 뜸 이걸로 이미지의 사이즈를 알 수 있음 (높이, 가로, color) 순서
imgResize = cv2.resize(img,(300,200)) # 이미지 사이즈가 줄어듬 가로 300, 높이 200 으로 줄어듬
print(imgResize.shape) # resize 를 사용해서 더 큰 이미지를 만들면 이미지가 stretch 된다
imgCropped = img[0:200,200:400] # image array 를 일부분만 자르기
cv2.imshow("Image",img)
cv2.imshow("Image Resize",imgResize)
cv2.imshow("image cropped", imgCropped)
cv2.waitKey(0)
-Opencv 를 통한 image 에 그림 및 글씨 사용
import cv2
import numpy as np
img = np.zeros((512,512,3),np.uint8) # 512x512 사이즈의 0 행렬
#print(img.shape)
#img[:] = 255,0,0 # [:] 이면 전체 행렬 모두 의미 하는것 255,0,0 이면 완전 파랑
cv2.line(img,(0,0),(img.shape[1],img.shape[0]),(0,255,0),3) # image, point1, point2, color, thickness
cv2.rectangle(img,(0,0),(250,350),(0,0,255),cv2.FILLED) # image, point1, point2, color, thickness(CV2.FILLED = 전체 채움)
cv2.circle(img,(400,50),30,(255,255,0),5) # image, center point, radius, color, thickness
cv2.putText(img, "OPENCV ",(300,100),cv2.FONT_HERSHEY_COMPLEX,1,(0,150,0),1) # image, text, starting point, font,font scale, color, thickness
cv2.imshow("Image",img)
cv2.waitKey(0)
-이미지 시점 변환
import cv2
import numpy as np
img = cv2.imread("Resources/cards.jpg")
width, height = 250,350
pts1 = np.float32([[111,219],[287,188],[154,482],[352,440]]) #원래 이미지의 4 코너 포인트
pts2 = np.float32([[0,0],[width,0],[0,height],[width,height]]) # 새롭게 이동시킬 4개의 코너 포인트
matrix = cv2.getPerspectiveTransform(pts1,pts2) # 원래 4개의점에서 새로운 4개의 점으로 이동시키는 matrix 생성하기
imgOutput = cv2.warpPerspective(img,matrix,(width,height)) # matrix 를 사용해서 안에 있는 점들을 새로운 이미지로 만들기
cv2.imshow("Image", img)
cv2.imshow("Image output",imgOutput)
cv2.waitKey(0)
original image 를 사용하여 시점 변환 시키기
-Image 합치기
import cv2
import numpy as np
img = cv2.imread("Resources/lena.png")
imghor = np.hstack((img,img)) # horizontal stack two image 이미지 사이즈가 같아야지 할수 있음
imgver = np.vstack((img,img)) # vertical stack two image
def stackImages(scale,imgArray): # 사이즈가 다른 이미지 & 흑백 컬러 이미지 & resize 할때 사용하는 함수
rows = len(imgArray)
cols = len(imgArray[0])
rowsAvailable = isinstance(imgArray[0], list)
width = imgArray[0][0].shape[1]
height = imgArray[0][0].shape[0]
if rowsAvailable:
for x in range ( 0, rows):
for y in range(0, cols):
if imgArray[x][y].shape[:2] == imgArray[0][0].shape [:2]:
imgArray[x][y] = cv2.resize(imgArray[x][y], (0, 0), None, scale, scale)
else:
imgArray[x][y] = cv2.resize(imgArray[x][y], (imgArray[0][0].shape[1], imgArray[0][0].shape[0]), None, scale, scale)
if len(imgArray[x][y].shape) == 2: imgArray[x][y]= cv2.cvtColor( imgArray[x][y], cv2.COLOR_GRAY2BGR)
imageBlank = np.zeros((height, width, 3), np.uint8)
hor = [imageBlank]*rows
hor_con = [imageBlank]*rows
for x in range(0, rows):
hor[x] = np.hstack(imgArray[x])
ver = np.vstack(hor)
else:
for x in range(0, rows):
if imgArray[x].shape[:2] == imgArray[0].shape[:2]:
imgArray[x] = cv2.resize(imgArray[x], (0, 0), None, scale, scale)
else:
imgArray[x] = cv2.resize(imgArray[x], (imgArray[0].shape[1], imgArray[0].shape[0]), None,scale, scale)
if len(imgArray[x].shape) == 2: imgArray[x] = cv2.cvtColor(imgArray[x], cv2.COLOR_GRAY2BGR)
hor= np.hstack(imgArray)
ver = hor
return ver
imgGray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
imgStack = stackImages(0.5,([img,imgGray,img],[img,img,img])) # 이미지 6개를 출력 0.5배로 resize 해서 출력
cv2.imshow("Horizontal", imghor)
cv2.imshow("vertical", imgver)
cv2.waitKey(0)
horizontal image stack
트랙바 & 마스크 만들기
import cv2
import numpy as np
def empty(a):
pass
path = "Resources/lambo.png"
cv2.namedWindow("TrackBars")
cv2.resizeWindow("TrackBars",640,240)
cv2.createTrackbar("HUE MIN","TrackBars",0,179,empty) #TrackBar 생성 이름, window 이름, 최소값, 최댓값, callback 함수
cv2.createTrackbar("HUE Max","TrackBars",179,179,empty)
cv2.createTrackbar("Sat MIN","TrackBars",0,255,empty)
cv2.createTrackbar("Sat Max","TrackBars",255,255,empty)
cv2.createTrackbar("Val MIN","TrackBars",0,255,empty)
cv2.createTrackbar("Val Max","TrackBars",255,255,empty)
while True:
img = cv2.imread(path)
imgHSV = cv2.cvtColor(img,cv2.COLOR_BGR2HSV) # hsv 로 변환
h_min = cv2.getTrackbarPos("HUE MIN","TrackBars") # trackbar 의 값을 받아옴 "트랙바 이름" , "window 이름"
h_max = cv2.getTrackbarPos("HUE MIN","TrackBars")
s_min = cv2.getTrackbarPos("Sat MIN","TrackBars")
s_max = cv2.getTrackbarPos("Sat MIN","TrackBars")
v_min = cv2.getTrackbarPos("Val MIN","TrackBars")
v_max = cv2.getTrackbarPos("Val MIN","TrackBars")
lower = np.array([h_min,s_min,v_min])
upper = np.array([h_max,s_max,v_max])
mask = cv2.inRange(imgHSV, lower, upper) # 이미지의 range 를 설정 이미지, 최솟값, 최댓값
imgResult = cv2.bitwise_and(img, img, mask=mask) # 두개의 이미지에서 두 이미지에서 두 픽셀 값이 참인것들만 뽑아서 한 이미지 만들기 and operation 임
cv2.imshow("original", img)
cv2.imshow("HSV",imgHSV)
cv2.waitKey(0)
트랙바를 사용해서 이미지의 이미지에 실시간으로 반영 (while 과같은 반복문에 있어야함)
-Contour and bounding box
import cv2
import numpy as np
def stackImages(scale,imgArray):
rows = len(imgArray)
cols = len(imgArray[0])
rowsAvailable = isinstance(imgArray[0], list)
width = imgArray[0][0].shape[1]
height = imgArray[0][0].shape[0]
if rowsAvailable:
for x in range ( 0, rows):
for y in range(0, cols):
if imgArray[x][y].shape[:2] == imgArray[0][0].shape [:2]:
imgArray[x][y] = cv2.resize(imgArray[x][y], (0, 0), None, scale, scale)
else:
imgArray[x][y] = cv2.resize(imgArray[x][y], (imgArray[0][0].shape[1], imgArray[0][0].shape[0]), None, scale, scale)
if len(imgArray[x][y].shape) == 2: imgArray[x][y]= cv2.cvtColor( imgArray[x][y], cv2.COLOR_GRAY2BGR)
imageBlank = np.zeros((height, width, 3), np.uint8)
hor = [imageBlank]*rows
hor_con = [imageBlank]*rows
for x in range(0, rows):
hor[x] = np.hstack(imgArray[x])
ver = np.vstack(hor)
else:
for x in range(0, rows):
if imgArray[x].shape[:2] == imgArray[0].shape[:2]:
imgArray[x] = cv2.resize(imgArray[x], (0, 0), None, scale, scale)
else:
imgArray[x] = cv2.resize(imgArray[x], (imgArray[0].shape[1], imgArray[0].shape[0]), None,scale, scale)
if len(imgArray[x].shape) == 2: imgArray[x] = cv2.cvtColor(imgArray[x], cv2.COLOR_GRAY2BGR)
hor= np.hstack(imgArray)
ver = hor
return ver
def getContours(img):
contours, Hierarchy = cv2.findContours(img,cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) # image, mode(cv2.RETR_EXTERNAL = outerconor 찾기 좋음)
for cnt in contours:
area = cv2.contourArea(cnt)
print(area)
if area > 500: # 단위는 픽셀 , 이렇게 threshold 값을 정하는 이유는 노이즈 제거하기 위해
cv2.drawContours(imgContour,cnt,-1,(255,0,0),3) # image, contour, contourindex, color, thickness
peri = cv2.arcLength(cnt,True) # getting contour parameter
approx= cv2.approxPolyDP(cnt,0.02*peri,True) # getting conor point
objCor = len(approx) # len 을 사용하여서 3 => 삼각형, 4=> 사각형 5 이상이면 원이라고 볼 수 있다.
x, y, w, h = cv2.boundingRect(approx) # x, y width height 를 알 수 있음
if objCor ==3 : objectType = "Tri" # 코너값들을 추출해서 코너갯수가 3 이면 삼각형
elif objCor==4: # 코너 갯수가 4 이면 사각형이다
aspRatio = w/float(h) # width 와 height 가 5% 미만으로 값이 같다면 정사각형 그렇지 않으면 사각형으로 분류한다
if aspRatio > 0.95 and aspRatio < 1.05: objecType = "Square"
else : objectType = "Rectangle"
elif objCor > 4 : objectType = "Circle" # 코너의 갯수가 4개 보다 많을경우 원으로 분류한다
else: objectType = "None"
cv2.rectangle(imgContour,(x,y),(x+w,y+h),(0,255,0),2) # contour 에서 box 를 치는 부분이다 시작점 + width, 시작점 + height 를 사용해서 박스를 친다
cv2.putText(imgContour, objectType,
(x+(w//2)-10,y+(h//2)-10),cv2.FONT_HERSHEY_COMPLEX,0.7,
(0,0,0),2) # 글씨로 위에 분류한 도형 글씨를 적는다
path = 'Resources/shapes.png'
img = cv2.imread(path)
imgContour = img.copy()
imgGray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
imgBlur =cv2.GaussianBlur(imgGray,(7,7),1)
imgCanny = cv2.Canny(imgBlur,50,50)
imgBlank = np.zeros_like(img)
getContours(imgCanny)
imgStack = stackImages(0.6,([img,imgGray,imgBlur],
[imgCanny,imgContour,imgBlank]))
cv2.imshow("Stack", imgStack)
cv2.waitKey(0)
-Face detection using pre-trained xml file
import cv2
import numpy as np
faceCascade = cv2.CascadeClassifier("Resources/haarcascade_frontalface_default.xml") # pretrained xml file using
img = cv2.imread("Resources/lena.png")
imgGray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
faces = faceCascade.detectMultiScale(imgGray,1.1,4) #image scaleFactor minNeighbors
for (x,y,w,h) in faces:
cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2) # putting bounding box
cv2.imshow("Result", img)
cv2.waitKey(0)
아래 영상을 참고하여 작성되었습니다.
- https://www.youtube.com/watch?v=WQeoO7MI0Bs