[Anaconda+python] GMSD의 matlab 코드를 python으로 작성하기

코딩/python|2020. 2. 20. 01:26

안녕하세요. 비스카이비전의 심교훈입니다. 오늘은 python 코딩을 연습하기 위해서 GMSD의 matlab 코드를 python으로 작성해보도록 하겠습니다. GMSD는 이미지품질평가(image quality assessment, IQA) 모델들 중에 아주 빠르면서도 비교적 정확하게 품질을 예측해내는 모델입니다. 우선 GMSD의 matlab 코드는 다음과 같습니다. 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
function [score, quality_map] = GMSD(Y1, Y2)
 
% GMSD - measure the image quality of distorted image 'Y2' with the reference image 'Y1'.
% inputs:
% Y1 - the reference image (grayscale image, double type, 0~255)
% Y2 - the distorted image (grayscale image, double type, 0~255)
% outputs:
 
% score: distortion degree of the distorted image
% quality_map: local quality map of the distorted image
 
% This is an implementation of the following algorithm:
% Wufeng Xue, Lei Zhang, Xuanqin Mou, and Alan C. Bovik, 
"Gradient Magnitude Similarity Deviation: A Highly Efficient Perceptual Image Quality Index",
% http://www.comp.polyu.edu.hk/~cslzhang/IQA/GMSD/GMSD.htm
 
= 170
Down_step = 2;
dx = [1 0 -11 0 -11 0 -1]/3;
dy = dx';
 
aveKernel = fspecial('average',2);
aveY1 = conv2(Y1, aveKernel,'same');
aveY2 = conv2(Y2, aveKernel,'same');
Y1 = aveY1(1:Down_step:end,1:Down_step:end);
Y2 = aveY2(1:Down_step:end,1:Down_step:end);
 
IxY1 = conv2(Y1, dx, 'same');     
IyY1 = conv2(Y1, dy, 'same');    
gradientMap1 = sqrt(IxY1.^2 + IyY1.^2);
 
IxY2 = conv2(Y2, dx, 'same');     
IyY2 = conv2(Y2, dy, 'same');
 
gradientMap2 = sqrt(IxY2.^2 + IyY2.^2);
quality_map = (2*gradientMap1.*gradientMap2 + T) ./(gradientMap1.^2+gradientMap2.^2 + T);
score = mean2(quality_map);
 
cs

 

위 matlab 코드를 한줄 한줄 분석해가면서 python으로 작성해봤습니다. 완벽하게 동일한 결과를 내기 위해서 디테일한 부분들에도 신경썼습니다. 참고로 아래 python 코드를 실행하시려면 opencv-python, numpy, scipy 패키지들을 설치해주셔야 합니다. conda install opencv-python numpy scipy 또는 pip install opencv-python numpy scipy를 anaconda prompt에 입력해주시면 됩니다.^^

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
import cv2
import numpy as np
from scipy import signal
 
ori_img = cv2.imread('ori.bmp', cv2.IMREAD_COLOR)
dist_img = cv2.imread('dist.bmp', cv2.IMREAD_COLOR)
 
ori_img = cv2.cvtColor(ori_img, cv2.COLOR_BGR2GRAY)
dist_img = cv2.cvtColor(dist_img, cv2.COLOR_BGR2GRAY)
 
ori_img = np.float64(ori_img)
dist_img = np.float64(dist_img)
 
ave_kernal = np.array([[0.250.25],
                       [0.250.25]])
 
ave_ori = signal.convolve2d(ori_img, ave_kernal, boundary='fill', mode='full')
(M, N) = ave_ori.shape
ave_ori = ave_ori[1:M, 1:N]
 
ave_dist = signal.convolve2d(dist_img, ave_kernal, boundary='fill', mode='full')
(M, N) = ave_dist.shape
ave_dist = ave_dist[1:M, 1:N]
 
ori_img = ave_ori[::2, ::2]
dist_img = ave_dist[::2, ::2
 
Prewitt_x = np.array([[10-1],
                      [10-1],
                      [10-1]])/3
Prewitt_x = np.float64(Prewitt_x)
Prewitt_y = np.transpose(Prewitt_x)
 
ori_GM_x = signal.convolve2d(ori_img, Prewitt_x, boundary='fill', mode='full')
(M, N) = ori_GM_x.shape
ori_GM_x = ori_GM_x[1:M-11:N-1]
 
ori_GM_y = signal.convolve2d(ori_img, Prewitt_y, boundary='fill', mode='full')
(M, N) = ori_GM_y.shape
ori_GM_y = ori_GM_y[1:M-11:N-1]
 
ori_GM = np.sqrt(np.square(ori_GM_x) + np.square(ori_GM_y))
 
dist_GM_x = signal.convolve2d(dist_img, Prewitt_x, boundary='fill', mode='full')
(M, N) = dist_GM_x.shape
dist_GM_x = dist_GM_x[1:M-11:N-1]
 
dist_GM_y = signal.convolve2d(dist_img, Prewitt_y, boundary='fill', mode='full')
(M, N) = dist_GM_y.shape
dist_GM_y = dist_GM_y[1:M-11:N-1]
 
dist_GM = np.sqrt(np.square(dist_GM_x) + np.square(dist_GM_y))
 
= 170
quality_map = (2*ori_GM*dist_GM + 170)/(np.square(ori_GM) + np.square(dist_GM) + T)
 
score = np.std(quality_map)
print("score:", score)
cs

 

GMSD의 개발자들이 제공한 matlab 코드와 제가 작성한 python 코드가 동일한 결과를 내는지 확인해보겠습니다. GMSD는 full-reference 모델이기 때문에 왜곡된 이미지의 품질을 평가할 때 아무런 왜곡도 존재하지 않는 깨끗한 원본 이미지를 참조해서 품질을 평가합니다. 저는 다음과 같은 왜곡 이미지와 원본 이미지를 테스트에 사용했습니다. 

 

 

GMSD의 경우 왜곡된 이미지의 품질이 원본 이미지와 가까울수록, 즉 좋을수록 0에 가까운 값을 산출해냅니다. 반대로 품질이 나쁠수록 0에서 먼 값을 산출해냅니다.

 

자, 그럼 matlab 코드와 python 코드가 위 테스트이미지쌍에 대해서 동일한 품질 점수를 산출해내는지 확인해보겠습니다. 

 

먼저 matlab 코드를 실행한 결과입니다.

그 다음은 python 코드를 실행한 결과입니다. 

 

소숫점 아래 5번째 자리에서 반올림하면 두 결과가 같은 것을 알 수 있습니다. 

 

하나만 더 테스트해볼까요? 이번엔 다음 이미지들을 가지고 테스트하겠습니다. 

 

matlab 코드로 얻은 점수와 python 코드로 얻은 점수는 각각 다음과 같습니다. 

 

 

역시 동일한 결과를 산출해냈습니다. 즉, GMSD 논문의 저자들이 제공한 matlab 코드와 제가 작성한 python 코드는 동일한 기능을 수행한다고 결론지을 수 있습니다. 

 

코드는 제 깃헙에서도 다운로드 받으실 수 있습니다. 

https://github.com/kyohoonsim/image_quality_assessment/tree/master/GMSD

 

kyohoonsim/image_quality_assessment

Contribute to kyohoonsim/image_quality_assessment development by creating an account on GitHub.

github.com