반응형

안녕하세요, 츄르 사려고 코딩하는 집사! 코집사입니다.

이번 글은 [영상처리/OpenCV-Python] 가우시안 노이즈 영상 이미지를 더하여 노이즈 줄이는 방법입니다.

학교 과제로 나왔었는데, 이 가우시안 노이즈 영상을 더해서 노이즈를 줄이라는 과제였습니다.

그래서, 단순하게 필터링 방법을 이용해보자라는 생각을 하게 되었고, 미디언 필터링, 평균값 필터링, 가우시안 필터링 등 여러 필터링을 사용했는데도 원하는 결과값이 안나오더라구요.

그래서, 단순 연산인 이미지 평균연산을 이용했는데, 원하는 결과값이 나왔습니다.

 

1. 결과

 

이미지를 합친 갯수 N=1, N=2, N=4 까지

 

왼쪽부터, 이미지를 합친 갯수에 따라서 많이 합쳤으면 노이즈가 많이 제거 되었습니다.

N=1, N=2, N=4 순으로 정렬되었습니다.

 

원리는 2개의 이미지의 값을 합쳐서 이미지의 갯수로 나눈 다음, 새로운 이미지에 넣는 방식입니다.

예를 들어, New[h,w] = (A[h,w] + B[h,w])/2 이런식으로 함수를 구현하였습니다.

 

 

2. 소스 코드

import os
import cv2
import numpy as np

_MAX_HISTO_ = 256

#오버플로우 방지를 위한 함수
def cut_range(img_src, min_val=0, max_val=255):
    img_cut = np.zeros(img_src.shape)
    for h in range(img_src.shape[0]):
        for w in range(img_src.shape[1]):
            if img_src[h,w] < min_val:
                img_cut[h,w] = min_val
            elif img_src[h,w] > max_val:
                img_cut[h,w] = max_val
            else:
                img_cut[h,w] = img_src[h,w]
    return img_cut

#원본 영상에 가우시안 노이즈를 추가한 결과를 반환하는 함수(float64 타입을 반환)
#원본 영상과 정규분포의 표준편차 값을 인자로 받음

def add_gaussian_noise(img_src, std):

    src_height = img_src.shape[0]
    src_width = img_src.shape[1]
    #노이즈가 발생한 이미지를 저장할 변수 생성(오버플로우를 방지하기 위해 float64형 사용)
    img_noisy = np.zeros(img_src.shape, dtype=np.float64)
    for h in range(src_height):
        for w in range(src_width):
            #평균0 표준편차가 1인 정규분포를 가지는 난수 발생
            std_norm = np.random.normal()
            #인자로 받은 표준편차와 곱
            random_noise = std*std_norm
            #원본 값에 발생한 난수에 따른 노이즈를 합
            img_noisy[h,w] = img_src[h,w]+random_noise
    #노이즈가 발생한 이미지를 반환
    return img_noisy

def img_aver(img1, img2):
    src_height = img1.shape[0]
    src_width = img1.shape[1]
    img = np.zeros(img1.shape, dtype=np.float64)
    for h in range(src_height):
        for w in range(src_width):
            img[h,w] = (img1[h,w] + img2[h,w])/2

    return img

def img_aver2(img1, img2, img3, img4):
    src_height = img1.shape[0]
    src_width = img1.shape[1]
    img = np.zeros(img1.shape, dtype=np.float64)
    for h in range(src_height):
        for w in range(src_width):
            img[h,w] = (img1[h,w] + img2[h,w]+img3[h,w] + img4[h,w])/4

    return img

#현재 실행되고 있는 경로 값을 얻어서 이미지 경로를 조합
cur_path = os.getcwd()
img_src='moon.jpg'
img_src_path = os.path.join(cur_path, img_src)

#원본 상태로 이미지 읽기
img_src = cv2.imread(img_src_path, cv2.IMREAD_GRAYSCALE)

#가우시안 노이즈를 생성
img_gn = add_gaussian_noise(img_src, 64)
img_gn2 = add_gaussian_noise(img_src, 64)
img_gn3 = add_gaussian_noise(img_src, 64)
img_gn4 = add_gaussian_noise(img_src, 64)
img_N2 = img_aver(img_gn, img_gn2)
img_N4 = img_aver2(img_gn, img_gn2, img_gn3, img_gn4 )

#값의 범위를 unit8형에 맞게 자르고 형변환
img_gn = np.uint8(cut_range(img_gn))
img_gn2 = np.uint8(cut_range(img_gn2))
img_N2 = np.uint8(cut_range(img_N2))
img_N4 = np.uint8(cut_range(img_N4))


               
cv2.imshow('N=1', img_gn) # N=1일 때
cv2.imshow('N=2', img_N2) # N=2일 때
cv2.imshow('N=4', img_N4) # N=4일 때
cv2.waitKey()
cv2.destroyAllWindows()

반응형
  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기