CameraX:Android 相机库开发实践

轻松实现 Android 相机功能:使用 CameraX 构建简单应用 本文介绍了android中jetpack库中的cameraX API的结构、模型和要求,并展示了如何实现一个简单cameraX相机应用,实现了拍照和录制视频功能。 阅读详情

前言

前段时间因为工作的需要对项目中的相机模块进行了优化,我们项目中的相机模块是基于开源库 CameraView 进行开发的。那次优化主要包括两个方面,一个是相机的启动速度,另一个是相机的拍摄的清晰度的问题。因为时间仓促,那次只是在原来的代码的基础之上进行的优化,然而那份代码本身存在一些问题,导致相机的启动速度无法进一步提升。所以,我准备自己开发一款功能完善,并且可拓展的相机库,于是 CameraX 就诞生了。

虽然去年学习了很多的 Android 的知识,但是这并没有什么骄傲的。我觉得如果一个人学习了很多的东西,但是却没有办法做出属于自己的东西,那么即使学了也跟没学一样。相比于学习能力,我更看重人的创造力。所以我也将开发一个 Android 相机库作为个人 2019 年在 Android 上面要完成的目标之一。

Android 相加开源库的现状

要使用 Android 相机实现图片拍照功能本身并不复杂,Camera1 + SurfaceView 就可以搞定。但是如果让相机能够自由拓展,就需要花费很多的功夫。我所接触的开源库包括 Google 非官方的 CameraView,以及 CameraFragment. 两个库的设计有各自的优点和缺点。

开源库优点缺点
CameraView1.支持基本的拍照、缩放等功能;2.支持自定义图片的宽高比;3.支持多种预览布局方式;1.每次获取相机支持的尺寸的时候,会先将其组装到一个有序的 Set 中,这个过程会占用一定的启动时间;2.不支持拍摄视频;3.代码堆砌,结构混乱
CameraFragment1.支持拍摄照片和视频;2.代码结构清晰1.不支持缩放;2.默认宽高比4:3,无法运行时修改;3.必须基于 Fragment

以上是两个开源库的优点和缺点,而我们可以结合它们的优缺点实现一个更加完善的相机库,同时对性能的优化和用户自定义配置,我们也提供了更多的可用的接口。

CameraX 整体结构设计

虽然文章的题目是相机开发实践,但是我们并不打算介绍太多关于如何使用 Camera API 的内容,因为本项目是开源的,读者可以自行 Fork 代码进行阅读。在这里,我们只对项目中的一些关键部分的设计思路进行说明。

相机整体架构

链接:https://www.processon.com/view/link/5c976af8e4b0d1a5b10a4049

以上是我们相机库的整体架构的设计图,这里笔者使用了 UML 建模进行基础的架构设计(当然,并非严格遵循 UML 建模的语言规则)。下面,我们介绍下项目的关键部分的设计思路。

Camera1 还是 Camera2?

了解 Android 相机 API 的同学可能知道,在 LoliPop 上面提出了 Camera2 API. 就笔者个人的实践开发的效果来看,Camera2 相机的性能确实比 Camera1 要好得多,这体现在相机对焦的速率和相机启动的速率上。当然,这和硬件也有一定的关系。Camera2 比 Camera1 使用起来确实复杂得多,但提供的可以调用的 API 也更丰富。Camera2 的另一个问题是国内的很多手机设备对 Camera2 的支持并不好。

对于这个问题,首先,我们可以根据系统的参数来判断该设备是否支持 Camera2:

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public static boolean hasCamera2(Context context) {
        if (context == null) return false;
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) return false;
        try {
            CameraManager manager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
            assert manager != null;
            String[] idList = manager.getCameraIdList();
            boolean notNull = true;
            if (idList.length == 0) {
                notNull = false;
            } else {
                for (final String str : idList) {
                    if (str == null || str.trim().isEmpty()) {
                        notNull = false;
                        break;
                    }
                    final CameraCharacteristics characteristics = manager.getCameraCharacteristics(str);

                    Integer iSupportLevel = characteristics.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
                    if (iSupportLevel != null && iSupportLevel == CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY) {
                        notNull = false;
                        break;
                    }
                }
            }
            return notNull;
        } catch (Throwable ignore) {
            return false;
        }
    }

