unity图像处理

unity图像处理

图像处理API

  • Graphics

    • Blit
      纹理通过材质渲染到目标,纹理设为材质的 _MainTex 属性
      将 dest 设置为渲染目标,为null时直接渲染到屏幕,使用后RenderTexture.active变成dest
      该操作在GPU上复制纹理,速度很快
      在 android 上如果不生效,尝试创建 RenderTexture 时深度值设为0
      Blit是纹理操作,所有参数都是针对纹理坐标,scale 和 offset 用来设置uv偏移和缩放,
      target 上的纹理坐标uv的颜色 color=texture(sourceTexture,uv*scale+offset)

      • 比如 上下颠倒
        Blit(screen, target, new Vector2(1f, -1f), new Vector2(0f,1f));
      • 比如 截取原纹理的 (x,y,w,h) 区域,值都是百分比的形式,比如 (0.2,0.2,0.6,0.6)
        Blit(screen, target, new Vector2(w,h), new Vector2(x,y));
    • ConvertTexture
      在不同格式和尺寸的纹理之间进行转换的有效方式,可以理解为直接对纹理数据进行加工,因此源和目标都是 Texture2D
      注意 Blit 目标是 RenderTexture
      ConvertTexture 对目标格式也有要求,必须是 RenderTarget 支持的格式,目前只测出支持 ARBG32
      请注意,由于 API 限制,DX9 或 Mac+OpenGL 中不支持此函数

    • CopyTexture
      高效复制,大小必须相同,格式必须兼容
      不是所有平台都支持,必须先用 SystemInfo.copyTextureSupport 检测是否支持
      如果源和目标纹理都标记为“可读”(即系统内存中存在 用于 CPU 读取/写入的数据副本),这些函数也将复制它
      否则只复制gpu数据

    • DrawMesh 绘制网格,只是提交到渲染队列

    • DrawTexture 在屏幕坐标系中绘制纹理,只能在OnGUI以及之后的生命周期方法中调用,否则无法显示。

    • SetRenderTarget 设置当前渲染目标

    • preserveFramebufferAlpha 渲染缓存保存alpha值

  • Texture2D

    • ReadPixels
      读取屏幕缓存到Texture2D,该函数从GPU上读取像素到CPU,比较耗时
      如果先设置 RenderTexture.active=XXX; 则读取的就是 XXX 这个 RenderTexture
      如果只是用来获取像素数据,不需要渲染,则不要调用 Texture2D.Apply ,因为Apply把像素数据从CPU上传到GPU,很耗时
      如果要用来渲染,则要调用 Texture2D.Apply
      该函数按像素拷贝,不会进行图像缩放,所有参数都是以像素为单位,[0,0] 表示左下
      不适合大分辨率的录屏操作,会卡,因为不能在GPU端缩放完再读回CPU
      可以用 ScreenCapture.CaptureScreenshotIntoRenderTexture
    • EncodeToPNG 编码成图像文件格式
    • EncodeToJPG
  • ImageConversion 图像编解码

    • EncodeToPNG
    • EncodeToJPG
    • UnsafeEncodeNativeArrayToPNG
    • UnsafeEncodeNativeArrayToJPG
  • RenderTexture 只包含GPU上的数据,要获取cpu上的数据(比如像素字节数组),需要使用 Texture2D.ReadPixels 从 GPU 传到 CPU

  • ScreenCapture 截屏

    • CaptureScreenshot 截屏保存成png
    • CaptureScreenshotAsTexture 截屏保存成 Texture2D
    • CaptureScreenshotIntoRenderTexture
      • 截屏保存成 RenderTexture,速度非常快,因为是GPU传到GPU,
      • 由于数据存在GPU,可以非常方便的对图像进行操作,比如用 Blit 进行缩放,
      • 截取黑屏,或无数据,参考 截屏常见问题
      • 由于截取的图是上下颠倒的,因此颠倒回来 Graphics.Blit(screen, target, new Vector2(1f, -1f), new Vector2(0f,1f));
      • 如果用 Texture2D.ReadPixels 截屏再缩放,则要先从GPU传到CPU,再从CPU传到GPU,效率会非常低
  • WebCamTexture
    捕获手机相机画面,可以参考 OpenCVForUnity\org\opencv\unity\helper\WebCamTextureToMatHelper.cs

  • GraphicsFormatUtility 格式转换

    • GetGraphicsFormat 把 TextureFormat 或 RenderTextureFormat 转成 GraphicsFormat
    • GetRenderTextureFormat 把 graphicsFormat 转成 RenderTextureFormat
    • GetComponentCount 获得图像通道数

