Hyogi's Notebook

영상 흐림과 선명화와 경계선 검출 다중 영상처리 개념

by 효기’s

영상 선명화 (Sharpening)

영상의 상세정보를 강화

평균값 필터링 : 이미지나 노이즈 제거하는데 사용 (잡티없앰)

sharpening(선명화) : 이미지나 영상 데이터의 선명도를 높이는데 사

중간값 필터링 : 노이즈 제거에 효과적

thresholding(임계치 처리) : 이미지나 영상 데이터에서 특정 값을 기준으로 이진화하는데 사용.

 

Bilateral Filtering 

Bilateral Filtering(양방향 필터링)은

이미지나 영상 데이터에서 노이즈를 제거하면서도 엣지(edge)를 보존하는 데 사용됩니다.

 

양각효과(embossing)

1. 양각효과 마스크를 회선처리

2. 회선한 값에 영상의 평균값을 더한다.

 

Alpha - trimmed 평균값 필터링 ★

중간값 필터링과 평균값 필터링의 장점을 결합

알파 값에 따라 양쪽 끝부분을 제외

import cv2
import sys
import numpy as np

def alpha_mean_filter(src, alpha, ksize):
    rows, columns = src.shape[:2]
    dd = ksize // 2     # 한쪽에 추가될 픽셀 수
    tmp = np.zeros((rows+ksize, columns+ksize))
    tmp[dd:dd+rows, dd:dd+columns] = src.copy() # 가운데에 원래 영상 배치, 주변은 모두 0이다.
    dm = np.floor(ksize * ksize * alpha).astype(np.uint8)
    dst = src.copy()    # 작업을 위한 임시 영상
    for r in range(rows):
        for c in range(columns):
            sorted = np.sort(np.ravel(tmp[r:r+ksize, c:c+ksize]))
            dst[r,c] = np.mean(sorted[int(alpha*ksize*ksize):-int(alpha*ksize*ksize)])

    return dst.astype(np.uint8)

img = cv2.imread('images/pns_color.jpg', cv2.IMREAD_GRAYSCALE)

if img is None:
    print('영상 읽기 실패')
    sys.exit()

cv2.imshow('Original', img)
dst = alpha_mean_filter(img, 0.3, 5)
cv2.imshow('Result', dst)
cv2.waitKey()
cv2.destroyAllWindows()

 

경계선 (Edge)

픽셀의 밝기 값이 급격하게 변하는 부분

객체와 객체, 개체와 배경의 경계

물체를 식별하고 물체의 위치, 모양, 크기 등을 인지하는 데 큰 역할

 

경계선 검출

경계선 검출 필터

# Edge Detection

import cv2
import sys
import numpy as np

img = cv2.imread('images/Lenna.png', cv2.IMREAD_GRAYSCALE)

if img is None:
    print('영상 읽기 실패')
    sys.exit()

PrewittX = np.array([[-1, -1, -1], 
                   [0, 0, 0], 
                   [1, 1, 1]])
PrewittY = np.array([[1, 0, -1], 
                   [1, 0, -1], 
                   [1, 0, -1]])

RobertsX = np.array([[-1, 0, 0], 
                   [0, 1, 0], 
                   [0, 0, 0]])
RobertsY = np.array([[0, 0, -1], 
                   [0, 1, 0], 
                   [0, 0, 0]])

SobelX = np.array([[-1, -2, -1], 
                   [0, 0, 0], 
                   [1, 2, 1]])
SobelY = np.array([[1, 0, -1], 
                   [2, 0, -2], 
                   [1, 0, -1]])

px = cv2.filter2D(img, -1, PrewittX)
py = cv2.filter2D(img, -1, PrewittY)
resultP = cv2.add(px, py)

rx = cv2.filter2D(img, -1, RobertsX)
ry = cv2.filter2D(img, -1, RobertsY)
resultR = cv2.add(rx, ry)

sx = cv2.filter2D(img, -1, SobelX)
sy = cv2.filter2D(img, -1, SobelY)
resultS = cv2.add(sx, sy)

cv2.imshow('Original', img)
cv2.imshow('Prewitt', resultP)
cv2.imshow('Roberts', resultR)
cv2.imshow('Sobel', resultS)
cv2.waitKey()
cv2.destroyAllWindows()

cv2.Scharr

소벨 필터가 커널의 크기가 작은 경우

또는 커널의 크기가 크더라도 그 중심에서 멀어 질수록 엣지 방향의 정확도가 떨어지는 단점이 있고 이를 개선한 필터

 

라플라시안 필터

2차 미분을 활용, 노이즈에 지나치게 민감 (많은 경계선이 나옴)

(밑에 실습 사진)

 

LOG 필터 (Laplacian of Gaussian)

가우시안 필터로 노이즈를 제거한 후, 라플라시안으로 경계선 검출