不过,即便上面方法返回的结果标明支持 Camera2,但相机仍然可能在启动中出现异常。所以 CameraView 的解决方案是,相机启动的方法返回一个 boolean 类型标明 Camera2 是否启动成功,如果失败了,就降级并使用 Camera1。但是降级的过程会浪费一定的启动时间,因此,有人提出了使用 SharedPreferences 存储降级的记录,下次直接使用 Camera1 的解决方案。

上面两种方案各自有优缺点,使用第二种方案意味着你要修改相机库的源代码,而我们希望以一种更加灵活的方式提供给用户选择相机的权力。没错,就是策略设计模式。

因为虽然 Camera1 和 Camera2 的 API 设计和使用不同,但是我们并不需要知道内部如何实现,我们只需要给用户提供切换相机、打开闪光灯、拍照、缩放等的接口即可。在这种情况下,当然使用门面设计模式是最好的选择。

另外,对于 TextureView 还是 SurfaceView 的选择,我们也使用了策略模式+门面模式的思路。

即。对于相机的选择,我们提供门面 CameraManager 接口,Camera1 的实现类 Camera1Manager 以及 Camera2 的实现类 Camera2Manager. Camera1Manager 和 Camera2Manager 又统一继承自 BaseCameraManager. 这里的 BaseCameraManager 是一个抽象类,用来封装一些通用的相机方法。

所以问题到了是 Camera1Manager 还是 Camera2Manager 的问题。这里我们提供了策略接口 CameraManagerCreator,它返回 CameraManager:

public interface CameraManagerCreator {

    CameraManager create(Context context, CameraPreview cameraPreview);
}

以及一个默认的实现:

public class CameraManagerCreatorImpl implements CameraManagerCreator {

    @Override
    public CameraManager create(Context context, CameraPreview cameraPreview) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && CameraHelper.hasCamera2(context)) {
            return new Camera2Manager(cameraPreview);
        }
        return new Camera1Manager(cameraPreview);
    }
}

因此,我们只需要在相机的全局配置中指定自己的 CameraManager 创建策略就可以使用指定的相机了。

全局配置

之前考虑指定 CameraManager 创建策略的时候,思路是直接对静态的变量赋值的方式,不过后来考虑到对相机的支持的尺寸进行缓存的问题,所以将其设计了静态单实例的类:

public class ConfigurationProvider {

    private static volatile ConfigurationProvider configurationProvider;

    private ConfigurationProvider() {
        if (configurationProvider != null) {
            throw new UnsupportedOperationException("U can't initialize me!");
        }
        initWithDefaultValues();
    }

    public static ConfigurationProvider get() {
        if (configurationProvider == null) {
            synchronized (ConfigurationProvider.class) {
                if (configurationProvider == null) {
                    configurationProvider = new ConfigurationProvider();
                }
            }
        }
        return configurationProvider;
    }

    // ... ...
}

除了指定一些全局的配置之外,我们还可以在 ConfigurationProvider 中缓存一些相机的信息,比如相机支持的尺寸的问题。因为相机所支持的尺寸属于相机属性的一部分,是不变的,我们没有必要获取多次,可以将其缓存起来,下次直接使用。当然,我们还提供了不使用缓存的接口:

public class ConfigurationProvider {

    // ...
    private boolean useCacheValues;
    private List<Size> pictureSizes;

    public List<Size> getPictureSizes(android.hardware.Camera camera) {
        if (useCacheValues && pictureSizes != null) {
            return pictureSizes;
        }
        List<Size> sizes = Size.fromList(camera.getParameters().getSupportedPictureSizes());
        if (useCacheValues) {
            pictureSizes = sizes;
        }
        return sizes;
    }

}

这样,我们在获取相机支持的图片尺寸信息的时候只需要传入 Camera 即可使用缓存的信息。当然,缓存信息在某些极端的情况下可能会带来问题,比如从 Camera1 切换到 Camera2 的时候,需要清除缓存。

