[PBRT-V3]怎么对比不同渲染算法的效果

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/libing_zeng/article/details/82534152

面对不同的渲染算法,比如:PT、BDPT、PM、SPPM、Original MLT、PSSMLT、MMLT等等,对比不同渲染算法效果的常用方式是:相同时间下,渲染图片的质量(或者,渲染相同质量图片所需的时间)。

这里涉及到一个关键问题:怎么评估渲染图片的质量?
一般是,计算渲染图片和参考图片(标准图片)的MSE(均方差)。

参考图片的选择要特别注意!!!
参考图片的选择要特别注意!!!
参考图片的选择要特别注意!!!
(小编正是在因为选错了参考图片然后被折磨得死去活来之后,才决定写这篇博文的)

举例说明。
假设我们要用MMLT渲染这么一个场景:
https://benedikt-bitterli.me/resources/
这里写图片描述
小编下载这个场景模型的原因是:其提供了参考图片(如果是本地自己用path tracing渲染一张参考图片的话,至少得好几十个小时吧)
具体怎么用PBRT-V3渲染这个场景,不是本篇文章的内容。此处默认已经完成渲染得到了一张渲染图片。
现在,是要根据渲染图片和参考图片的MSE判断渲染图片的质量。

下载的场景模型文件夹中包含两张参考图片,分别是:
TungstenRender.exr
TungstenRender.png
在不调节场景的几何参数时,对应的参考图片应该是来自TungstenRender.exr。

小编用的MSE程序是基于网络上找的一段python代码改的。
python貌似不能直接读取.exr文件,另外考虑到这个场景的描述文件中设置的渲染图片输出格式为.png,所以,我们将.exr格式的参考图片转换为.png格式。
Mac中的Preview软件是可以读取.exr格式的,而且可以直接将其转换为.png格式。但是,不要这么做,不要这么做,不要这么做!!!!!
这样操作得到的png参考图片和PBRT-V3产生的渲染图片是“不匹配”的,所以会导致MSE计算错误。

小编转换参考图片的具体步骤如下(敲黑板,划重点):
1,shift+cmd+4在屏幕上截一张640x360的图(考虑到:参考图片是1280x720分辨率,另外“截图”刚好是png格式),然后用Preview打开截图;
2,用Preview打开原.exr格式的参考图片,然后复制参考图片(ctrl+a,ctrl+c);
3,将1280x720参考图片粘贴到640x360的“截图”上(参考图片会自动缩小,然后调整位置使得参考图片刚好填在“截图”上)
4,Tools–>Adjust Size,将Resolution后面的数字由144改成72(此时“截图”图片即为1280x720分辨率png格式的参考图片了)

得到正确的参考图片之后,就可用如下代码计算MSE了。
(再次声明这段程序是基于网路上的python代码改的,原出处找不到了,抱歉)

import cv2


def clmap(v, k, upBound):  # mul and clamp
    val = v * k
    if val > upBound:
        return upBound
    else:
        return val


#inImage_1 = '/Users/libingzeng/CG/pbrt-v3/buildX/Debug/living-room/living-room_13_0_1280,720_m100_985s.png'  #
#inImage_1 = '/Users/libingzeng/CG/pbrt-v3/buildX/Debug/living-room/living-room_9_0_1280,720_670_9_7510s.png'  #
#inImage_1 = '/Users/libingzeng/CG/pbrt-v3/buildX/Debug/living-room/living-room_5_0_1280,720_750_9_7807s.png'  #
inImage_1 = '/Users/libingzeng/CG/pbrt-v3/buildX/Debug/living-room/living-room_11_0_1280,720_800_9_7744s.png'  #

#inImage_1 = '/Users/libingzeng/CG/pbrt-v3/buildX/Debug/living-room/living-room_13_1_1280,720_m60_901s.png'  #
#inImage_1 = '/Users/libingzeng/CG/pbrt-v3/buildX/Debug/living-room/living-room_13_1_1280,720_m70_1191s.png'  #
#inImage_1 = '/Users/libingzeng/CG/pbrt-v3/buildX/Debug/living-room/living-room_5_1_1280,720_500_9_7898s_zlb3.png'  #
#inImage_1 = '/Users/libingzeng/CG/pbrt-v3/buildX/Debug/living-room/living-room_9_1_1280,720_310_9_6843s_again,depth+2.png'  #
#inImage_1 = '/Users/libingzeng/CG/pbrt-v3/buildX/Debug/living-room/living-room_9_2_1280,720_270_9_6645s_again,depth+2.png'  #
#inImage_1 = '/Users/libingzeng/CG/pbrt-v3/buildX/Debug/living-room/living-room_9_2_1280,720_350_9_8416s_again,depth+2.png'  #
inImage_2 = '/Users/libingzeng/CG/pbrt-v3/buildX/Debug/living-room/living-room_17_18_1_reference.png'  #


