Compose使用OpenGL+CameraX快速实现相机“拍视频实时滤镜“、”拍照+滤镜“

用CameraX实现抖音式特效相机:美颜+滤镜+实时分析的完整代码实现 本文详细介绍了如何使用CameraX构建具备商业化水准的特效相机,涵盖从基础架构到高级功能的完整技术方案。通过实时美颜引擎、动态滤镜系统和性能调优等实践,帮助开发者实现抖音式特效相机的完整代码实现,提升短视频应用的用户体验。 阅读详情

一、前言

短视频热潮还没有褪去,写这篇文章主要是帮助大部分人,能快速上手实现类似效果,实际上是: CameraX拿相机数据,OpenGL给CameraX提供一个Surface,数据放到OpenGL渲染的线程上去做图像相关操作

OpenGL滤镜来自aserbao_AndroidCamera

视频录制核心代码参考改造自Google的grafika里面的部分代码,感兴趣的小伙伴,可以细读哦。

注意:文章末尾会贴上本篇文章的最终源代码地址,和快手,小红书视频录制效果一样。


GIF压缩失真了,请前往文章末尾下载源码体验

网上有很多,将解OpenGL的文章内容,同样的也很少有文章教大家如何去快速集成实现,大多数文章,上来就是一大篇和别的文章雷同的基础知识点讲解,容易看睡着,对于没有这方面基础的同学很难啃。

二、CameraX拍照的问题

1. CameraX去拍照片:默认图片质量大(可调整),但是:拍照数据返回慢。

2. 没有什么用的CameraX拓展:这玩意并不适合我们,没有这个拓展就用不了,那要这个拓展有什么用。

3. 拍视频并不能用ImageAnalysis做滤镜,拍照片可以用ImageAnalysis做滤镜效果

三、自定义GLTextureView

我编写一个GLCameraView方便支持我们的Activity动画打开。

因为我们要给CameraX提供surfaceProvider,所以我们需要实现SurfaceProvider接口

class GLCameraView(context: Context, private val ratio: Float) : GLTextureView(context), SurfaceProvider {
    override fun onSurfaceRequested(request: SurfaceRequest) {
        val resetTexture = resetPreviewTexture(request.resolution) ?: return
        val surface = Surface(resetTexture)
        request.provideSurface(surface, executor) {
            surface.release()
            if(!fromCameraLensFacing) {
                // 注意:切换前置和后置摄像头的时候,不能release surfaceTexture
                surfaceTexture?.release()
            }
        }
    }
    // 其他细节,可以直接用我们文章末尾的源码
}

根据方法提供的参数设置SurfaceTexture#setDefaultBufferSize,然后用surfaceTexture创建一个Surface,将它提供给SurfaceRequest

后面我们结合CameraX的时候就可以把GLCameraView传给Preview#setSurfaceProvider

四、CameraX + GLCameraView预览

1. 提供一个getCameraProvider()将相机的生命周期绑定到 LifecycleOwner

private suspend fun Context.getCameraProvider(): ProcessCameraProvider =
    suspendCoroutine { continuation ->
        ProcessCameraProvider.getInstance(this).also { cameraProvider ->
            cameraProvider.addListener(
                {
                  continuation.resume(cameraProvider.get())
                }, ContextCompat.getMainExecutor(this)
            )
        }
    }

2. 配置相机视图

