728x90

 

 

### 차분영상 

#첫번째 영상 - frame들

import sys
import numpy as np
import cv2


# 비디오 파일 열기
cap = cv2.VideoCapture('PETS2000.avi')

if not cap.isOpened():
    print('Video open failed!')
    sys.exit()

#첫번째 프레임을 배경영상으로 등록
#컬러로 구해도 되지만 현재는 굳이 컬러로 할 필요가 없고, 연산 속도를 올리기 위해서 gray로 변환
_,back = cap.read()
back = cv2.cvtColor(back, cv2.COLOR_BGR2GRAY)

#노이즈 제거위한 가우시안
#ksize= (0,0), 시그마 1 
back =cv2.GaussianBlur(back, (0,0), 1)

while True:
    ret, frame = cap.read() 

    if not ret:
        break
    frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    #블러처리
    frame =cv2.GaussianBlur(frame, (0,0), 1)
    
    #단순히 뺄셈이 아닌, 뺄셈 후 절대값을 넣어준다
    diff=cv2.absdiff(back, frame)

    #차이값이 30이상이면 255로 만들고 그게 아니면 0으로 만들기
    _,diff=cv2.threshold(diff,30,255, cv2.THRESH_BINARY)

    cv2.imshow('frame',frame)
    cv2.imshow('diff',diff)
    if cv2.waitKey(30)==27:
        break

    '''
    #블러를 하기 전 영상결과#
    결과 영상에서는 같은 물체지만 선에따라 하얀 점들이 반짝인다. 
    빛의 반사라든지 여러 요인으로 인해 튀는 값들이다. (노이즈)
    모폴로지 열기 연산 적용가능하지만 이번실습에서는 가우시안 블러를 이용한다
    '''
    '''
    흰색객체를 레이블링을 통해서 객체의 위치와 크기를 판단 한 후, 해당 위치에 바운딩 박스 그리면
    침입자 프로그램 만들수있다
    '''
cap.release()
cv2.destroyAllWindows()

 

## 차분영상2

import sys
import numpy as np
import cv2


# 비디오 파일 열기
cap = cv2.VideoCapture('PETS2000.avi')

if not cap.isOpened():
    print('Video open failed!')
    sys.exit()

# 배경 영상 등록
ret, back = cap.read()

if not ret:
    print('Background image registration failed!')
    sys.exit()

back = cv2.cvtColor(back, cv2.COLOR_BGR2GRAY)
back = cv2.GaussianBlur(back, (0, 0), 1.0)

# 비디오 매 프레임 처리
while True:
    ret, frame = cap.read()

    if not ret:
        break

    #그레이 변환 
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    
    #블러처리
    gray = cv2.GaussianBlur(gray, (0, 0), 1.0)

    # 차영상 구하기 & 이진화
    diff = cv2.absdiff(gray, back)

    #임계값 적용 후 레이블링
    _, diff = cv2.threshold(diff, 30, 255, cv2.THRESH_BINARY)

    # 레이블링을 이용하여 바운딩 박스 표시
    cnt, _, stats, _ = cv2.connectedComponentsWithStats(diff)

    for i in range(1, cnt):
        #s : 객체 픽셀 사이즈
        x, y, w, h, s = stats[i]

        if s < 100:
            continue

        #본래 영상 frame에다가 박스 그리기
        cv2.rectangle(frame, (x, y, w, h), (0, 0, 255), 2)

    cv2.imshow('frame', frame)
    cv2.imshow('diff', diff)

    if cv2.waitKey(30) == 27:
        break

cap.release()
cv2.destroyAllWindows()

 

### 이동평균 배경차분영상

import sys
import numpy as np
import cv2


# 비디오 파일 열기
cap = cv2.VideoCapture('PETS2000.avi')

if not cap.isOpened():
    print('Video open failed!')
    sys.exit()

# 첫번째 프레임을 배경 영상 등록
ret, back = cap.read()

if not ret:
    print('Background image registration failed!')
    sys.exit()

# back: uint8 배경, fback: float32 배경
back = cv2.cvtColor(back, cv2.COLOR_BGR2GRAY)

#노이즈 제거 위한 블러처리
back = cv2.GaussianBlur(back, (0, 0), 1.0)
print('back',back)
#업데이트는 미세한 값을 다루기 때문에 float 타입으로 변환 후 진행한다
fback = back.astype(np.float32)

