通过python alghoritm将方形Hald clut转换为经典Hald clut

通过python alghoritm将方形Hald clut转换为经典Hald clut,python,android,numpy,opencv,cube,Python,Android,Numpy,Opencv,Cube,我的问题是:我有一个方形Hald851x512px,我想把它转换成.CUBE文件 将正方形Hald转换为经典Hald,然后轻松转换为立方体(参见第二个算法) 图片:- 我正在尝试反转这个简单的python算法,它可以很好地转换经典Hald->Square Hald: 我们需要重塑价值观。一些想法或建议?谢谢 更新2:多亏格罗斯格勒的作者尤金·维多文,我才解决了这个问题。如果有人建议实施3D结构(可能使用numpy?),我们会接受。我对python很在行 from PIL import Ima

我的问题是:我有一个方形Hald851x512px,我想把它转换成.CUBE文件

  • 正方形Hald转换为经典Hald,然后轻松转换为立方体(参见第二个算法) 图片:-
我正在尝试反转这个简单的python算法,它可以很好地转换经典Hald->Square Hald:

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

更新2:多亏格罗斯格勒的作者尤金·维多文,我才解决了这个问题。如果有人建议实施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()
更新3:我按照建议,用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()

这是一个C++代码,它解析HALD图像的每个像素,并将其值放入3DLUT中,后者保存为立方体格式的文件。代码缺少一些东西来保持紧凑。希望这能帮助您理解索引算法,以便您可以自己在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);
}
std::字符串格式字符串(常量字符*格式,…)
{
if(Format==NULL | | Format[0]='\0')返回“”;
静态std::字符串Res;
va_列表参数;
va_开始(参数,格式);
int len=_vscprintf(格式,args);
Res.resize(len);
vsprintf((char*)Res.data(),格式,args);
va_端(args);
返回Res;
}
void convert_hald_to_cube()
{
CLUT LUT;//必须实现一个类来存储任意大小的3DLUT数据
//在这里,您可以将HALD图像数据转换为二维HALD_颜色数组
// ...
//从HALD 2D数组获取3DLUT值
int hald_side_in_像素=512;
int lutSize=(int)(powf((float)hald_side_in_像素*hald_side_in_像素,1.f/3.f)+0.5f);//+0.5f用于对正值进行舍入
int-iR,iG,iB;
int-cubeIndex=0;

对于Iy y=0;Yi在Python中复制了相同的AlgRoTIM,这很简单,但是由于一些奇怪的原因,蓝色通道不再改变最后的行,如果你有时间,请看一看谢谢。现在我尝试在C++或java上做同样的事情。也许我不能用三个数组FR、FG、FB这样。就像你使用了三个独立的1DLUT。代替一个3DLUT。必须使用单个索引访问三个RGB值,因为它们表示单个体素。可以分配lutSize**3元素的数组fr、fg、fb,但索引iR、iG、iB永远不能等于或大于lutSize。由于不使用类/结构存储3D LUT体素,因此可以在ore访问其fr、fg、fb值,如下所示:idx=iR*lutSize*lutSize+iG*lutSize+iB,然后是fr[idx]、fg[idx]、fb[idx]……非常感谢,解决了!现在我正在尝试使用numpy进行优化,以避免idx…3D阵列已创建,非常完美!再次感谢。我发布了这两种解决方案,3D阵列的速度(平均)慢250毫秒而不是索引为idx=…的3x1D数组,我认为这是因为我使用numpy库
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()
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);
}