图像格式转换

  • TextureFormat 转 GraphicsFormat
    GraphicsFormatUtility.GraphicsFormat
  • GraphicsFormat 转 RenderTextureFormat
    GraphicsFormatUtility.GetRenderTextureFormat

计算图像通道数

图像处理的一般流程

  • 渲染到 RenderTexture
    使用 Graphics.Blit
    或者 设置 Camera.targetTexture 然后调用 Camera.Render()
  • 用 RenderTexture 生成 Texture2D
    使用 Texture2D.ReadPixels
  • 将 Texture2D 保存成文件或设置给 RawImage 进行显示
    使用 Texture2D.EncodeToPNG
  • 截屏
    使用 Texture2D.ReadPixels(慢) 或 ScreenCapture.CaptureScreenshotIntoRenderTexture(快)

动态创建材质

	//	shaderName 是可以在任何材质的着色器弹出窗口中看到的名称,例如“Standard”、“Unlit/Texture”、“Legacy Shaders/Diffuse”等
	//	场景中必须有对象引用了着色器,否则着色器有可能缺失
	//	可以直接把着色器添加到 ProjectSettings->Graphics->Built-in Shader Settings->Always included shaders
	//	如果只是某个平台用,可以加到 ProjectSettings->Player->Android->Other Settings->PreloadAssets
	Shader shader = Shader.Find(shaderName);	
	Material material = new Material(shader);

创建RenderTexture

	public static RenderTexture CreateRenderTexture(int width, int height, int depth = 24, 
		RenderTextureFormat format = RenderTextureFormat.ARGB32, bool usequaAnti = true)
	{
   
		var rt = new RenderTexture(width, height, depth, format);
		rt.wrapMode = TextureWrapMode.Clamp;
		if (QualitySettings.antiAliasing > 0 && usequaAnti)
		{
   
			rt.antiAliasing = QualitySettings.antiAliasing;
		}
		rt.Create();
		return rt;
	}

	RenderTexture rt = CreateRenderTexture(1024,720,24,RenderTextureFormat.ARGB32);
	//	如果是临时使用,经常使用
	RenderTexture renderTexture = RenderTexture.GetTemporary(texture2D.width, texture2D.height);
	//	使用 renderTexture 后释放
	RenderTexture.ReleaseTemporary(renderTexture);

RenderTexture 和 Texture2D 互转

RenderTexture 代表GPU纹理,Texture2D 代表CPU纹理,当要操作纹理时使用 RenderTexture 更快,当要操作数据时使用 Texture2D
  • RenderTexture 转 Texture2D

    1. 方法一:

      	Texture2D tex = new Texture2D(renderTexture.width, renderTexture.height, TextureFormat.RGB24, false);
      	var prevActive = RenderTexture.active;
      	RenderTexture.active = renderTexture;
      	
      	// ReadPixels 读取当前渲染目标某个区域的像素并写入 tex 中,[0,0] 表示左下
      	tex.ReadPixels(new Rect(0, 0, renderTexture.width, renderTexture.height), 0, 0);
      	//	Apply 把纹理数据上传给GPU,如果这个纹理只是用来获取像素数据,不需要渲染,则不要调用该函数,因为很耗时
      	tex.Apply();
      	
      	RenderTexture.active = prevActive;
      
    2. 方法二:

      	renderTexture.enableRandomWrite = true;
      	Texture2D tex = new Texture2D(renderTexture.width, renderTexture.height, TextureFormat.RGB24, false);
      	Graphics.ConvertTexture(renderTexture, tex);  //RT要enableRandomWrite,T2D要关闭mipmap,否则报错误
      
  • Texture2D 转 RenderTexture

    	//	如果只是临时使用,用这个效率更高
    	RenderTexture renderTexture = RenderTexture.GetTemporary(texture2D.width, texture2D.height);
    	RenderTexture prev = RenderTexture.active;
    	RenderTexture.active = renderTexture;
    	Graphics.Blit(texture2D, renderTexture);
    	RenderTexture.active = prev;
    	RenderTexture.ReleaseTemporary(renderTexture);
    

获取 RenderTexture 图像数据

	//	RenderTexture 数据是在 GPU 上,要获取数据必须先传到 cpu 上
	byte[] pixelBuffer = new byte[renderTexture.width *
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值