@Composable
fun CameraXView(
    modifier: Modifier,
    lensFacing: Int,
    content: @Composable (GLCameraView) -> Unit
) {
    val context = LocalContext.current
    val lifecycleOwner = LocalLifecycleOwner.current

    val glCameraPreview = remember {
        // 配置9:16
        GLCameraView(context, 9 / 16F)
    }
    val scope = remember {
        CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate)
    }
    LaunchedEffect(lensFacing) {
        val cameraProvider = context.getCameraProvider()
        // 解除生命周期绑定,并从 CameraX 中移除
        cameraProvider.unbindAll()

        val preview = Preview.Builder().apply {
            // 设置成9:16
            setTargetAspectRatio(AspectRatio.RATIO_16_9)
        }.build()

        // 需要在preview.setSurfaceProvider前面调用
        glCameraPreview.switchCameraLensFacing(true,lensFacing)
        preview.setSurfaceProvider(glCameraPreview)

        // 设置前置、后置摄像头切换
        val cameraSelector = CameraSelector.Builder()
            .requireLensFacing(lensFacing)
            .build()
            
        kotlin.runCatching {
            cameraProvider.bindToLifecycle(
                lifecycleOwner,
                cameraSelector,
                preview
            )
        }
    }
    Box(...) {
        DisposableEffect(
            AndroidView(
                factory = { glCameraPreview },
                modifier = Modifier.fillMaxSize()
            )
        ) {
            onDispose {
                scope.launch {
                   glCameraPreview.switchCameraLensFacing(false,lensFacing)
                   val cameraProvider = context.getCameraProvider()
                   // 解除生命周期绑定,并从 CameraX 中移除
                   cameraProvider.unbindAll()
                }
            }
        }
        content(glCameraPreview)
    }
}

从上面的代码片段中,我们可以看到以下内容:

  1. 初始化ProcessCameraProvider的实例,将相机的生命周期绑定到LifecycleOwner。
  2. LaunchedEffect(lensFacing) 只有切换前置/后置摄像头会触发里面的逻辑,需要调用cameraProvider.unbindAll() 解除生命周期绑定,并从 CameraX 中移除。
  3. 初始化Preview设置surfaceProvider,这里需要注意的是调用切换摄像头方向的方法需要在setSurfaceProvider前面调用。
  4. 通过CameraSelector构建切换的前置/后置摄像头。
  5. 调用cameraProvider.bindToLifecycle。
  6. 在AndroidView的factory里面返回我们的glCameraPreview。
  7. 在onDispose里面我们需要调用cameraProvider.unbindAll()解除生命周期绑定,并从 CameraX 中移除。

五、CameraXView三方app如何使用

上面我们给出了CameraXView的实现,我们在content: @Composable (GLCameraView) -> Unit 这里面可以放我们的拍照/拍视频/其他菜单视图,如果是拍视频,需要控制slideGpuFilterGroupEnable,没有拍摄视频前,可以水平切换滤镜,拍摄中是不可以切换的。

1. 拍摄视频用法:

CameraXView(
    modifier = modifier,
    lensFacing = lensFacingProvider()
) { glCameraPreview ->
    LaunchedEffect(recordingStateProvider()) {
       if (null != recordingStateProvider()) {
          // 拍视频
          glCameraPreview.takeVideo(videoRecordingFileUri?.path ?: "")
       }
       // 为null的状态,才可以滑动切换滤镜
       glCameraPreview.slideGpuFilterGroupEnable = (recordingStateProvider() == null)
   }
   
   // TakeVideoOptionsBar里面显示的视频拍摄的时间
   val recordingTimeState = glCameraPreview.getRecordingTimeState().collectAsState()

   TakeVideoOptionsBar(
       // 用于控制里面按钮状态
       recordingState = recordingStateProvider(),
       // 视频拍摄时长(实时的,单位:分钟:秒:毫秒)
       recordingTime = recordingTimeState.value,
       onTakeVideo = {
           // 回调当前状态,再根据viewModel返回的state去做ui数据展示
           onTakeVideoClick.invoke(glCameraPreview.isRecording())
       },
       ....
    )
}

2. 拍照片用法:

CameraXView(
  modifier = modifier,
  lensFacing = lensFacingProvider()
) { glCameraPreview ->
    TakePhotoOptionsBar(
        onTakePhoto = {
            // OpenGL里面去取一帧图片数据,这个数据是秒生成的
            glCameraPreview.takePicture(takePictureFileUri?.path ?: "")
            // 直接通知ViewModel播放一个“快门声音”,并打开需要接收照片数据的页面
            currentOnTakePhotoClick.invoke()
        }
    )
}

这里再插一段,怎么播放快门声音,这里给大家介绍一下:
Ringtone
提供了一种快速播放铃声、通知或其他类似类型声音的方法,我们可以看到官方文档里面提示我们去看RingtoneManager,当然,你也可以用SoundPool

