【问题标题】:Convert Square Hald clut to Classic Hald clut through a python alghoritm通过 python 算法将 Square Hald clut 转换为 Classic Hald clut
【发布时间】:2020-09-06 09:00:40
【问题描述】:

我的问题是:我有一个 Square Hald 8 512x512px,我想将其转换为 .CUBE 文件

  • Square Hald 转换为 Classic Hald,然后轻松转换为 CUBE(参见第二个算法) 图片:Square Hald 8 - Classic Hald 8

我正在尝试反转这个简单的 python 算法,它可以很好地转换 Classic Hald -> Square Hald:

import numpy, cv2

hald = cv2.imread("classic_hald_8.png")

size = int(hald.shape[0] ** (1.0/3.0) + .5)

clut = numpy.concatenate([
    numpy.concatenate(hald.reshape((size,size,size**2,size**2, 3))[row], axis=1)
    for row in range(size)
])

cv2.imwrite("square_hald_8.png", clut)
import imageio as iio, numpy as np
imagen=iio.imread("Classic_Hald_8.png")

r,g,b=(imagen[:,:,0]).reshape(-1), (imagen[:,:,1]).reshape(-1), (imagen[:,:,2]).reshape(-1)
np.savetxt("Classic_Hald_8.cube",X=np.column_stack((r/255,g/255,b/255)),fmt='%1.6f', header="LUT_3D_SIZE 64", comments="")

我们需要重塑价值观。一些想法或建议?谢谢

UPDATE2:感谢 GrossGrade 的作者 Eugene Vdovin,我已经解决了。如果有人建议实施 3D 结构(可能使用 numpy?),则可以接受。我对 python 很菜鸟

from PIL import Image

im = Image.open('test.png','r')
values = im.load()
hald_side_in_pixels = im.size[0]
hald_in_pixels = im.size[0]*im.size[0]
lutSize = int(hald_in_pixels ** (1.0/3.0) + .5) 

fr = [0.0]*hald_in_pixels
fg = [0.0]*hald_in_pixels
fb = [0.0]*hald_in_pixels

cubeIndex = 0
for y in range(hald_side_in_pixels):
 for x in range(hald_side_in_pixels):
  iR = cubeIndex % lutSize
  iG = y % lutSize
  iB = int(x/lutSize)+(int(y/lutSize)*int(hald_side_in_pixels/lutSize))
  idx = iR * lutSize * lutSize + iG * lutSize + iB
  fr[idx],fg[idx],fb[idx] = values[x,y]  
  cubeIndex+=1


with open("test.cube", "w") as output:
 output.write("DOMAIN_MIN 0 0 0\nDOMAIN_MAX 1 1 1\nLUT_3D_SIZE " + str(lutSize) + '\n')
 for iB in range(lutSize):
  for iG in range(lutSize):
   for iR in range(lutSize):
    idx = iR * lutSize * lutSize + iG * lutSize + iB
    output.write((str("%.9f" % (fr[idx]/255)) + ' ' +  str("%.9f" % (fg[idx]/255)) + ' ' + str("%.9f" % (fb[idx]/255)))+ '\n')
output.close()

UPDATE3:我已经按照建议,我用 numpy 创建了一个 3D 数组,现在它更干净了,但是它比 3x 1D 数组慢了大约 150 毫秒,我发布了代码

from PIL import Image
import numpy as np

im = Image.open('test.png','r')
values = im.load()
hald_side_in_pixels = im.size[0]
lutSize = int((hald_side_in_pixels*hald_side_in_pixels) ** (1.0/3.0) + .5)

LUT = np.empty((lutSize,lutSize,lutSize), dtype=bytearray)
cubeIndex = 0
for y in range(hald_side_in_pixels):
 for x in range(hald_side_in_pixels):
  iR = cubeIndex % lutSize
  iG = y % lutSize
  iB = int(x/lutSize)+(int(y/lutSize)*int(hald_side_in_pixels/lutSize))
  LUT[iR,iG,iB]=values[x,y]
  cubeIndex+=1


with open("test1.cube", "w") as output:
 output.write("DOMAIN_MIN 0 0 0\nDOMAIN_MAX 1 1 1\nLUT_3D_SIZE " + str(lutSize) + '\n')
 for iB in range(lutSize):
  for iG in range(lutSize):
   for iR in range(lutSize):
    output.write((str("%.9f" % (LUT[iR,iG,iB][0]/255)) + ' ' +  str("%.9f" % (LUT[iR,iG,iB][1]/255)) + ' ' + str("%.9f" % (LUT[iR,iG,iB][2]/255)))+ '\n')