注:这里缓存的时候应该使用 SoftReference,但是考虑到数据量不大,没有这么设计,以后会考虑修改。

输出媒体文件的尺寸的问题

使用 Android 相机一个让人头疼的地方是计算尺寸的问题:因为相机支持的尺寸有三种,包括相片的支持尺寸、预览的支持尺寸和视频的支持尺寸。预览的尺寸决定了用户看到的画面的清晰程度,但是真正拍摄出图片的清晰度取决于相片的尺寸,同理输出的视频的尺寸取决于视频的尺寸。

在 CameraView 中,它允许你指定一个图片的尺寸,当没有满足的要求的尺寸的时候会 Crash…这样的处理方式是将其不好的,因为用户根本无法确定相机最大的支持尺寸,而 CameraView 甚至没有提供获取相机支持尺寸的接口……

为了解决这个问题,我们首先提供了一系列用户获取相机支持尺寸的接口:

    Size getSize(@Camera.SizeFor int sizeFor);

    SizeMap getSizes(@Camera.SizeFor int sizeFor);

这里的 SizeFor 是基于注解的枚举,我们通过它来判断用户是希望获取相片、预览还是视频的尺寸信息。这里的 SizeMap 是一个哈希表,从相机的宽高比映射到对应的尺寸列表。跟 CameraView 处理方式不同的是,我们只有在调用上述方法的时候才计算图片的宽高比信息,虽然调用下面的方法的时候会花费一丁点儿时间,但是相机的启动速度大大提升了:

    @Override
    public SizeMap getSizes(@Camera.SizeFor int sizeFor) {
        switch (sizeFor) {
            case Camera.SIZE_FOR_PREVIEW:
                if (previewSizeMap == null) {
                    previewSizeMap = CameraHelper.getSizeMapFromSizes(previewSizes);
                }
                return previewSizeMap;
            case Camera.SIZE_FOR_PICTURE:
                if (pictureSizeMap == null) {
                    pictureSizeMap = CameraHelper.getSizeMapFromSizes(pictureSizes);
                }
                return pictureSizeMap;
            case Camera.SIZE_FOR_VIDEO:
                if (videoSizeMap == null) {
                    videoSizeMap = CameraHelper.getSizeMapFromSizes(videoSizes);
                }
                return videoSizeMap;
        }
        return null;
    }

获取了相机的尺寸信息的目的当然是将其设置到相机上面,所以我们提供了两个用来设置相机尺寸的接口:

    void setExpectSize(Size expectSize);

    void setExpectAspectRatio(AspectRatio expectAspectRatio);

它们一个用来指定期望的输出文件的尺寸,一个用来指定期望的图片的宽高比。

OK,既然用户可以指定计算参数,那么怎么计算呢?这当然还是用户说了算的,因为我们一样在全局配置中为用户提供了计算的策略接口:

public interface CameraSizeCalculator {

    Size getPicturePreviewSize(@NonNull List<Size> previewSizes, @NonNull Size pictureSize);

    Size getVideoPreviewSize(@NonNull List<Size> previewSizes, @NonNull Size videoSize);

    Size getPictureSize(@NonNull List<Size> pictureSizes, @NonNull AspectRatio expectAspectRatio, @Nullable Size expectSize);

    Size getVideoSize(@NonNull List<Size> videoSizes, @NonNull AspectRatio expectAspectRatio, @Nullable Size expectSize);
}

当然,我们也会提供一个默认的计算策略。在 CameraManager 内部,我们会在需要的地方调用上述接口的方法以获取最终的相机尺寸信息:

    private void adjustCameraParameters(boolean forceCalculateSizes, boolean changeFocusMode, boolean changeFlashMode) {
        Size oldPreview = previewSize;
        long start = System.currentTimeMillis();
        CameraSizeCalculator cameraSizeCalculator = ConfigurationProvider.get().getCameraSizeCalculator();
        android.hardware.Camera.Parameters parameters = camera.getParameters();
        if (mediaType == Media.TYPE_PICTURE && (pictureSize == null || forceCalculateSizes)) {
            pictureSize = cameraSizeCalculator.getPictureSize(pictureSizes, expectAspectRatio, expectSize);
            previewSize = cameraSizeCalculator.getPicturePreviewSize(previewSizes, pictureSize);
            parameters.setPictureSize(pictureSize.width, pictureSize.height);
            notifyPictureSizeUpdated(pictureSize);
        }

        // ... ...
    }