我们在RingtoneManager找到getRingtone可以根据音频文件的Uri返回一个Ringtone,然后可以拿Ringtone#play去播放一段音频,还没结束,我们还需要配置一下音频属性AudioAttributes:

AudioAttributes.Builder().setUsage(...).build()

我们可以看到AudioAttributes.Builder#setUsage,有下面这么多usage可配置

篇幅问题,更多细节,大家可以仔细查看官方的文档,这里我们用的是:AudioAttributes.USAGE_MEDIA

当使用是媒体(如音乐或电影配乐)时使用的值

所以:只要我们的设备播放音乐或者视频能听到声音,那么我们这个快门播放也同样可以听到声音。

从上面的用法,我们可以看出:

  1. 可以在CameraXView的content: @Composable (GLCameraView) -> Unit 这里面放我们相机页面的其他菜单和操作视图。
  2. 拍照基本上是秒生成返回图片数据,比CameraX直接去拍照快的不止一点两点。
  3. 照片和视频都支持水平滑动切换滤镜,同样,外部可以通过当前拍摄视频状态,来控制“水平滑动切换滤镜”功能是否可用。
  4. 拍照完成有快门声音播放。

六、处理grafik视频保存问题

无论是AndroidCamera还是grafika它们两个用的都是同一套视频录制方法,同样的在源码中一开始注释的内容是:

// We don't know when these will actually finish (or even start). 
// We don't want to delay the UI thread though, so we return immediately.

很显然,它并不知道这些何时会真正完成,那么怎么去解决呢?

点击停止录制的时候,肯定需要找到stopRecording对吧,我们进这里面看看

这个骚操作,我们得治治,我们先调用:

mHandler.sendMessage(mHandler.obtainMessage(MSG_QUIT))

然后再直接调用handleStopRecording方法,这里需要注意:

需要将耗时操作移动到gl线程外面,否则OpenGL ES所在的线程被阻塞或者被挂起,导致渲染设备上下文丢失(直接表现就是:画面不会再动,无法继续绘制)

切记切记!!

所以这里我们可以放在子线程里面去执行handleStopRecording方法。

我们稍微修改了一下handleStopRecording方法里面的内容

private fun handleStopRecording() {
        Log.d(TAG, "handleStopRecording")
        kotlin.runCatching {
            mVideoEncoder?.drainEncoder(true)
        }
        mVideoEncoder?.stopAudRecord()
        releaseEncoder()
}

我们可以看到多了一个try/catch,为什么?drainEncoder方法的注释中写到它:

从编码器中提取所有待处理的数据并将其转发到复用器

CameraDrawer#onDrawFrame,系统会在每次重新绘制GLTextureView时调用此方法。
然后会触发我们的TextureMovieEncoder#handleFrameAvailable:

这里我们针对上面红色框区域的代码做调整:

强行停止结束,会导致drainEncoder被异常终止,需要捕获一下异常,如果发现异常同样需要停止后面的代码执行。

我们在TextureMovieEncoder里面看到fun handleFrameAvailable的调用上一级来自TextureMovieEncoder#frameAvailable

同样我们需要调整这个方法里面的代码,调整前:

mHandler.sendMessage(mHandler.obtainMessage(MSG_FRAME_AVAILABLE,
     (int) (timestamp >> 32), (int) timestamp, transform));

调整后:

if(isRecording){
    mHandler?.apply {
        sendMessage(
            obtainMessage(
                MSG_FRAME_AVAILABLE,
                (timestamp shr 32).toInt(),
                timestamp.toInt(),
                transform
            )
        )
    }
}

我们再看一下TextureMovieEncoder的源码,里面只有触发了Looper#quit,isRecording才为false,因为我们上面修改了TextureMovieEncoder#stopRecording方法,提前调用了Looper#quit,所以这里需要同步停止发送MSG_FRAME_AVAILABLE消息。

核心解决处理的关键代码,全部讲完。

下面就来看看我们最终提供给大家的项目功能视频吧,拍照和拍视频都支持水平滑动切换滤镜功能:


GIF压缩失真了,请下载源码体验

目前遗留有个问题是:切换前置摄像头和后置摄像头,会有个颠倒的问题,除了这个问题,一切正常满足生产开发需求。

源码地址:

如果你可以访问github网站,点击此链接:
https://github.com/TheMelody/ComposeCameraxOpenGL

如果 不能访问github ,可点击这里下载,我们建议到 github 上下载:
https://download.youkuaiyun.com/download/logicsboy/87328624

点赞❤️+关注❤️+收藏❤️+评论❤️,划走了可就找不到了哦

Android Compose 调用系统相机拍照 这段代码首先定义了一个CameraApp的Composable函数,该函数包含了一个按钮,用户点击按钮时会启动系统相机应用。请注意,实际应用中,还需要处理权限请求等更多复杂的情况。此外,由于不同Android版本的相机API可能有所不同,你可能需要根据你的目标Android版本来调整代码。在Android中,使用Compose调用系统相机拍照功能涉及到多个组件和步骤。在Compose中,你可以创建一个RememberLauncher来处理这个任务。首先,确保你的Android项目已经添加了相机相关的权限。 阅读详情

相关推荐

Compose使用OpenGL+CameraX快速实现相机拍视频实时滤镜“、”拍照+滤镜

资源代码对应的文章地址:https://blog.youkuaiyun.com/logicsboy/article/details/128404161 使用Jetpack Compose UI开发框架,快速简单易上手,使用CameraX + OpenGL,实现更快更高效的拍照片+录视频。 为什么要用OpenGL呢?因为我们需要用到“滤镜”,同样的,我们:把数据放到OpenGL渲染的线程上去做图像相关操作,能实现更快的数据保存,基本上是毫秒级别的,而且图片质量不失真,速度快,如果只用CameraX去拍照片,你会发现CameraX图片质量大,而且返回数据结果慢,感觉臃肿的样子。 同学们,可以下载我们的源码和快手APP的视频拍照和视频录制进行对比一下,我们的速度和它的是一样的,而且图片质量也不失真。

Android使用OpenGL实现相机滤镜

在onSurfaceCreated方法中通过setOnFrameAvailableListener方法监听相机数据的回调,相机数据回调时,调用requestRender()方法,触发onDrawFrame方法。继承GLSurfaceView用于展示渲染的画面,并实现GLSurfaceView.Renderer接口。在onDrawFrame函数中对画面进行渲染,渲染的逻辑在CameraDrawer中,基本都是些固定代码。而渲染的glsl代码我放在了,raw文件夹下。版本是早期的版本,可以只获取相机数据。

工宗浩生财指南针 1104

GLCamera:基于 OpenGL ES 开发,支持实时滤镜、相机录制、视频播放功能

GLCamera 多种滤镜 后期仍会扩展 支持相机录制

Jetpack Compose 中使用 CameraX 拍照和录制视频

在 Android 开发的历史中,Camera 的 API 是一直受人诟病的,直观的感觉就是配置复杂、臃肿、难用、不易理解,官方也在尝试着不断改进开发者关于Camera的使用体验,Camera 的 API 截止目前经历了 Camera(已废弃)、Camera2、CameraX 三个版本。 初代 Camera API从 5.0 开始已经宣布废弃,而 Camera2 的 API 特别难用,所以就有了 CameraX ,本文主要探索如何在 Jetpack Compose 中使用 CameraX。

川峰的博客 4838

android 摄像头实时滤镜

这个是一个可以实时滤镜的录制视频,对照片进行滤镜相框处理的代码

Android_CameraX_+_OpenGL。虽然_CameraX_已经封装了大部分对相机操作,_GLCameraX.zip

Android_CameraX_+_OpenGL。虽然_CameraX_已经封装了大部分对相机操作,_GLCameraX

gl-Camera

OpenGL的Camera的原理详细,和原理的推导过程。

Stream__的博客 1370

金融数据自动化:从同花顺API到Excel的智能转换之旅