output.close()

【问题讨论】:

    标签: python android numpy opencv cube


    【解决方案1】:

    这是解析 HALD 图像的每个像素并将其值放入 3DLUT 的 C++ 代码,稍后将其保存到 CUBE 格式的文件中。代码缺少一些东西来保持一切紧凑。希望这将帮助您了解索引算法,以便您可以自己在 python 中实现它。

    std::string formatstring(const char *Format, ...)
    {
        if(Format == NULL || Format[0] == '\0') return "";
        static std::string Res;
        va_list args;
        va_start(args, Format);
        int len = _vscprintf(Format, args);
        Res.resize(len);
        vsprintf((char*)Res.data(), Format, args);
        va_end(args);
        return Res;
    }
    
    void convert_hald_to_cube()
    {
        CLUT LUT; // you must implement a class to store 3DLUT data of any size
    
        // Here you getting your HALD image data into a 2D-array hald_colors
        // ...
    
        // Getting 3DLUT values from a HALD 2D-array
        int hald_side_in_pixels = 512;
        int lutSize = (int)(powf((float)hald_side_in_pixels*hald_side_in_pixels,1.f/3.f)+0.5f); // +0.5f is for rounding a positive value
        int iR,iG,iB;
        int cubeIndex = 0;
        for(int y=0; y<hald_side_in_pixels; ++y) 
        {
            for(int x=0; x<hald_side_in_pixels; ++x)
            {
                iR = cubeIndex % lutSize;
                iG = y % lutSize;
                iB = (x/lutSize)+((y/lutSize)*(hald_side_in_pixels/lutSize));
                            
                // Here you copy the hald_colors[x][y] color value to the 3DLUT voxel value at indexes {iR,iG,iB}
                            
                cubeIndex++;
            }
        }
    
        // Putting 3DLUT values to a CUBE file
        FILE *f = fopen("OutputCubeFile.cube", "w+");
        fputs("TITLE my cube file\n",f);                        
        fputs("DOMAIN_MIN 0 0 0\n",f);
        fputs("DOMAIN_MAX 1 1 1\n",f);
        std::string s = "LUT_3D_SIZE " + std::to_string((_ULonglong)lutSize) + "\n";
        fputs(s.c_str(),f);
        for(int iB=0; iB<lutSize; ++iB) 
        {
            for(int iG=0; iG<lutSize; ++iG) 
            {
                for(int iR=0; iR<lutSize; ++iR) 
                {
                    float fr,fg,fb;
                    
                    // Here you copy the 3DLUT voxel value at indexes {iR,iG,iB} to the values fr,fg,fb
                    
                    std::string outputvalues = formatstring("%.9f %.9f %.9f\n",fr,fg,fb); 
                    fputs(outputvalues.c_str(),f);
                }
            }
        }
        fclose(f);
    }
    

    【讨论】:

    • 我已经在 python 中复制了相同的算法,这很容易,但由于某些奇怪的原因,蓝色通道不再更改最后几行,如果你有时间看看谢谢。现在我正在尝试在 C++ 或 Java 上做同样的事情,也许我会很幸运
    • 不能这样使用三个数组fr,fg,fb。这就像您使用三个独立的 1DLUT 而不是一个 3DLUT。必须使用单个索引访问三个 RGB 值,因为它们代表单个体素。您分配 lutSize**3 个元素的数组 fr,fg,fb,但索引 iR,iG,iB 永远不能等于或大于 lutSize。由于您不使用类/结构来存储 3D LUT 体素,因此您可以在访问其 fr、fg、fb 值之前计算每个体素的索引,如下所示:idx = iR * lutSize * lutSize + iG * lutSize + iB然后是 fr[idx],fg[idx],fb[idx]...
    • 非常感谢,已解决!现在我正在尝试使用 numpy 进行优化以避免 idx...
    • 3D 阵列已创建,非常完美!再次感谢。我已经发布了这两个解决方案,3D 数组比 3x1D 数组慢 250ms(平均)索引 idx=... 我想是因为我使用 numpy 库
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-27
    • 1970-01-01
    • 1970-01-01
    • 2022-12-03
    • 2011-07-26
    相关资源
    最近更新 更多