본문 바로가기

카테고리 없음

opencv PYTHON

-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 항상 같이 따라와야함

  Blur 7,7 흐릿하게 나옴

 

 

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)

 

 

original image
cropped image

 

-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)

 

geometry on image

 

 

-이미지 시점 변환

 

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)

 

HSV 이미지 만들기

 

트랙바를 사용해서 이미지의 이미지에 실시간으로 반영 (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)

image contour
bounding box
Box naming

 

-Face detection using pre-trained xml file

 

Face Detection method

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)

Face detection using pre-trained xml file

 

 

 

아래 영상을 참고하여 작성되었습니다.

- https://www.youtube.com/watch?v=WQeoO7MI0Bs