性能优化

为了对相机的性能进行优化,笔者可是花了大量的精力。因为在之前进行优化的时候积累了一些经验,所以这次开发的时候就容易得多。下面是 TraceView 进行分析的图:

Android 相机 TraceView 分析

可以看出从相机当中获取支持尺寸的本身会占用一定时间的,而这种属于相机固有的信息,一般是不会发生变化的,所以我们可以通过将其缓存起来来提升下一次打开相机的速率。

整体上,该项目的优化主要体现在几个地方:

  1. 使用注解+常量取代枚举:因为枚举占用的内存空间比较大,而单纯使用注解无法约束输入参数的范围。这在 enums 包下面可以看到,这也是 Android 性能优化最常见的手段之一。

  2. 延迟初始化:我们为了达到只在使用到某些数据的时候才初始化的目的采用了延迟初始化的解决方案,比如 Size 的宽高比的问题:

public class Size {

    // ...

    private double ratio;

    public double ratio() {
        if (ratio == 0 && width != 0) {
            ratio = (double) height / width;
        }
        return ratio;
    }

}
  1. 数据结构的应用和选择:选择合适的数据结构和自定义数据结构往往能起到化腐朽为神奇的作用。比如 SizeMap
public class SizeMap extends HashMap<AspectRatio, List<Size>> {
}

比如在列表数据结构的应用上面,使用 ArrayList 但是提前指定数组大小,减小数组扩容的次数:

    public static List<Size> fromList(@NonNull List<Camera.Size> cameraSizes) {
        List<Size> sizes = new ArrayList<>(cameraSizes.size());
        for (Camera.Size size : cameraSizes) {
            sizes.add(of(size.width, size.height));
        }
        return sizes;
    }
  1. 缓存,这个我们之前已经提到过,除了尺寸信息我们还缓存了一些其他的信息,具体可以参考源码。

  2. 异步线程:这个当然是最能提升应用相应速度的方式。它能够让我们不阻塞主线程,从而提升界面相应的速度。但是在相机开发的时候存在一个问题,即通常打开的相机的时候比较耗时,所以放在异步线程中;而开启预览处于主线程,这很容易因为线程执行的顺序的问题导致一些难以预测的异常。在之前,笔者的解决方案是使用一个私有锁来实现线程的控制。

总结

本次相机库开发占用的时间其实不多,更多的时间花费在了 UML 建模图的设计和在真正开发之前收集资料信息。不得不说,如果你开发一个小的项目,不需要做什么设计,直接就可以上了,但是如果你设计一个比较复杂的库,花费更多时间在 UML 建模上面是值得的,因为它能让你的开发思路更加清晰。另外,为了开发 Camera2,笔者不仅找遍了开源库,还翻译了相关的官方文档,这在开源项目中会一并奉上。

相机目前支持的功能

编号功能
1拍摄照片
2拍摄视频
3指定使用 Camera1 还是 Camera2
4指定使用 TextureView 还是 SurfaceView
5闪光灯打开和关闭
6自动对焦的选择
7前置和后置相机
8快门声
9指定缩放的大小
10指定期望的图片大小
11指定期望的图片宽高比
12获取支持的图片、预览和视频的尺寸信息
13相机尺寸发生变化监听
14输出视频的文件位置
15输出视频的时间长度
16手指界面滑动的监听
17触摸进行缩放
18预览自适应和裁剪等
19缓存相机信息,清除和不适用缓存信息

最后是关于项目的一些小问题

该项目目前所有功能已经开发完毕,不过仍有一些小的问题需要完善:

  1. Camera2 预览放大之后拍摄出的图片没有放大效果的问题;
  2. Camera1 拍摄出的图片需要旋转 90 度;
  3. Camera2 在屏幕旋转成横屏之后相机预览需要同时选择 90 度的问题;
  4. Camera1 和 Camera2 切换存在一些问题。

