文章不长,请耐心看完。会有收获~~~~~~~~~~~~~~~~~~~~~~~
简介:
SFM(Shape From Move),SFS(Shape from Shading),SFP(Shape From Polarization)等技术均是三维重建常用的方法,但是无论选择哪一种技术,在三维重建的过程中都无法避免法线。而为了更好的存储与纹理移植,法线贴图应运而生。
法线贴图存储法线的形式为:RGB通道分别存储法线的XYZ轴坐标,即将物体表面某一点的向量信息保存至图像通道中。
由于我是做SFP的,以下为三个具有代表意义的数据集:
文1提出了真实场景下环境的偏振数据集(含真实法线)
文1:export.arxiv.org/pdf/2112.11377.pdf
代码1:GitHub - ChenyangLEI/sfp-wild: [CVPR2022] Shape from Polarization for Complex Scenes in the Wild
文2提出利用深度学习解决偏振法线歧义性,并公布纹理较简单的小物体数据集(含真实法线)
文2:ecva.net/papers/eccv_2020/papers_ECCV/papers/123690545.pdf
代码2:GitHub - UCLA-VMG/DeepSfP
数据集2:https://drive.google.com/file/d/1EtjfMTfpanJotH92GFz300X_ZEmGXuqr/view
文3为清华大学团队公布的透明物体偏振数据集(含真实法线)
文3:arxiv.org/pdf/2208.11836.pdf
数据集3:https://cloud.tsinghua.edu.cn/f/2feaea15e9094941b4bd/?dl=1
那么,这些数据集中的法线贴图真实值是如何得到的呢?博主对网上现有的法线贴图获取方式进行了一个汇总。
法线贴图获取方式
网上现有的法线贴图获取方式,可分为以下四类:
1.一种说法,利用blender、3dmax等三维建模软件,进行高模、低模等操作,最后烘培出出法线贴图。如果你想尝试一下的话,可以参考以下贴。
Blender法线贴图(贴1)
(34条消息) blender烘焙法线贴图_blender 法线贴图_danad的博客-CSDN博客
3dmax法线贴图(贴2)
(34条消息) 什么是法线贴图 今天教你如何制作法线贴图_法线图_langgesanshiyi的博客-CSDN博客
但是,很可惜。贴1对法线贴图的制作描述的貌似不是很清晰,而贴2中有的图像看不到。
2.利用ps,对图像进行法线贴图操作,这种方法的效果更倾向于sobel边缘检测出来的结果(边缘轮廓特别明显,但是物体表面较平扁)。但是,Ps对于法线贴图的制作仍具有最高的兼容性,因为ps可打开多种格式。下图为Ps中的结果图,从左至右分别为高度图,高度结果法线图,强度图,强度结果法线图。
具体实现可参考以下贴(34条消息) Shader Graph2-使用PS生成正确的法线贴图_ps生成法线图_艺菲的博客-CSDN博客
(34条消息) 如何通过Photoshop根据纹理贴图轻松获得法线贴图_如何通过纹理生产人物法线_qq_21315789的博客-CSDN博客
3.利用normal在线生成法线贴图,这个网站的功能还是很强的。它可以根据高度图生成相应的法线贴图,但是经对比,它与真实值之间仍存在一定的差距。单不可否认,这个网站还是有很大的实用性。注意该网站支持的图像为高度图获取法线图,而输入强度图像时效果较差。下面是博主在该网站上进行测试的结果图
具体实现可参考以下贴:(34条消息) 一个免费在线法线贴图生成器(Normal Map Generator)_在线转法线_开发游戏的老王的博客-CSDN博客
4.经测试,unity在得到法线贴图时,其效果优于以上三种方法。它的具体操作步骤如下:
首先,我们输入的是强度图像,它是2d的。其次,我们将它拖拽至assets中并左键单击,可以在inspector(检查器)中找到texture type选择normal map 。最后,单击右下角apply。下面是输入为强度图像的结果图,从左至右分别为强度图,不选取gray,选取gray。
下面是输入为高度图时的结果图,从左至右分别为强度图,不选取gray,选取gray,数据集中真实法线贴图(已mask)。
可以看出,当输入为高度图,且选择gray时,得到的法线贴图与数据集中的真实值最为相似。
最后,我们对于同一张高度图像,进行了ps、normal在线网站、unity之间的对比。可以看出,在unity中得到的法线贴图最符合物体表面,且结果具有表面突出信息。下面从左到右分别为高度图、ps结果图、normal在线网站结果图、unity结果图、数据集中真实法线图。
unity不支持将法线贴图直接导出为png格式,当我们直接对法线贴图进行截图时,得到的图像会被压缩,所以将纹理法线导出为png格式仍被需要。下面是利用C#联合unity实现将法线贴图导出为png格式的代码。
首先,我们需要在菜单栏下windows里面新增一个名为‘Normal Map Exporter ’的按钮。
实现这一功能的代码为
GUILayout.Label("Normal Map Exporter", EditorStyles.boldLabel); // 在编辑器窗口中显示标题
其次,点击此按钮会弹出如下界面。
将图像托至红框处,在点击‘Export as PNG’ 便可弹出对话框保存至本地。实现这个功能的代码如下
normalMapTexture = (Texture2D)EditorGUILayout.ObjectField("Normal Map Texture", normalMapTexture, typeof(Texture2D), false); // 在编辑器中创建一个字段,用于选择法线贴图纹理
if (GUILayout.Button("Export as PNG")) // 在编辑器中创建一个按钮,点击时触发导出操作
。。。。。。。。。。
在点击‘Export as PNG’时会进行,读取纹理法线的相关操作,代码如下
if (GUILayout.Button("Export as PNG")) // 在编辑器中创建一个按钮,点击时触发导出操作
{
if (normalMapTexture != null) // 检查是否已选择法线贴图
{
string texturePath = AssetDatabase.GetAssetPath(normalMapTexture); // 获取法线贴图在项目中的路径
Debug.Log("Texture Path: " + texturePath);
TextureImporter textureImporter = (TextureImporter)AssetImporter.GetAtPath(texturePath); // 获取法线贴图的导入器
// 检查纹理是否已设置为法线贴图类型
if (textureImporter.textureType != TextureImporterType.NormalMap)
{
textureImporter.textureType = TextureImporterType.NormalMap; // 将纹理类型设置为法线贴图
textureImporter.SaveAndReimport(); // 保存和重新导入纹理
}
// 将颜色空间设置为线性
textureImporter.sRGBTexture = false;
textureImporter.SaveAndReimport();
// 创建一个临时的RenderTexture
RenderTexture renderTexture = RenderTexture.GetTemporary(normalMapTexture.width, normalMapTexture.height, 0, RenderTextureFormat.Default, RenderTextureReadWrite.Linear);
Graphics.DrawTexture(new Rect(0, 0, renderTexture.width, renderTexture.height), normalMapTexture);
RenderTexture previous = RenderTexture.active;
RenderTexture.active = renderTexture;
// 创建一个Texture2D用于导出
Texture2D exportTexture = new Texture2D(normalMapTexture.width, normalMapTexture.height, TextureFormat.RGBA32, false);
exportTexture.ReadPixels(new Rect(0, 0, renderTexture.width, renderTexture.height), 0, 0);
Debug.LogWarning("exportTexture:"+ exportTexture); // 若未选择法线贴图,输出警告信息
exportTexture.Apply();
RenderTexture.active = previous;
RenderTexture.ReleaseTemporary(renderTexture);
弹出的保存图像窗口为
注意,保存图像的路径应为Assets下。实现的相关代码为
// 将Texture2D保存为PNG
byte[] bytes = exportTexture.EncodeToPNG();
string path = EditorUtility.SaveFilePanel("Export Normal Map", "", "NormalMap.png", "png"); // 弹出文件保存对话框,选择保存路径和文件名
if (!string.IsNullOrEmpty(path))
{
System.IO.File.WriteAllBytes(path, bytes);
AssetDatabase.Refresh(); // 刷新资源数据库,使新的PNG文件在项目中可见
Debug.Log("Normal Map exported as PNG: " + path); // 在控制台输出导出路径
代码可在这里直接下载(35条消息) 【免费】unity中将法线贴图导出png格式的代码,可直接运行C#实现非截图!!!截图会压缩图像质量资源-CSDN文库
如有不正之处,欢迎指出。
同时欢迎关注,下一步尝试由三维模型的某一视角得出高度图。