728x90

 

 

평균값 필터_1

### 평균값 필터

import sys
import numpy as np
import cv2


src = cv2.imread('rose.bmp', cv2.IMREAD_GRAYSCALE)

if src is None:
    print('Image load failed!')
    sys.exit()

''' 방법1
#ndarray
#1/9 float이므로 자동으로 dtype이 float64
#경우따라 비트를 32,64 선택해도 된다
kernel= np.array([[1/9,1/9,1/9],
                 [1/9,1/9,1/9],
                 [1/9,1/9,1/9]], dtype=np.float32)
'''

#필터링함수
#-1:입력영상과 동일한 데이터 타입이 만들어진다. 현재입력영상은 그레이스케일
# dst=cv2.filter2D(src, -1,kernel)

'''
#방법2
kernel=np.ones((3,3), dtype=np.float64)/9.
'''
#방법3
dst=cv2.blur(src,(3,3))

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

cv2.destroyAllWindows()

 

평균값 필터_2

### 평균값 필터2

import sys
import numpy as np
import cv2

src = cv2.imread('rose.bmp', cv2.IMREAD_GRAYSCALE)

if src is None:
    print('Image load failed!')
    sys.exit()

cv2.imshow('src', src)

for ksize in (3, 5, 7): #3x3, 5x5, 7x7
    dst = cv2.blur(src, (ksize, ksize))

    desc = 'Mean: {}x{}'.format(ksize, ksize)
    cv2.putText(dst, desc, (10, 30), cv2.FONT_HERSHEY_SIMPLEX,
                1.0, 255, 1, cv2.LINE_AA)

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

cv2.destroyAllWindows()

 

가우시안 필터_1

### 가우시안 필터

import sys
import numpy as np
import cv2


src = cv2.imread('rose.bmp', cv2.IMREAD_GRAYSCALE)

#커널크기는 (0,0)을 사용함으로써 sigma값을 계산하여 자동으로 크기를 결정한다
#사용자가 강제로 커널크기를 결정하면 가우시안의 분포 모양 가중치를 사용 못하기 때문에 지양한다
#sigmaX=1
#1.커널크기는 8*sigma+1(0.0좌표를 추가로 더한다), 9*9 커널크기 : 주로 float 타입 영상에 사용
#2.커널크기는 6*sigma+1(0.0좌표를 추가로 더한다), 7*7 커널크기 : 주로 uint8 타입 영상에 사용
#블러를 강하게,더 흐릿하게 할땐 시그마 값을 올린다
dst= cv2.GaussianBlur(src, (0,0),1) #7*7커널크기, sigmax=3, 6*3+1=19*19커널
dst2 = cv2.blur(src, (7, 7))

cv2.imshow('src', src)
cv2.imshow('dst', dst)
cv2.imshow('dst2', dst2)
cv2.waitKey()

cv2.destroyAllWindows()

 

가우시안 필터_2

### 가우시안필터 크기에 따른 영상변화

import sys
import numpy as np
import cv2


src = cv2.imread('rose.bmp', cv2.IMREAD_GRAYSCALE)

if src is None:
    print('Image load failed!')
    sys.exit()

cv2.imshow('src', src)

for sigma in range(1, 6):
    # sigma 값을 이용하여 가우시안 필터링
    dst = cv2.GaussianBlur(src, (0, 0), sigma)

    desc = 'sigma = {}'.format(sigma)
                        #(x축의 글자 시작점 좌표,y축 글 시작점 좌표)
    cv2.putText(dst, desc, (10, 30), cv2.FONT_HERSHEY_SIMPLEX,
                1.0, 255, 1, cv2.LINE_AA)

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

cv2.destroyAllWindows()

 

샤프닝 필터_1

### 샤프닝

import sys
import numpy as np
import cv2

src = cv2.imread('rose.bmp', cv2.IMREAD_GRAYSCALE)

if src is None:
    print('Image load failed!')
    sys.exit()

blr = cv2.GaussianBlur(src,(0,0),2) #블러가 된 영상, 부드러워진 영상, 차이값을 얻디위해 블러처리