另外,由于时间限制,该相机库目前没有进行严格的测试,所以建议使用的时候进行充分测试之后再使用。

是否会继续完善该项目?

是的,包括对相机的功能进行充分测试。只是目前的时间结点,笔者有其他的事务需要处理,所以先把它介绍给读者。当然也希望能够有更多感兴趣的朋友对该项目贡献代码。

项目地址:

  1. 项目地址:https://github.com/Shouheng88/CameraX
  2. UML 建模图地址:https://www.processon.com/view/link/5c976af8e4b0d1a5b10a4049
  3. 笔者翻译的Camera2 文档:https://github.com/Shouheng88/Android-notes/blob/master/性能优化/Android相机Camera2资料.md
Android 相机应用开发中 CameraX 的使用介绍 摘要: CameraX是Android Jetpack中的相机开发库,基于Camera2 API封装,简化开发流程并提供跨设备一致性。其核心优势包括易用性、生命周期管理、丰富功能和扩展性,支持预览、拍照、图像分析和视频录制等用例。开发步骤包括添加依赖、请求权限、配置预览视图,并使用ProcessCameraProvider绑定用例到生命周期。CameraX通过抽象底层细节,显著降低开发复杂度,适合快速构建稳定高效的相机应用。 阅读详情

相关推荐

Android CameraX 使用入门

在 Android 应用中要实现 Camera 功能还是比较困难的,为了保证在各品牌手机设备上的兼容性、响应速度等体验细节,Camera 应用的开发者往往需要花很大的时间和精力进行测试,甚至需要手动在数百种不同设备上进行测试。CameraX 正是为解决这个痛点而诞生的。

luo_boke的博客 2万+

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

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

夏的专栏 1630

Android 相机开发入门指南:CameraX 与 Camera2 的终极对比与实践

在移动应用开发中,相机功能已成为社交、电商、工具类应用的标配能力。但 Android 相机开发因其碎片化设备和复杂的硬件交互,一直是开发者面临的高难度领域。Google 先后推出 Camera2(API 21+)和 CameraX(Jetpack 组件)两套解决方案,本文将深度解析两者的差异与最佳实践。另外,对2025年依然奋战在Android开发前线的战友们问个好,祝我们这些移动开发者越来越棒!

懒人的技术笔记 1974

Mediapipe框架在Android上的使用

MediaPipe是用于构建跨平台多模态应用ML管道的框架,其包括快速ML推理,经典计算机视觉和媒体内容处理(如视频解码)。下面是用于对象检测与追踪的MediaPipe示例图,它由4个计算节点组成:PacketResampler计算器;先前发布的ObjectDetection子图;围绕上述BoxTrakcing子图的ObjectTracking子图;以及绘制可视化效果的Renderer子图。

夜雨飘零 1万+

Android CameraX自定义照相机实践

最近公司有一个Android 盒子项目,需要用到自定义照相机功能,就去重新看一下Android 端的照相机功能。几年前使用的是Camera+SurfaceView自定义相机拍照,目前看来,有点老了,现在要看Jetpack里面的Camera X。所以想挑战一下,使用CameraX来改造一下。总结了一下自定义照相机有1、Camera + SurfaceView(不推荐了)基本都符合这几个步骤。

一个持续编程的盲人。 1960

Android 实现相机(CameraX)预览

CameraX 是一个 Jetpack 库,旨在帮助您更轻松地开发相机应用。对于新应用,我们建议从 CameraX 开始。它提供一致且易于使用的 API,适用于绝大多数 Android 设备,并向后兼容 Android 5.0(API 级别 21)。

afufufufu的博客 4694

深入理解相机二(相机架构概览)

