Преобразование из файла изображения OpenEXR (Spherical Panorami c DepthMap), вызывающее преобразование Geomerty в сбой - PullRequest
8 голосов
/ 10 января 2020

Я читаю файл TiledExr следующим образом, используя C ++ и OpenEXR

std::vector<double> TiledExrDepthMapExtractor::extractDepthMap(const char* filePath,
    int& width, int& height, ProgressFunc& progressCallback, ErrorFunc& errorCallback)
{
    // Do some stuff then...
    return pixelVector;
}

Это вызывается из C#

public class ExrDepthMapExtractor : IDepthMapExtractor
{
    public RawDepthMap GetDepthMap(string filePath)
    {
        return ExtractRawDepthMap(filePath, Callbacks.ProgressCallback, Callbacks.ErrorCallback);
    }

    private unsafe RawDepthMap ExtractRawDepthMap(string filePath,
        Callbacks.ProgressFunc progressCallback, Callbacks.ErrorFunc errorCallback)
    {
        using (InternalExtractRawDepthMapWrapper(filePath, out RawDepthMap rdm, progressCallback, errorCallback))
        {
            rdm.Source = filePath;
            return rdm;
        }
    }

    private unsafe PixelVectorSafeHandle InternalExtractRawDepthMapWrapper(
        string filePath, out RawDepthMap rdm, Callbacks.ProgressFunc progressCallback, Callbacks.ErrorFunc errorCallback)
    {
        if (!NativeMethods.ExtractDepthMapAs1DArray(out PixelVectorSafeHandle pixelVectorHandle,
            out double* pixels, out int width, out int height, filePath, progressCallback))
            throw new FormatException($"Depth map could not be extracted from \"{filePath}\"");

        var pixelList = new List<double>();
        for (int i = 0; i < width * height; i++)
            pixelList.Add(pixels[i]);

        rdm = new RawDepthMap()
        {
            Source = filePath,
            DepthMapArray = pixelList,
            Height = height,
            Width = width
        };

        return pixelVectorHandle;
    }
}

Через API

[SuppressUnmanagedCodeSecurity()]
internal static class NativeMethods
{
    [DllImport("Blundergat.OpenExr.Adapter.dll", CallingConvention = CallingConvention.Cdecl)]
    [return: MarshalAs(UnmanagedType.I1)]
    internal static unsafe extern bool ExtractDepthMapAs1DArray(
        out PixelVectorSafeHandle vectorHandle,
        out double* points,
        out int width,
        out int height,
        string filePath,
        Callbacks.ProgressFunc progressCallback);

    [DllImport("Blundergat.OpenExr.Adapter.dll", CallingConvention = CallingConvention.Cdecl)]
    internal static unsafe extern bool Release(IntPtr itemsHandle);
}

и преобразуется в RawDepthMap

public class RawDepthMap
{
    public string Source { get; set; }

    public List<double> DepthMapArray { get; set; }

    public int Height { get; set; }

    public int Width { get; set; }

    public override string ToString()
    {
        string source = !String.IsNullOrEmpty(Source) ? Source : "N/A";
        StringBuilder builder = new StringBuilder($"RawDepthMap: Source \"{source}\"");
        if (DepthMapArray != null)
            builder.Append($", Array size {DepthMapArray:N0}");

        builder.Append($", Width {Width:N0}, Height {Height:N0}");
        return builder.ToString();
    }
}

Это сферическая карта глубины (это сферическое панорамное изображение), по сути, одномерный массив измерений глубины. Исходя из этого, я конвертирую в декартовое облако точек, используя

public class DepthMapToPointCloudAdapter : IDepthMapToPointCloudAdapter
{
    public DepthMapToPointCloudAdapter() { }

    public IPointCloud GetPointCloudFromDepthMap(RawDepthMap rdm)
    {
        // Do some transformations. 
        return new PointCloud(dataPoints.ToArray(), rdm.Source);
    }
}

Это дает следующее облако точек

enter image description here

Теперь мне нужно прочитать файл EXR изображения. Я делаю это снова, как описано выше, используя C ++

std::vector<double> ImageExrDepthMapExtractor::extractDepthMap(const char* filePath,
    int& width, int& height, ProgressFunc& progressCallback, ErrorFunc& errorCallback)
{
    // Do some reading... 
    return pixelVector;
}

Та же процедура преобразования в декартову PointCloud, но на этот раз я получаю сферическую геометрию.

enter image description here

Это явно связано с тем, как я читаю файл изображения (RGBA) .exr, но что именно вызывает это?

...