将Texture2D转换为OpenCV Mat?

3

有一个与在Unity中将OpenCV的cv::Mat转换为Texture2D有关的帖子,我提供了一个有效的答案。现在,我想尝试相反的过程,但已经卡在这里几个小时了。

我想将Unity的Texture2D转换为OpenCV的cv::Mat,以便可以在C++端处理纹理。

这是我想要转换为cv:Mat的Unity项目中的原始Texture2D:

enter image description here

这是将其转换为cv:Mat后的样子:

enter image description here

它看起来非常苍白。 我不担心图像的旋转。我可以修复那个。只是想知道为什么它看起来这么苍白。还使用cv::imwrite保存图像进行测试,但问题也存在于保存的图像中。

C# 代码:

[DllImport("TextureConverter")]
private static extern float TextureToCVMat(IntPtr texData, int width, int height);

unsafe void TextureToCVMat(Texture2D texData)
{
    Color32[] texDataColor = texData.GetPixels32();
    //Pin Memory
    fixed (Color32* p = texDataColor)
    {
        TextureToCVMat((IntPtr)p, texData.width, texData.height);
    }
}

public Texture2D tex;

void Start()
{
    TextureToCVMat(tex);
}

C++ 代码:

DLLExport void TextureToCVMat(unsigned char*  texData, int width, int height)
{
    Mat texture(height, width, CV_8UC4, texData);

    cvNamedWindow("Unity Texture", CV_WINDOW_NORMAL);
    //cvResizeWindow("Unity Texture", 200, 200);
    cv::imshow("Unity Texture", texture);
    cv::imwrite("Inno Image.jpg", texture);
}

我还尝试在C++端创建一个结构体来保存像素信息,而不是使用unsigned char*,但结果仍然是相同的。
struct Color32
{
    uchar r;
    uchar g;
    uchar b;
    uchar a;
};


DLLExport void TextureToCVMat(Color32* texData, int width, int height)
{
    Mat texture(height, width, CV_8UC4, texData);

    cvNamedWindow("Unity Texture", CV_WINDOW_NORMAL);
    cvResizeWindow("Unity Texture", 200, 200);
    cv::imshow("Unity Texture", texture);
}

为什么图像看起来这么失真,如何解决?


我脑海中想到的唯一方法就是传递一组参数给 imwrite 函数,例如 std::vector<int> params; params.push_back(CV_IMWRITE_JPEG_QUALITY); params.push_back(100); 然后调用 imwrite 函数。 - mutantkeyboard
1
@mutantkeyboard 注意,我不在乎 imwrite。我只是用它来调试图像,并找出为什么它会显示成那样。如果 cv::imshow 也失败了,cv::imwrite 也应该失败。我刚刚尝试过了,问题仍然存在,但是感谢你的建议。 - Programmer
1
OpenCV默认创建图像为BGRA格式,而Color32格式为RGBA。使用cv::cvtColor函数将其转换为RGBA格式。 - zindarod
1
@zindarod 但他已经有了CV_8UC4,这是一个4通道8位矩阵。我认为它是RGBA格式的。我不知道你是否尝试过伽马校正 @Programmer - mutantkeyboard
2
在您的C++代码中,执行以下操作:cv::cvtColor(texture,texture,cv::COLOR_BGRA2RGBA)。正如您所说的Texture2D.format提供了RGB24,因此在您的情况下,Alpha通道并不重要。 - zindarod
显示剩余2条评论
1个回答

7

OpenCV 默认创建的图像格式为BGR,而 Color32 则将像素存储为RGBA。不过,由于 OP 在评论中提到 Texture2D.format 的纹理格式为RGB24,我们可以完全忽略 alpha 通道。

DLLExport void TextureToCVMat(unsigned char*  texData, int width, int height)
{
    Mat texture(height, width, CV_8UC4, texData);
    cv::cvtColor(texture,texture,cv::COLOR_BGRA2RGB);

    cv::imshow("Unity Texture", texture);
    cv::waitKey(0);
    cv::destroyAllWindows();

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接