'''
엣지 포인트만 남아서 윤곽선으로 보인다. 
이 윤곽선을 나타내는 픽셀값을 원본 영상에 더하면 되는데
subtract는 음수의 값을 0으로 바꾸기 때문에 완전한 엣지 픽셀모양이 아니다
이를 해결하기 위해서 addweighted를 사용한다
dst =cv2.subtract(src,blr) 
'''
#src에 1가중치, blr에 -1 가중치 준뒤
#결과값을 잘 보기 위해서 128을 더해준다
tmp= cv2.addWeighted(src,1,blr,-1,128) #회색부분은 윤곽선이 아닌 부분임,흰색또는 검정색 부분이 엣지 포인트

#방법1
#아래처럼하면 tmp객체를 이용한 덧셈을 할 필요가 없다
#원하는 결과물은 (원본-부드러운영상)+원본= "2원본-부드러워진영상"이므로
#가중치를 아래처럼 설정한다.
dst= cv2.addWeighted(src,2,blr,-1,128) #가중치에 -가 붙으면 뺄셈이 가능하다

#방법2
#numpy형식이므로 아래 처럼 src-blr 형태로가능
#타입이 float으로 계산해야 saturate가 되지 않는다
# dst=np.clip(2.0*src-blr, 0,255).astype(np.uint8) #float64형태->np.uint8 변환해야 0~255 값 표현가능(2**8=256)

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

cv2.destroyAllWindows()

 

샤프닝 필터_2

### 컬러샤프닝

import sys
import numpy as np
import cv2

src = cv2.imread('rose.bmp') #컬러

if src is None:
    print('Image load failed!')
    sys.exit()

#컬러영상:밝기 채널만 활용한다
src_ycrcb = cv2.cvtColor(src, cv2.COLOR_BGR2YCrCb)

                    #0: Y(밝기)plane
src_f = src_ycrcb[:, :, 0].astype(np.float32) #np.float32 실수타입으로 바꾼다. 정교한 결과를 위해서

#GaussianBlur은 입력영상의 타입을 출력영상 타입과 같게 한다
#src_f가 실수값이라서 blr도 실수값을 가진다.
#실수값을 가진다는 건 213.3243352 의3243352이라는 미세한 픽셀값이 살아 있다는 의미
#따라서 미세한 값까지 반영한 픽셀값을 uint8로 변경해서 출력하면 보다 더 정교한 결과를 얻을수 있다 
blr = cv2.GaussianBlur(src_f, (0, 0), 2.0)

#더해진 값을 0번째 plane에 덮어쓰기
src_ycrcb[:, :, 0] = np.clip(2.* src_f - blr, 0, 255).astype(np.uint8)

dst = cv2.cvtColor(src_ycrcb, cv2.COLOR_YCrCb2BGR) #imshow는 BGR채널만 취급한다

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

cv2.destroyAllWindows()

 

median 필터

### median 필터 

import sys
import numpy as np
import cv2

src = cv2.imread('noise.bmp', cv2.IMREAD_GRAYSCALE)

if src is None:
    print('Image load failed!')
    sys.exit()

#입력영상에서 3*3 커널 픽셀을 정렬 한 후 median값을 결과영상 가운데 값에 그대로 넣는다
#후추노이즈 제거에 효과적
dst = cv2.medianBlur(src, 3)

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

cv2.destroyAllWindows()
   

 

### 잡음제거 필터

import sys
import numpy as np
import cv2

src = cv2.imread('lenna.bmp', cv2.IMREAD_GRAYSCALE)

if src is None:
    print('Image load failed!')
    sys.exit()

#커널크기는 자동적으로 계산되기 때문에 -1값으로 입력하는게 좋다
#10(시그마 값임): 이 값을 기준으로 엣지 부분인지 아닌지를 판단한다.(sigmaColor)
#5: sigmaspace -> 가우시안블러의 시그마기능과 완전히 같다
#5이상의 값을 넣으면 가우시간 필터값이 커지게 된다 (8*sigma+1 또는 6*sigma+1)
#필터크기가 커진다-> 연산량증가 -> 속도 저하
dst = cv2.bilateralFilter(src, -1, 10, 5)