# 비디오 매 프레임 처리
while True:
    ret, frame = cap.read()

    if not ret:
        break

    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    gray = cv2.GaussianBlur(gray, (0, 0), 1.0)

    # fback: float32, back: uint8 배경
    #fback(dst): dst가 입력에도 있고 출력에도 있을경우엔 dst를 인자로 줘야한다. 출력으로 받으면 안된다
    # 알파값:0.01(gray적용), 0.99(fback적용)
    cv2.accumulateWeighted(gray, fback, 0.01)

    #absdiff는 두개의 입력영상 타입이 같아야 한다
    back = fback.astype(np.uint8)
    diff = cv2.absdiff(gray, back)
    _, diff = cv2.threshold(diff, 30, 255, cv2.THRESH_BINARY)

    # 레이블링을 이용하여 바운딩 박스 표시
    cnt, _, stats, _ = cv2.connectedComponentsWithStats(diff)

    for i in range(1, cnt):
        x, y, w, h, s = stats[i]

        if s < 100:
            continue

        cv2.rectangle(frame, (x, y, w, h), (0, 0, 255), 2)

    cv2.imshow('frame', frame)
    cv2.imshow('diff', diff)
    cv2.imshow('back', back)

    if cv2.waitKey(30) == 27:
        break

cap.release()
cv2.destroyAllWindows()

 

### MOG 추적

import sys
import numpy as np
import cv2


# 비디오 파일 열기
cap = cv2.VideoCapture('PETS2000.avi')

if not cap.isOpened():
    print('Video open failed!')
    sys.exit()

# 배경 차분 알고리즘 객체 생성

# history 기본값500: 과거 몇개의 프레임을 사용할건지 정함(기본값 500프레임)
# detectshadow: True(그림자 검출가능)
# bs = cv2.createBackgroundSubtractorMOG2() #MOG2 원리 이해x

bs = cv2.createBackgroundSubtractorKNN()

#그림자를 나타낸 회색이 없어지고 255로 처리됨
# bs.setDetectShadows(False) 

# 비디오 매 프레임 처리
while True:
    ret, frame = cap.read()

    if not ret:
        break

    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    #apply 이용해서 현재프레임을 입력(다음 비디오 프레임)으로 넣어서 계속 업데이트
    #fgmask: 0또는 255, 그림자까지 포함한다면 0,128,255 세개의 값으로 구성된 마스크 
    fgmask = bs.apply(gray)
    back = bs.getBackgroundImage() #현재 배경영상이 어떻게 업데이트가 되는지 볼수 있는 함수

    # 레이블링을 이용하여 바운딩 박스 표시
    cnt, _, stats, _ = cv2.connectedComponentsWithStats(fgmask)

    for i in range(1, cnt):
        x, y, w, h, s = stats[i]

        if s < 80: #사각형 안 픽셀 수가 80보다 작으면 무시
            continue

        cv2.rectangle(frame, (x, y, w, h), (0, 0, 255), 2)

    cv2.imshow('frame', frame)
    cv2.imshow('back', back)
    cv2.imshow('fgmask', fgmask)

    if cv2.waitKey(20) == 27:
        break

cap.release()
cv2.destroyAllWindows()

 

## 이동평균 추적

import sys
import numpy as np
import cv2


# 비디오 파일 열기
cap = cv2.VideoCapture('camshift.avi')

if not cap.isOpened():
    print('Video open failed!')
    sys.exit()

# 초기 사각형 영역: (x, y, w, h)
x, y, w, h = 135, 220, 100, 100 #귤 좌표 설정(ROI selector)
rc = (x, y, w, h)

ret, frame = cap.read()

if not ret:
    print('frame read failed!')
    sys.exit()

roi = frame[y:y+h, x:x+w]
roi_hsv = cv2.cvtColor(roi, cv2.COLOR_BGR2HSV)

# HS 히스토그램 계산
channels = [0, 1] #hue(색상), saturation(채도)
ranges = [0, 180, 0, 256] #hue:0~180, sat: 0~256 (255+1 1더해서 설정해야한다)
#귤이 위치한 좌표 위치에 대해서 히스토그램을 계산
#위 색상,채도 범위를 가졌을때의 히스토그램을 계산
#2차원 히스토그램: 축이 2개이고, 각 축이 만나는 지점의 개수를 표현
hist = cv2.calcHist([roi_hsv], channels, None, [90, 128], ranges)

# Mean Shift 알고리즘 종료 기준
#iteration:10 
#정확도가 1 이하(이동크기가 1픽셀보다 작으면) 종료
term_crit = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 1)

# 비디오 매 프레임 처리
while True:
    ret, frame = cap.read()

    if not ret:
        break

    # HS 히스토그램에 대한 역투영
    frame_hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)

    #hist를 인자로 입력, 히스토그램 역투영 확률 영상을 반환
    #히스토그램 역투영:관심 영역의 히스토그램과 유사한 히스토그램을 갖는 영역을 찾아내는 기법
    #hist와 같은 컬러를 frame_hsv에서 찾아낸다
    backproj = cv2.calcBackProject([frame_hsv], channels, hist, ranges, 1)

    # Mean Shift
    # 본래는 입력이자 출력은 인자에만 입력해야하지만
    # rc가 튜플이라서 출력 표시를 해야 업데이트가 된다
    _, rc = cv2.meanShift(backproj, rc, term_crit)

    # 추적 결과 화면 출력
    cv2.rectangle(frame, rc, (0, 0, 255), 2)
    cv2.imshow('frame', frame)

    if cv2.waitKey(60) == 27:
        break