#inImage_1 = '/Users/libingzeng/CG/pbrt-v3/buildX/Debug/bathroom2/bathroom2-10_again,0_1280,720_m100_1446s.png'  #
#inImage_1 = '/Users/libingzeng/CG/pbrt-v3/buildX/Debug/bathroom2/bathroom2-10_again,0_1280,720_m140_2179s.png'  #
#inImage_1 = '/Users/libingzeng/CG/pbrt-v3/buildX/Debug/bathroom2/bathroom2-10_again,0_1280,720_m280_3805s.png'  #

#inImage_1 = '/Users/libingzeng/CG/pbrt-v3/buildX/Debug/bathroom2/bathroom2-10_again,1_1280,720_m50_1176s.png'  #
#inImage_1 = '/Users/libingzeng/CG/pbrt-v3/buildX/Debug/bathroom2/bathroom2-10_again,1_1280,720_m55_1290s.png'  #
#inImage_1 = '/Users/libingzeng/CG/pbrt-v3/buildX/Debug/bathroom2/bathroom2-10_again,1_1280,720_m60_1410s.png'  #
#inImage_1 = '/Users/libingzeng/CG/pbrt-v3/buildX/Debug/bathroom2/bathroom2-10_again,1_1280,720_m65_1520s.png'  #
#inImage_1 = '/Users/libingzeng/CG/pbrt-v3/buildX/Debug/bathroom2/bathroom2-10_again,1_1280,720_m70_1597s.png'  #
#inImage_1 = '/Users/libingzeng/CG/pbrt-v3/buildX/Debug/bathroom2/bathroom2-10_again,1_1280,720_m100_2321s.png'  #
#inImage_2 = '/Users/libingzeng/CG/pbrt-v3/buildX/Debug/bathroom2/bathroom2-9_reference.png'  #

dif_img = 'dif_' + inImage_1

img_1 = cv2.imread(inImage_1)  # read as color image
img_2 = cv2.imread(inImage_2)

dif = img_1.copy()
show_dif = dif.copy()  # dif image for show only

width = img_1.shape[0]  # get width
height = img_1.shape[1]  # get height
sum = 0

for i in range(width):
    for j in range(height):
        # dif[i, j] = [128,0,0]      # b g r
        # print img_1[i,j]-img_2[i,j]

        #diff0 = float(img_1[i, j][0]) - float(img_2[i, j][0])
        #diff1 = float(img_1[i, j][1]) - float(img_2[i, j][1])
        #diff2 = float(img_1[i, j][2]) - float(img_2[i, j][2])
        #diff = (abs(diff0) + abs(diff1) + abs(diff2)) / 3.0

        y1 = img_1[i, j][2] * 0.212671 + img_1[i, j][1] * 0.715160 + img_1[i, j][0] * 0.072169
        y2 = img_2[i, j][2] * 0.212671 + img_2[i, j][1] * 0.715160 + img_2[i, j][0] * 0.072169
        diff = y1 - y2
        diff0 = diff

        sum = sum + diff ** 2

        if diff0 < 0:
            show_dif[i, j] = [0, clmap(abs(diff0), 10, 255), 0]

        elif diff0 > 0:
            show_dif[i, j] = [0, 0, clmap(abs(diff0), 10, 255)]
        else:
            show_dif[i, j] = [0]

        dif[i, j] = abs(diff0)

mse = sum / (width * height)
print 'MSE: ', mse

print dif_img
print 'different data:'
print 'max : ', dif.max()
print 'min : ', dif.min()
print 'mean : ', dif.mean()

cv2.imwrite(dif_img, show_dif)

cv2.imshow('_dif', show_dif)
cv2.waitKey(0)
cv2.destroyAllWindows()

参考图片:
这里写图片描述

渲染图片:
这里写图片描述

输出结果
这里写图片描述

从前面程序中可以看到,可视化的是第0通道(blue)的差异。
注意:
1,程序中默认通道次序是blue、green、red(和常见的rgb次序不一样)
2,一般求三个通道的MSE的方式是:分别求每个通道的MSE,然后平均。小编的求法是:对单像素点的三个通道的差异的绝对值求平均值,然后对这个平均值平方求和,最后再平均

渲染图片和参考图片的第0通道的差异图:
(绿色:差异<0;红色:差异>0;黑色:差异=0)
这里写图片描述

猜你喜欢

转载自blog.csdn.net/libing_zeng/article/details/82534152