经典好文推荐,通过阅读本文,您将收获以下知识点: 一、相机架构概览 二 、Camera App 三、Camera Framework 四、Camera Provider 五、CamX-CHI(Camera HAL) 六、Camera Driver 七、Camera Hardware 一、相机架构概览 Android系统利用分层思想,将各层的接口定义与实现分离开来,以接口作为各层的脉络连接整体框架,将具体实现的主导权交由各自有具体实现需求的平台厂商或者Android 开发者,这样既做到把控全局,也给

转载和创作优秀的博客 1191

Android CameraX 1.1.0 Java版本使用教程

Android CameraX 1.1.0 Java版本使用教程 教程参考Android官方文档,并将其教程代码转成Java语言。完整代码:CameraXDemo_Java 1. 注意事项 最低支持API是21 Android Studio 至少是3.6版本 Java8环境 2. 创建项目 新建Android项目,注意Minimum SDK至少是API21 添加依赖(1.0.1版本至1.1.0-alpha08(博客编写时的最新版本)均支持。) def camerax_version = "1.

Teolih的博客 6151

安卓CameraX的使用

注:Jetpack是一个由多个库组成的套件,可帮助开发者遵循最佳做法、减少样板代码并编写可在各种Android版本和设备中一致运行的代码,让开发者可将精力集中于真正重要的编码工作。谷歌的文档只提供了Kotlin的代码示例,根据Kotlin的代码示例和文档,本文提供Java的实现。

java_t_t的博客 2804

Jetpack系列教程(一):CameraX的实战开发——让相机开发从“地狱“到“天堂“

本文介绍了Google推出的CameraX库,它极大简化了Android相机开发流程。CameraX通过抽象层解决了传统Camera2 API的复杂性和兼容性问题,支持98%的Android设备(API 21+)。文章详细展示了CameraX的三步开发流程:添加依赖、配置布局和初始化相机,并提供了拍照、切换摄像头和图像分析等进阶功能实现代码。重点强调了CameraX自动生命周期管理的优势,解决了传统开发中的资源管理难题,同时提醒开发者注意权限申请和图像代理资源释放等关键细节。CameraX使相机开发从数百行

qq_32890771的博客 1444

Android相机开发:CameraX库使用全解析

在Android开发中,相机功能是许多应用程序不可或缺的一部分。然而,传统的Android相机API存在使用复杂、兼容性差等问题。CameraX库是Google推出的一个Jetpack支持库,旨在简化Android相机开发过程,提供一致且易于使用的API,同时确保在不同设备上的兼容性。本文的目的是全面解析CameraX库的使用,涵盖从基础概念到实际项目开发的各个方面,帮助开发者快速上手并深入掌握CameraX库的应用。

移动开发前沿的博客 1582

安卓相机开发:Camera、Camera2与CameraX的使用对比及选型指南

本文对比分析了安卓相机开发中的三种API:传统Camera API、Camera2 API和CameraX。Camera API已逐渐被废弃,仅支持基础功能且存在兼容性问题;Camera2 API提供更精细的硬件控制但开发复杂度高;CameraX则简化了开发流程,提供生命周期管理并自动处理兼容性问题。文章通过具体示例说明了各API的使用方法,并建议开发者根据项目需求选择:简单应用优先CameraX,专业摄影应用可选Camera2。

故事不长丨的博客 1474

使用 CameraX 进行相机开发:Android 指南

相机应用是现代移动开发中常见的功能之一,它允许用户拍摄照片和录制视频。在 Android 平台上,Google 推出了 CameraX API,它简化了相机开发的复杂性,提供了易于使用的相机功能。本篇博客将带您逐步学习如何使用 CameraX API 在 Android 应用中实现相机功能,包括预览、拍照和录制视频,并展示如何处理相机参数和图像数据。相机功能在现代移动应用中非常常见,它允许用户拍摄照片和录制视频,为用户提供了丰富的拍摄体验。

2201_76125261的博客 1329

android CameraX构建相机拍照

Android CameraX 是一个 Jetpack 支持库,旨在简化相机应用的开发工作。它提供了一致且易用的API接口,适用于大多数Android设备,并可向后兼容至Android 5.0(API级别21)。CameraX解决了在多种设备上实现相机功能时所遇到的兼容性问题,大大减少了需要编写的设备专属代码量。同时,它还通过提供一种基于用例的、具有生命周期感知能力的方式,简化了相机功能的开发。