'''
sigmaColor추가설명
위 예제처럼 표준편차가 10이라고 한다면
가우시안 분포x 값이 -10<x<10 사이에 67%값들이 모여있다고 설명할수 있다
이때, 보통 플러스마이너스 2시그마, or 3시그마 보다 큰 픽셀이라면 
엣지로 인식해서 블러를 적용안하고 살린다. 
'''


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

cv2.destroyAllWindows()

 

카툰필터 

### 카툰 필터

# 카툰 필터 카메라

import sys
import numpy as np
import cv2

#자연스러운 컬러를 단순한 컬러로 바꾸고 ->cv2.bilaterFilter
#검정색 엣지를 단순한 컬러 영상에 ->cv2.Canny
#합친다 ->cv2.bitwise_and():검정색 엣지를  0픽셀값으로 변경하고, 그외 하얀 부분은 단순한 컬로 영상으로 채운다
def cartoon_filter(img):
    
    #크기 반으로 축소
    h,w =img.shape[:2]
    img =cv2.resize(img, (w//2, h//2)) #축소 후 연산하면 연산량도 줄어들뿐만 아니라 단순한 컬러의 효과가 극대화된다

    blr= cv2.bilateralFilter(img, -1, 20, 7) #과장하게 만들기 위해 시그마 값을 좀 높게 설정
    
    #50~120으로하면 평탄한 부분이 검정,엣지가 하얀색이되므로 255로 빼서 반전시킨다
    #평탄한부분이 하얀, 엣지가 검정으로 반전되는 것
    edge=cv2.Canny(img,50,120) #컬러영상을 내부적으로 그레이로 바꾼다
    edge=cv2.cvtColor(edge,cv2.COLOR_GRAY2BGR) #blr가 컬러이므로 합치기 위해서 타입을 컬러로 통일
    dst= cv2.bitwise_and(blr,edge)
    
    #크기 정상으로 다시 확대
    dst=cv2.resize(dst,(w,h), interpolation=cv2.INTER_NEAREST) #interpolation의 디폴트 값으로 하면 블러처리된 느낌을 준다
                                                               #지금은 급격한 변화를 줘야 하므로 따로 설정한다

    return dst

#그레이로 컨버트 시킨 후 
#가우시안블러로 처리한다. 
#가우시안블러를 사용하면 엣지 부분이 완만한 곡선으로 블러처리되는데
#이 부분을 검정색으로처리하고, 나머지는 모두 흰색으로 처리한다
#검정과 흰색을 처리하는 연산은 가우시안블러를 한 영상을 그레이영상에 나눗셈하여 얻을수 있다
#가우시안블러가 큰 쪽(엣지가 발생한 영역)은 0.xx 값으로 나온다.
#엣지영역에 가우시안블러를 처리하면 급격한 경사을 완만한 곡선으로 만들어준다
#급격한 경사를 이루는 부분의 높이가 완만한곡선의 높이보다 낮으므로
#완만한곡선의 높이를 나누면 0.xx로 되고
#반대로 그레이값의 높이가 더 큰 평탄화 부분은 픽셀 1.xxx로 결과값을 얻게 된다
#0.xx 와 1.xx 이둘이 남겨 되는데 0픽셀이나 1픽셀이나 구분을 못하므로 곱하기 255로 해준다
#결론적으로 0*255, 1*255이 되므로 엣지 부분이 검정색, 나머지가 하얀색으로 된다
def pencil_sketch(img): 
    gray= cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    blr= cv2.GaussianBlur(gray, (0,0), 3)#가우시안블러처리
    dst=cv2.divide(gray, blr, scale=255) #나눠준후 255곱하기
    return dst


cap = cv2.VideoCapture(0)

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

cam_mode = 0 # 0이 오리지널, 1:카툰필터, 2:스케치 필터

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

    if not ret:
        break

    if cam_mode == 1:
        frame = cartoon_filter(frame)
    elif cam_mode == 2:
        frame = pencil_sketch(frame)
        # frame = cv2.cvtColor(frame, cv2.COLOR_GRAY2BGR) #없어도 작동한다

    cv2.imshow('frame', frame)
    key = cv2.waitKey(1)

    if key == 27:
        break
    elif key == ord(' '):
        cam_mode += 1
        if cam_mode == 3:
            cam_mode = 0


cap.release()
cv2.destroyAllWindows()

 

728x90

+ Recent posts