두 개 과정을 수학 계산에 의해 하나의 필터로 계산

# Laplacian, LoG

import cv2
import sys
import numpy as np

img = cv2.imread('images/Lenna.png', cv2.IMREAD_GRAYSCALE)

if img is None:
    print('영상 읽기 실패')
    sys.exit()

lap = cv2.Laplacian(img, cv2.CV_64F)
gs = cv2.GaussianBlur(img, (5,5), 0)

log = cv2.Laplacian(gs, cv2.CV_64F)

cv2.imshow('Original', img)
cv2.imshow('Laplacian', lap)
cv2.imshow('LoG', log)
cv2.waitKey()
cv2.destroyAllWindows()

 

컬러 경계선 검출

영상 밝기의 변화 : HIS공간에서 I (밝기)에 대해 검출

 RGB 채널의 변화 : R, G, B 각 채널에 대해 검출

 

캐니 경계선 검출(Canny Edge Detection)

좋은 경계선 검출 조건 

1. 정확한 검출

2. 정확한 위치

3. 단일한 경계선

 

캐니 알고리즘

가우시안 필터링으로 노이즈 제거

소벨 마스크로 기울기가 높은 지점 검출

비최대 억제 적용

hysteresis edge tacking : 상한 하한 임계값을 두고, 상한 임계값보다 크면 경계선으로 선정

                                         상한보다 작고 하한보다 크며, 강한 경계선과 연결되면 경계선으로 선정

 

캐니 경계선 검출 예시

# Canny Edge Detection

import cv2
import sys
import numpy as np

# img = cv2.imread('images/Lenna.png', cv2.IMREAD_GRAYSCALE)
img = cv2.imread('images/balloons.jpg', cv2.IMREAD_COLOR)

if img is None:
    print('영상 읽기 실패')
    sys.exit()

be = cv2.Canny(img[:,:,0], 80, 150)
ge = cv2.Canny(img[:,:,1], 80, 150)
re = cv2.Canny(img[:,:,2], 80, 150)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
cn = cv2.Canny(gray, 80, 150)

cv2.imshow('Original', img)
cv2.imshow('Blue',img[:,:,0])
cv2.imshow('Green',img[:,:,1] )
cv2.imshow('Red', img[:,:,2])
cv2.imshow('Blue Edge', be)
cv2.imshow('Green Edge', ge)
cv2.imshow('Red Edge', re)
cv2.imshow('Gray', gray)
cv2.imshow('Canny', cn)
cv2.waitKey()
cv2.destroyAllWindows()

Cartoon 영상 만들기

# Cartoon 영상 만들기
# 1) 영상을 단순화 - 영상 축소 후 bilateral 필터링
# 2) 경계선 영상 생성 - Canny 호출
# 3) 단순화된 영상과 경계선 영상의 합성

import cv2
import sys
import numpy as np

img = cv2.imread('images/Lenna.png', cv2.IMREAD_GRAYSCALE)

if img is None:
    print('영상 읽기 실패')
    sys.exit()