本文详细介绍了如何利用同花顺API实现金融数据自动化处理,并将其智能转换为Excel格式的全流程。通过Python编程和Excel高级技巧,读者可以掌握从数据获取、清洗到输出的完整解决方案,大幅提升金融数据分析的效率和准确性。文章特别强调了同花顺API的使用技巧和Excel自动化输出的最佳实践。

sql99的博客 461

Android笔记(十三):结合JetPack Compose和CameraX实现视频的录制和存储

结合Jetpack Compose和CameraX框架实现视频的录制以及将录制的时间保存到媒体库中。

userhu2012的博客 2212

Ubuntu声卡检测与故障排查:从基础命令到驱动修复

本文详细介绍了在Ubuntu系统中进行声卡检测与故障排查的完整流程。从使用lspci、aplay等基础命令识别硬件,到排查驱动冲突、修复权限问题,再到调整PulseAudio高级配置,提供了一套系统性的解决方案。文章结合实战案例,帮助用户快速诊断并解决Ubuntu系统常见的“无声”问题,恢复音频功能。

g2h3i4j5的博客 228

快速谱峭度算法解析

最近一直在研究振动信号的最优解调带宽寻找方法,而快速谱峭度算法是最常见的一种,因此本篇文章准备对该算法做个深入解析,也相当于自己的学习记录了。本篇文章对快速谱峭度算法做了一个较为详细的介绍,实际上就是通过多组滤波器将信号分解到不同的频段,再计算每个频段的峭度,从而找到值最大的频段,进一步地我们也可以选取其他指标作为频段的选择,以便更好地找到振动信号中的故障信息。

qq1234534215的博客 2741

音视频系列--OpenGL纹理+CameraX滤镜渲染

上一篇写了OpenGL基础理论 最近趁着空余时间把OpenGL纹理学习了,然后结合CameraX做了下滤镜效果,还是打算记录下学习效果。 关于纹理的介绍可以学习这篇文章 一、CameraRender 数据源使用CameraX,没有Camera2代码的复杂,CameraX的使用比较简单,之前写的这篇文章有过CameraX的介绍使用,这里不做过多赘述了。 public class CameraRender implements GLSurfaceView.Renderer, Preview.OnPreview

夏的专栏 1630

GD32F4x芯片加密实战:从读保护到安全启动全解析

本文详细解析了GD32F4x芯片加密的实战操作,从读保护功能到安全启动全流程。通过具体代码示例和应用场景分析,帮助开发者有效防止固件被盗用,提升工业控制、智能门锁等场景下的数据安全性。重点介绍了读保护功能的底层机制、配置步骤及常见问题解决方案。

weixin_42629671的博客 207

compose中实现拍照和选取相册功能兼容android 13+

拍照和选取图片的intent在Android上是通用的,后面写的compose组合方法才是compose里面特有的,所以这里也可以拿来放到非compose里面使用。//图片结果//定义单例的原因是因为拍照返回的时候页面会重新实例takePhoto,导致拍照的uri始终为空 val instance get() = Helper . obj } private object Helper {. let {

Tobey_r1的博客 3690

计算机组成原理课程设计_微程序控制的简单模型机设计

微程序控制的简单模型机设计 要求 基本要求 完成一个简单主机的设计,模型机应具备如下能力:在自行设计的指令集基础上,运行自行编写的简单用户程序,实现特定运算功能。 弹性要求 在此基础上,完成必要的扩展,实现模型机的功能扩展设计,包括:实现多种运算功能(指令集的扩充)、支持更为丰富的寻址方式、有更为完善的微程序设计等。 实验软件和硬件环境 QuartusII, FPGA计算机组...

sailist的记录站 3万+

SAP FICO 中的 F-02 :概念、使用场景及案例解析

在 SAP FICO (财务会计与管理会计) 模块中,F-02 是一个用于录入总账凭证的事务代码。这个事务代码主要用于手动输入总账凭证,适用于各类财务交易,例如资产购入、费用支付、收入确认等。F-02 的重要性在于,它允许财务人员在 SAP 系统中创建凭证,并确保这些凭证能够正确影响总账账户。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 2060