cap.release()
cv2.destroyAllWindows()

 

### camshift 추적

#색상 정보 트래킹
import sys
import numpy as np
import cv2


# 비디오 파일 열기
cap = cv2.VideoCapture('camshift.avi')

if not cap.isOpened():
    print('Video open failed!')
    sys.exit()

# 초기 사각형 영역: (x, y, w, h)
x, y, w, h = 135, 220, 100, 100
rc = (x, y, w, h)

ret, frame = cap.read()

if not ret:
    print('frame read failed!')
    sys.exit()

roi = frame[y:y+h, x:x+w]
roi_hsv = cv2.cvtColor(roi, cv2.COLOR_BGR2HSV) #원색을 추적할때는 HSV가 유리하다 왜?

# HS 히스토그램 계산
channels = [0, 1]
ranges = [0, 180, 0, 256]
hist = cv2.calcHist([roi_hsv], channels, None, [90, 128], ranges)

# CamShift 알고리즘 종료 기준
term_crit = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 1)

# 비디오 매 프레임 처리
while True:
    ret, frame = cap.read()

    if not ret:
        break

    # HS 히스토그램에 대한 역투영
    frame_hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
    backproj = cv2.calcBackProject([frame_hsv], channels, hist, ranges, 1)

    # CamShift
    # return 값은 retval, window 인데  retval은 교재에 나와있는 것처럼 복잡한 튜플 형식이며
    # 이값을 이용해서 사각형을 회전된 사각형으로 바꿀수 있다
    # probImage=>backproj 확률에 대한 영상 즉, 점들의 분포가 어떻게 되어가고 있는지를 명시해야하는데
    # 여기서는 히스토그램의 역투영을 이용함, 혹은 데이터 분포를 표현 할수 있는 다른 방법을 적용시킬수 있다.(ndarray형태로)
    ret, rc = cv2.CamShift(backproj, rc, term_crit)

    # 추적 결과 화면 출력
    cv2.rectangle(frame, rc, (0, 0, 255), 2)
    #타원그리는 함수
    cv2.ellipse(frame, ret, (0, 255, 0), 2) #회전된 사각형에 내접하는 타원을 그려준다
    cv2.imshow('frame', frame)

    if cv2.waitKey(60) == 27:
        break

cap.release()
cv2.destroyAllWindows()

 

### Optical Flow

import sys
import numpy as np
import cv2

#optical Flow 
'''
x방향으로의 이동속도
y방향으로의 이동속도
한 좌표가 다른 좌표로 이동했을때 overflow 미지수 두개 발생
어떤 N*N Window를 설정하면 객체가 이동하는 속도는 같으므로 N**2개 방정식이 생긴다
'''

src1 = cv2.imread('frame1.jpg')
src2 = cv2.imread('frame2.jpg')

if src1 is None or src2 is None:
    print('Image load failed!')
    sys.exit()

#컬러변환->goodFeaturesToTrack는 gray만 입력으로 받는다
gray1 = cv2.cvtColor(src1, cv2.COLOR_BGR2GRAY)

#코너점을 찾는 goodFeaturesToTrack함수
pt1 = cv2.goodFeaturesToTrack(gray1, 50, 0.01, 10)

#src1, src2 에서 움직임 정보를 찾아내서 pt1 코너점 좌표가 어디로 이동했는지 pt2에 정보가 담겨져 있다
#pt2(이동된 점의 좌표)는 None으로 입력하고 출력으로 받는다
pt2, status, err = cv2.calcOpticalFlowPyrLK(src1, src2, pt1, None)

dst = cv2.addWeighted(src1, 0.5, src2, 0.5, 0)

for i in range(pt2.shape[0]):
    #잘못된것은 표현 무시하고, 잘된 것만 표시하도록 해준다
    if status[i, 0] == 0: #status가 0인것은 무시, 움직이지 않고 제자리 인 좌표?
        continue
    print(pt1[i,0]) #x,y 코너점의 좌표
    cv2.circle(dst, tuple(pt1[i, 0]), 4, (0, 255, 255), 2, cv2.LINE_AA) #이동 전 좌표
    cv2.circle(dst, tuple(pt2[i, 0]), 4, (0, 0, 255), 2, cv2.LINE_AA) #이동 후 좌표
    cv2.arrowedLine(dst, tuple(pt1[i, 0]), tuple(pt2[i, 0]), (0, 255, 0), 2)

cv2.imshow('dst', dst)
cv2.waitKey()
cv2.destroyAllWindows()

 

728x90

'실습 note' 카테고리의 다른 글

OpenCV_11(딥러닝)  (0) 2021.03.04
OpenCV_10(머신러닝)  (0) 2021.03.03
OpenCV_8(특징점 검출&매칭)  (0) 2021.02.26
OpenCV_7(영상분할&객체검출)  (0) 2021.02.25
OpenCV_6(이진 영상 처리)  (0) 2021.02.24

+ Recent posts