超级博客 1642

Android相机启动加速详解

本篇文章给大家详细分析了Android实现相机启动加速的相关知识点内容以及实例代码,有兴趣的朋友参考下。

从零到一:基于DESeq2的转录组差异表达分析实战指南

本文详细介绍了基于DESeq2的转录组差异表达分析实战指南,涵盖数据准备、标准化处理、差异分析及结果解读等关键步骤。DESeq2凭借其稳定性和对低表达基因的友好处理,成为转录组数据分析的首选工具。文章还提供了常见问题排查和优化建议,帮助研究者高效完成从分析到发表的完整流程。

weixin_26759093的博客 269

Simple-Camera开发者揭秘:如何用CameraX实现高效相机功能

Simple-Camera是一款快速、轻量且功能丰富的相机应用,专为追求简单操作与高效性能的用户设计。它采用Google的CameraX库作为核心技术,实现了从预览到拍照、录像的完整相机功能,同时保持了代码的简洁性和可维护性。本文将深入剖析Simple-Camera如何利用CameraX构建高效相机功能,为开发者提供实用的实现思路和最佳实践。 ## CameraX:现代Android相机开发的终

gitblog_00682的博客 944

MAX3232芯片引脚功能详解与外围电路设计避坑指南(从电荷泵到静电防护)

本文详细解析了MAX3232芯片的引脚功能与外围电路设计,重点介绍了其电荷泵架构和RS232通信接口的应用。通过实际案例和参数对比,提供了电路设计中的常见问题解决方案和静电防护建议,帮助工程师优化工业控制与嵌入式系统中的通信可靠性。

weixin_30596165的博客 432

Android CameraX深度解析:从Camera1到CameraX的相机架构演进

Android相机开发演进:从Camera1到CameraX 本文系统梳理了Android相机开发架构的演进历程。Camera1作为早期方案虽简单易用但功能有限;Camera2 API提供了更强大的控制能力,却因复杂架构提高了开发门槛。CameraX作为现代化解决方案,通过生命周期感知、用例抽象和统一兼容层三大设计,实现了开发效率与功能控制的平衡。其核心将相机功能抽象为Preview、ImageCapture和ImageAnalysis三大用例,显著降低了开发复杂度,同时自动处理设备兼容性问题,成为当前An

Jm0218Xx的博客 1460

(01)ORB-SLAM2源码无死角解析-(38) EPnP 算法原理详解→理论基础二:分情况求得beta初始解

讲解关于slam一系列文章汇总链接:史上最全slam从零开始,针对于本栏目讲解的(01)ORB-SLAM2源码无死角解析链接如下(本文内容来自计算机视觉life ORB-SLAM2 课程课件): (01)ORB-SLAM2源码无死角解析-(00)目录_最新无死角讲解:https://blog.youkuaiyun.com/weixin_43013761/article/details/123092196 文末正下方中心提供了本人联系方式,点击本人照片即可显示WX→官方认证{\color{blue}{文末正下方中心}

江南才尽江南山,年少无知年少狂! 1024

SIMULINK开发项目实例 1000 例专栏之第847例--基于飞行控制与稳定性的场景实例:多旋翼无人机在风扰动下的稳定性分析

本文介绍了使用Simulink进行多旋翼无人机风扰动稳定性分析的完整流程。首先建立包含动力学模型、控制系统和环境模拟三大模块的仿真系统,其中动力学模型基于牛顿-欧拉方程,控制系统采用PID调节器。重点展示了MATLAB函数实现的风扰动模型和姿态控制算法,通过设置输入信号和输出显示模块完成闭环仿真。最后通过多次风速条件下的仿真测试评估控制系统的抗干扰能力和稳定性表现,为无人机控制系统设计提供了有效的仿真验证方法。

xiaoheshang_123的博客 321
上一篇: C++ 复习笔记
下一篇: 一款现代、高效的 Android 图片压缩框架
开发者如是说
博客等级 码龄10年 67粉丝 163原创
评论 5
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值