h, w = img.shape[:2]    # 영상의 높이와 넓이 구하기
img2 = cv2.resize(img, (w//2, h//2))  # 반으로 축소(단순화)

blr = cv2.bilateralFilter(img2, -1, 20, 7)  # 과장된 효과를 위해 큰 값 지정
edge = 255 - cv2.Canny(img2, 80, 120)       # 흰색과 검정색의 반전

dst = cv2.bitwise_and(blr, edge)    # Canny 영상의 검은색(경계선)을 blr에서 강화
dst = cv2.resize(dst,  (w, h),  interpolation=cv2.INTER_NEAREST)

cv2.imshow('Original', img)
cv2.imshow('Cartoon', dst)
cv2.waitKey()
cv2.destroyAllWindows()

 

두 영상의 덧셈

import cv2
import sys
import numpy as np

img = cv2.imread('images/Lenna.png', cv2.IMREAD_GRAYSCALE)

if img is None:
    print('영상 읽기 실패')
    sys.exit()

# np.array는 [rows, colums]로 구성되므로, [height, width] 구성임에 주의!
h, w = img.shape[:2]    # 영상의 높이와 넓이 구하기
mask = np.zeros((w, h), dtype=np.uint8)  # 배경은 검정색(0)
mask = cv2.circle(mask, (w//2, h//2), h//4, (255,255,255), cv2.FILLED) # 흰색 원 그리기
mask = 255 - mask   # 마스킹할 부분을 흰 색으로

mask = cv2.imread('images/circle.png', cv2.IMREAD_GRAYSCALE)
dst = cv2.add(img, mask)

cv2.imshow('Original', img)
cv2.imshow('Mask', mask)
cv2.imshow('Result', dst)
cv2.waitKey()
cv2.destroyAllWindows()

# 영상 가중 덧셈(Image Blending)

import cv2
import sys
import numpy as np

img1 = cv2.imread('images/baboon.png', cv2.IMREAD_COLOR)
img2 = cv2.imread('images/Lenna.png', cv2.IMREAD_COLOR)

if img1 is None or img2 is None:
    print('영상 읽기 실패')
    sys.exit()

a = 0.3     # 가중치
dst = cv2.addWeighted(img1, a, img2, 1-a, 0)

cv2.imshow('Original', img1)
cv2.imshow('Image', img2)
cv2.imshow('Result', dst)
cv2.waitKey()
cv2.destroyAllWindows()

트랙바 활용 영상 가중 덧셈

# 영상 가중 덧셈
# 트랙바 활용

import cv2
import sys
import numpy as np

img1 = cv2.imread('images/baboon.png', cv2.IMREAD_COLOR)
img2 = cv2.imread('images/Lenna.png', cv2.IMREAD_COLOR)

if img1 is None or img2 is None:
    print('영상 읽기 실패')
    sys.exit()
    
def change(x):
    pass
cv2.namedWindow('Mixed')
cv2.createTrackbar('Weight', 'Mixed', 0, 100, change)

while True:
    weight = cv2.getTrackbarPos('Weight', 'Mixed')
    result = cv2.addWeighted(img1, float(100-weight)*0.01, img2, float(weight)*0.01, 0)
    cv2.imshow('Mixed', result)
    
    if cv2.waitKey(1) & 0xFF == 27:     # ESC로 종료
        break

cv2.waitKey()
cv2.destroyAllWindows()

 

뺄셈 연산을 이용한 이진화

병뚜껑의 이상유무 검사

패키지 라벨 오부착 검사

충전 수위 검사

나사 파손 검사

기어 파손 검

영상의 뺄샘으로 틀린그림 찾기 가능

# 영상 뺄셈

import cv2
import sys
import numpy as np

img1 = cv2.imread('images/diff1.jpg', cv2.IMREAD_COLOR)
img2 = cv2.imread('images/diff2.jpg', cv2.IMREAD_COLOR)

if img1 is None  or img2 is None:
    print('영상 읽기 실패')
    sys.exit()

dst = cv2.absdiff(img1, img2)   # 영상의 차이ㅣ 구하기
ret, bin = cv2.threshold(dst, 30, 255, cv2.THRESH_BINARY) # 차이를 강화
ans = cv2.absdiff(img1, bin)    # 원래 영상에 표시

cv2.imshow('Original1', img1)
cv2.imshow('Original2', img2)
cv2.imshow('Result', dst)
cv2.imshow('ans', ans)
cv2.waitKey()
cv2.destroyAllWindows()

 

AND 연산

마스킹할 때 사용

OR 연산

합성할 떄 사용

XOR 연산

NOT 연산

# biwise and,  or,  xor, not
# gray image에서 밝기 0은  이진수 0, 밝기가 0이 아니면 이진수 1
# gray image에서 이진수 1은 밝기가 255임

import cv2
import sys
import numpy as np

img1 = np.zeros((300, 300), dtype=np.uint8)  # 배경은 검정색(0)
img2 = np.zeros((300, 300), dtype=np.uint8)  # 배경은 검정색(0)
img1 = cv2.circle(img1, (150,150), 150, 255, -1) # 흰색 원 그리기
img2 = cv2.rectangle(img2, (25,25), (275,275), 255,-1) # 흰색 사각형 그리기

bAnd = cv2.bitwise_and(img1, img2)
bOr = cv2.bitwise_or(img1, img2)
bXor = cv2.bitwise_xor(img1, img2)
bNot = cv2.bitwise_not(img1)

cv2.imshow('Circle', img1)
cv2.imshow('Rectangle', img2)
cv2.imshow('AND', bAnd)
cv2.imshow('OR', bOr)
cv2.imshow('XOR', bXor)
cv2.imshow('NOT', bNot)
cv2.waitKey()
cv2.destroyAllWindows()

 

영상 합성

# 영상 합성

import cv2
import sys
import numpy as np

src = cv2.imread('images/Lenna.png', cv2.IMREAD_COLOR)
mask = cv2.imread('images/Lenna_mask.png', cv2.IMREAD_COLOR)
dst = cv2.imread('images/flowers-413.jpg', cv2.IMREAD_COLOR)

if src is None or mask is None or dst is None:
    print('영상 읽기 실패')
    sys.exit()

cv2.copyTo(src, mask, dst)
cv2.imshow('Original', src)
cv2.imshow('mask', mask)
cv2.imshow('Result', dst)

cv2.waitKey()
cv2.destroyAllWindows()

블로그의 정보

감성 개발자 효기

효기’s

활동하기