IT/AI\ML

[python/OpenCV] 이미지 처리 예제 Q06~Q10

개발자 두더지 2020. 4. 20. 19:24
728x90

문제는 지난 포스팅과 같은 링크에 존재한다.

https://github.com/yoyoyo-yo/Gasyori100knock/tree/master/Question_01_10

 

yoyoyo-yo/Gasyori100knock

画像処理100本ノックして画像処理を画像処理して画像処理するためのもの For Japanese, English and Chinese - yoyoyo-yo/Gasyori100knock

github.com


Q06.감색처리(減色処理)

여기서는 이미지의 값을 256^3에서4^3,

즉 R,G,B in {32, 96, 160, 224}의 각 4 값을 감색하는 것이다.

이것을 '양자화 조작'이라고 한다.

각 값에 관해서 아래와 같이 정의한다.

val = {  32  (  0 <= val <  64)
         96  ( 64 <= val < 128)
        160  (128 <= val < 192)
        224  (192 <= val < 256)

 

A06.감색처리(減色処理)의 답안

import cv2
import numpy as np


# Dicrease color
def dicrease_color(img):
	out = img.copy()

	out = out // 64 * 64 + 32

	return out


# Read image
img = cv2.imread("assets/imori.jpg")

# Dicrease color
out = dicrease_color(img)

cv2.imwrite("out.jpg", out)
cv2.imshow("result", out)
cv2.waitKey(0)
cv2.destroyAllWindows()

https://tat-pytone.hatenablog.com/entry/2019/06/13/210251

 

K-Meansクラスタリングによる画像の減色 - Pythonでいろいろやってみる

K-Meansクラスタリングは、与えられたデータを自動的に分類するアルゴリズムであるクラスタリングの一種で、クラスタの平均を用い、与えられたクラスタ数k個に分類する手法です。(Wikipedia >> k平均法) cv2.kmeans()を用いるとK-Meansクラスタリングが簡単に実装できます。これを画像データに用いてBGRのチャンネルについてクラスタリングし、各クラスタに含まれる画素を、各クラスタの中心値に変換することで減色できます。 OpenCV >> K-Means Clustering in Op

tat-pytone.hatenablog.com

검색해 본 결과 K-Means클러스터링으로 비슷한 효과를 낼 수 있는 것 같다.


Q07. 평균 풀링(平均プーリング)

여기서는 이미지를 그리드 분할(어떤 고정 길이의 영역으로 나눔)하여,

각 영역 내 (셀)의 평균치를 그 영역 내의 값으로 메운다.

이와 같이 그리드를 분할하여 그 영역내의 대표값을 구하는 작업을 풀링(pooling)이라고 한다.

이러한 풀링 조작은 CNN(Convolutional Neural Network)에 있어 굉장히 중요한 역할을 한다.

이러한 풀링 조작은 아래와 같은 식으로 정의되어 있다.

여기서의 R은 풀링을 실시하는 영역이다.

만약 3X3의 역역에 풀링을 하면, |R|=3x3=9가 된다.

 

A07. 평균 풀링(平均プーリング)의 답안

import cv2
import numpy as np


# average pooling
def average_pooling(img, G=8):
    out = img.copy()

    H, W, C = img.shape
    Nh = int(H / G)
    Nw = int(W / G)

    for y in range(Nh):
        for x in range(Nw):
            for c in range(C):
                out[G*y:G*(y+1), G*x:G*(x+1), c] = np.mean(out[G*y:G*(y+1), G*x:G*(x+1), c]).astype(np.int)
    
    return out


# Read image
img = cv2.imread("assets/imori.jpg")

# Average Pooling
out = average_pooling(img)

# Save result
cv2.imwrite("out.jpg", out)
cv2.imshow("result", out)
cv2.waitKey(0)
cv2.destroyAllWindows()

Q08. 맥스 풀링 (Maxプーリング)

7번 문제와는 달리 평균값이 아닌 최대값으로 풀링하는 것이다.

A08. 맥스 풀링 (Maxプーリング)의 답안

import cv2
import numpy as np

# max pooling
def max_pooling(img, G=8):
    # Max Pooling
    out = img.copy()

    H, W, C = img.shape
    Nh = int(H / G)
    Nw = int(W / G)

    for y in range(Nh):
        for x in range(Nw):
            for c in range(C):
                out[G*y:G*(y+1), G*x:G*(x+1), c] = np.max(out[G*y:G*(y+1), G*x:G*(x+1), c])

    return out


# Read image
img = cv2.imread("imori.jpg")

# Max pooling
out = max_pooling(img)

# Save result
cv2.imwrite("out.jpg", out)
cv2.imshow("result", out)
cv2.waitKey(0)
cv2.destroyAllWindows()

맥스 풀링에 대한 또 다른 답안은 아래와 같다.

import cv2
import numpy as np
 
img = cv2.imread("assets/imori.jpg")
 
# 出力用
out = np.zeros_like(img)
 
num = int(128 / 8)
 
# forで全探索
for i in range(0, 128, 8):
    for j in range(0, 128, 8):
        for k in range(3):
            # 8x8の配列を取得する
            o = img[i:i+8, j:j+8, k]
            # 最大値を取る
            v = np.max(o)
            # 出力用の配列に入れる
            out[i:i+8, j:j+8, k] = v
 
out = out.astype(np.uint8)
 
# 表示
cv2.imshow("result", out)
cv2.waitKey(0)
cv2.imwrite("out.jpg", out)
cv2.destroyAllWindows()

Q09.가우시안필터(ガウシアンフィルタ)

가우시안 필터(3x3 표준편차 1.3)을 구현하고 imori_noise.jpg의 노이즈를 제거해보자.

가우시안 필터란 이미지의 평활화(매끄럽게 하는 것)하는 필터의 한 종류이며, 노이즈 제거에도 사용된다.

노이즈 제거는 메디안필터, 평활화필터, LoG필터 등이 있다.

가우시안필터는 주목화소의 주변화소를 가우스 분포에 의한 가중치에 따라 평활화하며,

다음과 같은 공식으로 표현할 수 있다.

重み g(x,y,s) = 1/ (2 * pi * sigma * sigma) * exp( - (x^2 + y^2) / (2*s^2))
標準偏差s = 1.3による8近傍ガウシアンフィルタは
            1 2 1
K =  1/16 [ 2 4 2 ]
            1 2 1

 

A09. 가우시안필터(ガウシアンフィルタ)의 답안

https://github.com/yoyoyo-yo/Gasyori100knock/blob/master/Question_01_10/imori_noise.jpg

 

yoyoyo-yo/Gasyori100knock

画像処理100本ノックして画像処理を画像処理して画像処理するためのもの For Japanese, English and Chinese - yoyoyo-yo/Gasyori100knock

github.com

우선 위의 링크에서 imori_noise.jpg를 다운 받아 assets파일에 저장하여야 잘 실행이 된다는 점을 주의하자.

import cv2
import numpy as np


# Gaussian filter
def gaussian_filter(img, K_size=3, sigma=1.3):
	if len(img.shape) == 3:
		H, W, C = img.shape
	else:
		img = np.expand_dims(img, axis=-1)
		H, W, C = img.shape

		
	## Zero padding
	pad = K_size // 2
	out = np.zeros((H + pad * 2, W + pad * 2, C), dtype=np.float)
	out[pad: pad + H, pad: pad + W] = img.copy().astype(np.float)

	## prepare Kernel
	K = np.zeros((K_size, K_size), dtype=np.float)
	for x in range(-pad, -pad + K_size):
		for y in range(-pad, -pad + K_size):
			K[y + pad, x + pad] = np.exp( -(x ** 2 + y ** 2) / (2 * (sigma ** 2)))
	K /= (2 * np.pi * sigma * sigma)
	K /= K.sum()

	tmp = out.copy()

	# filtering
	for y in range(H):
		for x in range(W):
			for c in range(C):
				out[pad + y, pad + x, c] = np.sum(K * tmp[y: y + K_size, x: x + K_size, c])

	out = np.clip(out, 0, 255)
	out = out[pad: pad + H, pad: pad + W].astype(np.uint8)

	return out


# Read image
img = cv2.imread("assets/imori_noise.jpg")


# Gaussian Filter
out = gaussian_filter(img, K_size=3, sigma=1.3)


# Save result
cv2.imwrite("out.jpg", out)
cv2.imshow("result", out)
cv2.waitKey(0)
cv2.destroyAllWindows()

이 문제 역시 OpenCV를 활용하면 간단한 코드로 해결 가능하다.

http://labs.eecs.tottori-u.ac.jp/sd/Member/oyamada/OpenCV/html/py_tutorials/py_imgproc/py_filtering/py_filtering.html

 

画像の平滑化 — OpenCV-Python Tutorials 1 documentation

画像のぼかし (平滑化) 画像のぼかしはローパスフィルタのカーネルを重畳積分することで実現でき,画像中のノイズ除去などに使います.画像中の高周波成分(エッジやノイズ)を消すことで結果として画像全体がぼけます(エッジをぼけさせない画像のぼかし方もあります).OpenCVが用意しているのは4種類のぼかし方です. 1. 平均 平均を取るには正規化された箱型フィルタを使います. カーネルの範囲内にある全画素の画素値の平均をとります. cv2.blur() か cv2.boxFilter() を使います.カーネルの縦

labs.eecs.tottori-u.ac.jp

참고하여 작성한 코드는 아래와 같다.

import cv2
import numpy as np

# Read image
img = cv2.imread("assets/imori_noise.jpg")


# Gaussian Filter
out = cv2.GaussianBlur(img,(3,3),1.3)

# Save result
cv2.imwrite("gaussian.jpg", out)
cv2.imshow("result", out)
cv2.waitKey(0)
cv2.destroyAllWindows()

Q10. 메디안 필터(メディアンフィルタ)

이번에는 메디안 필터로 노이즈를 제거하는 문제이다.

앞서 말했듯, 메이안 필터는 이미지의 평활화 필터의 한 종류이다.

이것은 주목화소의 3x3의 영역내의 메디안값(중앙값)을 줄력하는 필터이다.

A10. 메디안 필터(メディアンフィルタ)의 답안

import cv2
import numpy as np


# Median filter
def median_filter(img, K_size=3):
    H, W, C = img.shape

    ## Zero padding
    pad = K_size // 2
    out = np.zeros((H + pad*2, W + pad*2, C), dtype=np.float)
    out[pad:pad+H, pad:pad+W] = img.copy().astype(np.float)

    tmp = out.copy()

    # filtering
    for y in range(H):
        for x in range(W):
            for c in range(C):
                out[pad+y, pad+x, c] = np.median(tmp[y:y+K_size, x:x+K_size, c])

    out = out[pad:pad+H, pad:pad+W].astype(np.uint8)

    return out


# Read image
img = cv2.imread("imori_noise.jpg")


# Median Filter
out = median_filter(img, K_size=3)


# Save result
cv2.imwrite("out.jpg", out)
cv2.imshow("result", out)
cv2.waitKey(0)
cv2.destroyAllWindows()

위의 답안 링크에 있는 내용을 보면 메디안 필터에 대한 내용도 나온다.

그 내용을 참고하여 작성한 코드는 아래와 같다.

import cv2
import numpy as np

# Read image
img = cv2.imread("assets/imori_noise.jpg")


# Gaussian Filter
out = cv2.medianBlur(img,3)

# Save result
cv2.imwrite("median.jpg", out)
cv2.imshow("result", out)
cv2.waitKey(0)
cv2.destroyAllWindows()

문제의 답변 링크 외에 10번까지 자신만의 방법으로 문제를 푼 포스트도 있어서 공유한다.

https://chizuchizu.com/2019/05/06/knock/#Q7

 

【Q.1-10】画像処理100本ノックの解法を全部載っける|チズブログ!

はじめに みなさんは、「画像処理100本ノック」というものを知っていますか? 画像処理100本ノックを作ったった こちら

chizuchizu.com

 

728x90