jetpack Compose 使用 GLSurfaceView的例子

页面中包含两个按钮, 点击按钮1 ,GL中新增纹理,实现了一个 compose 测试 GL纹理的例子;点击按钮2 ,GL中释放纹理。

GYBIN02的专栏 853

【AI智能体】Codex AI 辅助编程高级技能实战操作详解

Codex AI 辅助编程高级技能实战操作详解

congge 6755

录制视频,实现特效与滤镜的几种方式(二)

本文并非专业音视频领域的文章,只不过是其在 Android 方向的 Camera 硬件下结合一些常用的应用场景而已。所以本文并不涉及到太专业的音视频知识,你只需要稍微了解一些以下知识点即可流畅阅读。Android 三种 Camera 分别如何预览,有什么区别?三种 Camera 回调的数据 byte[] 格式有什么区别?如何转换如何旋转?录制视频中常用的 NV21,I420,Surface 三种输入格式对哪一种COLOR_FORMAT完成编码?

chuyouyinghe的专栏 1282

【AI应用实战-Codex】Mac intel芯片下安装Codex(二)

摘要:本文介绍了在Intel芯片Mac上安装OpenAI Codex桌面应用时遇到的问题及解决方法。由于官方仅提供ARM64版本,导致Intel Mac无法直接运行。解决方案包括:1)使用社区脚本将ARM版DMG与x64 Electron重新打包成兼容版本;2)使用VSCode插件配合CLI作为替代方案。文章详细记录了重新打包过程中遇到的"electron_common_owl_features"绑定缺失错误,通过注入stub代码、重算ASAR完整性哈希等步骤成功解决问题。最终生成的Co

3510

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

Android笔记(八):基于CameraX库结合Compose和传统视图组件PreviewView实现照相机画面预览和照相功能

CameraX是JetPack库之一,通过CameraX可以向应用增加相机的功能。在下列内容中,将介绍一个结合CameraX实现一个简单的拍照应用。本应用必须采用Android SDK 34。

userhu2012的博客 3633

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

CameraX 1.3 Beta 版发布 | 为 Android 应用带来更强大的相机功能

作者 / Donovan McMurray,Camera Developer Relations EngineerCameraX 是 Android Jetpack 的相机库,可帮助您为不同的 Android 版本和设备打造一致的出色体验,随着 CameraX 1.3 版本的推出,这个库的实用性也更上一层楼。CameraX 已用于越来越多的 Android 应用中,拥有非常广泛的应用场景,包括简单...

Android开发者 1361

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

在 Jetpack Compose 中使用 CameraX示例

在使用Jetpack Compose开发安卓应用,当在学习使用CameraX组件时发现官方提供的教程不是Compose的。与是我就记录一下,简单的示例。

lxyoucan的博客 850

CameraX使用

添加依赖 def camerax_version = "1.1.0-beta03" // CameraX core library implementation "androidx.camera:camera-core:$camerax_version" // CameraX Camera2 extensions[可选]拓展库可实现人像、HDR、夜间和美颜、滤镜但依赖于OEM implementation "androidx.camera:camera-camera2:$camerax_version" /

Alvin's Planets 1402

CameraX和OpenGL的融合(cameraX预览数据openGL渲染)

上一篇实现了rc版本的CameraX的一些基本能力 但是那只是基本,因为很多时候我们想要在拿到预览的YUV之前,就做一些事情,那只能通过拿到SurfaceTexture交给OpenGL去渲染,这篇文章就是主要说这个的,相关文章或者视频再网上挺少的,所以花费了比较多时间,后面细说。 前置知识 OpenGL(Open Graphics Library)是开放图形库。是用于渲染2D、3D矢量图形的跨语言、跨平台的应用程序编程接口API。简单来说就是一套画图的API。 OpenGL ES (OpenGL fo

重学Android,保持学习 3208
上一篇: OpenHarmony 物联网设备开发环境搭建
下一篇: 使用DevEco Device Tool编译并烧录全部步骤和过程详解
Halifax ‎
博客等级 码龄14年 4272粉丝 43原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Halifax ‎

交个朋友

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值