Android之Camera1实现相机开发

简单谈谈android自定义相机的实现(上 android.hardware.Camera) 通常情况下,调用android系统相机基本上可以满足拍照的需求,而自定义相机的需求一般来自于开发自己的相机应用,今天我们来简单聊聊android自定义相机的实现,限于篇幅,我们上篇只讨论android.hardware.Camera,下篇我会和大家一起讨论一下android.hardware.Camera2 android.hardware.Camera android 5.0 之前控制相机硬件是通 阅读详情

一、前言

现在很多app都会有拍照功能,一般调用系统进行拍照裁剪就能满足平时的需求,但有些场景或者特殊情况下如:持续不间断拍多张照片或者是进行人脸识别的时候,这时候之间调用系统原生相机拍照时不能满足自己的开发需求,就需要使用原生Camera来进行自定义开发,本文会采用android.hardware.CameraAPI来进行开发。在Android生态中,Camera是碎片化较为严重的一块,因为现在Android本身有三套API:

  • Camera:Android 5.0以下
  • Camera2:Android 5.0以上
  • CameraX:基于Camera2API实现,极大简化在minsdk21及以上版本的实现过程

下面打算分别采用camera1,camera2,cameraX来实现相机开发。

另外各家厂商(华为,OPPO,VIVO,小米)都对Camera2支持程度各不相同,从而导致需要花很大功夫来做适配工作,很多时候直接采用camera1进行开发。 做过相机的同学都知道,Camera1相机开发一般分为五个步骤:

  • 检测相机资源,如果存在相机资源,就请求访问相机资源,否则就结束
  • 创建预览界面,一般是继承SurfaceView并且实现SurfaceHolder接口的拍摄预览类,并且创建布局文件,将预览界面和用户界面绑定,进行实时显示相机预览图像
  • 创建拍照监听器来响应用户的不同操作,如开始拍照,停止拍照等
  • 拍照成功后保存文件,将拍摄获得的图像文件转成位图文件,并且保存输出需要的格式图片
  • 释放相机资源,当相机不再使用时,进行释放

了解完开发步骤后,因为本文是针对Camera1来进行开发,那下面先了解一些具体的类和方法。

二、Surface、SurfaceView、SurfaceHolder

1.Surface

Surface根据英文直译是表面的意思,在源码中有这样描述的:

/**
 * Handle onto a raw buffer that is being managed by the screen compositor.
 *
 * <p>A Surface is generally created by or from a consumer of image buffers (such as a
 * {@link android.graphics.SurfaceTexture}, {@link android.media.MediaRecorder}, or
 * {@link android.renderscript.Allocation}), and is handed to some kind of producer (such as
 * {@link android.opengl.EGL14#eglCreateWindowSurface(android.opengl.EGLDisplay,android.opengl.EGLConfig,java.lang.Object,int[],int) OpenGL},
 * {@link android.media.MediaPlayer#setSurface MediaPlayer}, or
 * {@link android.hardware.camera2.CameraDevice#createCaptureSession CameraDevice}) to draw
 * into.</p>
 */ 

上面的意思:Surface是用来处理屏幕显示内容合成器所管理的原始缓存区工具,它通常由图像缓冲区的消费者来创建如(SurfaceTexture,MediaRecorder),然后被移交给生产者(如:MediaPlayer)或者显示到其上(如:CameraDevice),从上面可以得知:

  • Surface通常由SurfaceTexture或者MediaRecorder来创建
  • Surface最后显示在MediaPlayer或者CameraDevice上
  • 通过Surface就可以获得管理原始缓存区的数据
  • 原始缓冲区(rawbuffer)是用来保存当前窗口的像素数据

在Surface内有一个Canvas成员:

 private final Canvas mCanvas = new CompatibleCanvas(); 

我们知道,画图都是在Canvas对象上来画的,因为Suface持有Canvas,那么我们可以这样认为,Surface是一个句柄,而Canvas是开发者画图的场所,就像黑板,而原生缓冲器(rawbuffer)是用来保存数据的地方,所有得到Surface就能得到其中的Canvas和原生缓冲器等其他内容。

2.SurfaceView

SurfaceView简单理解就是Surface的View。

/**
 * Provides a dedicated drawing surface embedded inside of a view hierarchy.
 * You can control the format of this surface and, if you like, its size; the
 * SurfaceView takes care of placing the surface at the correct location on the
 * screen
 */ 

意思就是SurfaceView提供了嵌入视图层级中的专用surface,你可以控制surface的格式或者大小(通过SurfaceView就可以看到Surface部分或者全部内容),SurfaceView负责把surface显示在屏幕的正确位置。

public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallback {
....
final Surface mSurface = new Surface();       // Current surface in use
....
private final SurfaceHolder mSurfaceHolder = new SurfaceHolder(){
    .....
 }
} 

SurfaceView继承自View,并且其中有两个成员变量,一个是Surface对象,一个是SurfaceHolder对象,SurfaceView将Surface显示在屏幕上,SurfaceView通过SurfaceHolder得知Surface的状态(创建、变化、销毁),可以通过getHolder()方法获得当前SurfaceView的SurfaceHolder对象,然后就可以对SurfaceHolder对象添加回调来监听Surface的状态。

Surface是从Object派生而来,实现了Parcelable接口,看到Parcelable很容易让人想到数据,而SurfaceView就是用来展示Surface数据的,两者的关系可以用下面一张图来描述:

SurfaceView和Suface

Surface是通过SurfaceView才能展示其中内容。

到这里也许大家会有一个疑问,SurfaceView和普通的View有什么区别?相机开发就一定要用SurfaceView吗?

首先普通的View和其派生类都是共享同一个Surface,所有的绘制必须在主线程(UI线程)进行,通过Surface获得对应的Canvas,完成绘制View的工作。

SurfaceView是特殊的View,它不与其他普通的view共享Surface,在自己内部持有Surface可以在独立的线程中进行绘制,在自定义相机预览图像这块,更新速度比较快和帧率要求比较高,如果用普通的View去更新,极大可能会阻塞UI线程,SurfaceView是在一个新起的线程去更新画面并不会阻塞UI线程。还有SurfaceView底层实现了双缓冲机制,双缓冲技术主要是为了解决反复局部刷新带来的闪烁问题,对于像游戏,视频这些画面变化特别频繁,如果前面没有显示完,程序又重新绘制,这样会导致屏幕不停得闪烁,而双缓冲及时会把要处理的图片在内存中处理后,把要画的东西先画到一个内存区域里,然后整体一次行画处理,显示在屏幕上。举例说明: 在Android中,如果自定义View大多数都会重写onDraw方法,onDraw方法并不是绘制一点显示一点,而是绘制完成后一次性显示到屏幕上。因为CPU访问内存的速度远远大于访问屏幕的速度,如果需要绘制大量复杂的图形时,每次都一个个从内存读取图形然后绘制到屏幕就会造成多次访问屏幕,这些效率会很低。为了解决这个问题,我们可以创建一个临时的Canvas对象,将图像都绘制到这个临时的Canvas对象中,绘制完成后通过drawBitmap方法绘制到onDraw方法中的Canvas对象中,这样就相对于Bitmap的拷贝过程,比直接绘制效率要高。

所以相机开发中最适合用SurfaceView来绘制。

3.SurfaceHolder

/**
 * Abstract interface to someone holding a display surface.  Allows you to
 * control the surface size and format, edit the pixels in the surface, and
 * monitor changes to the surface.  This interface is typically available
 * through the {@link SurfaceView} class.
 *
 * <p>When using this interface from a thread other than the one running
 * its {@link SurfaceView}, you will want to carefully read the
 * methods
 * {@link #lockCanvas} and {@link Callback#surfaceCreated Callback.surfaceCreated()}.
 */
 public interface SurfaceHolder {
    ....
     public interface Callback {

        public void surfaceCreated(SurfaceHolder holder);

        public void surfaceChanged(SurfaceHolder holder, int format, int width,
                int height);

        public void surfaceDestroyed(SurfaceHolder holder);
        ...
    }
 } 

这是一个抽象的接口给持有surface对象使用,允许你控制surface的大小和格式,编辑surface中的像素和监听surface的变化,这个接口通常通过SurfaceView这个类来获得。

另外SurfaceHolder中有一个Callback接口,这个接口有三个方法:

  • public void surfaceCreated(SurfaceHolder holder)

    surface第一次创建回调

  • public void surfaceChanged(SurfaceHolder,int format,int width,int height)

    surface变化的时候会回调

  • public void surfaceDestroyed(SurfaceHolder holder)

    surface销毁的时候回调

除了上面Callback接口比较重要外,另外还有以下几个方法也比较重要:

  • public void addCallback(Callback callback)

    为SurfaceHolder添加回调接口

  • public void removeCallback(Callback callback)

    对SurfaceHolder移除回调接口

  • public Canvas lockCanvas()

    获取Canvas对象并且对它上锁

  • public Canvas lockCanvas(Rect dirty)

    获取一个Canvas对象,并且对它上锁,但是所动的内容是dirty所指定的矩形区域

  • public void unlockCanvasAndPost(Canvas canvas)

    当修改Surface中的数据完成后,释放同步锁,并且提交改变,将新的数据进行展示,同时Surface中的数据会丢失,加锁的目的就是为了在绘制的过程中,Surface数据不会被改变。

  • public void setType(int type)

    设置Surface的类型,类型有以下几种:

    SURFACE_TYPE_NORMAL:用RAM缓存原生数据的普通Surface

    SURFACE_TYPE_HARDWARE:适用于DMA(Direct memory access)引擎和硬件加速的Surface

    SURFACE_TYPE_GPU:适用于GPU加速的Surface

    SURFACE_TYPE_PUSH_BUFFERS:表明该Surface不包含原生数据,Surface用到的数据由其他对象提供,在Camera图像预览中就使用该类型的Surface,有Camera负责提供给预览Surface数据,这样图像预览会比较流畅,如果设置这种类型就不能调用lockCanvas来获取Canvas对象。

    到这里,会发现Surface、SurfaceView和SurfaceHolder就是典型的MVC模型。

    • Surface:原始数据缓冲区,MVC中的M
    • SurfaceView:用来绘制Surface的数据,MVC中的V
    • SurfaceHolder:控制Surface尺寸格式,并且监听Surface的更改,MVC中的C

上面三者的关系可以用下面一张图来表示:

三者关系图

三、Camera

查看源码时,发现android.hardware.cameragoogle不推荐使用了:

camera

下面讲讲Camera最主要的成员和一些接口:

Camera核心类

1.CameraInfo

在Camera类里,CameraInfo是静态内部类:

 /**
     * Information about a camera
     * 用来描述相机信息
     * @deprecated We recommend using the new {@link android.hardware.camera2} API for new
     *             applications.
     * 推荐在新的应用使用{android.hardware.camera2}API
     */
    @Deprecated
    public static class CameraInfo {
        /**
         * The facing of the camera is opposite to that of the screen.
         * 相机正面和屏幕正面相反,意思是后置摄像头
         */
        public static final int CAMERA_FACING_BACK = 0;

        /**
         * The facing of the camera is the same as that of the screen.
         * 相机正面和屏幕正面一致,意思是前置摄像头
         */
        public static final int CAMERA_FACING_FRONT = 1;

        /**
         * The direction that the camera faces. It should be
         * CAMERA_FACING_BACK or CAMERA_FACING_FRONT.
         * 摄像机面对的方向,它只能是CAMERA_FACING_BACK或者CAMERA_FACING_FRONT
         *
         */
        public int facing;

        /**
         * <p>The orientation of the camera image. The value is the angle that the
         * camera image needs to be rotated clockwise so it shows correctly on
         * the display in its natural orientation. It should be 0, 90, 180, or 270.</p>
         * orientation是相机收集图片的角度,这个值是相机采集的图片需要顺时针旋转才能正确显示自
         * 然方向的图像,它必须是0,90,180,270中
         *
         *
         * <p>For example, suppose a device has a naturally tall screen. The
         * back-facing camera sensor is mounted in landscape. You are looking at
         * the screen. If the top side of the camera sensor is aligned with the
         * right edge of the screen in natural orientation, the value should be
         * 90. If the top side of a front-facing camera sensor is aligned with
         * the right of the screen, the value should be 270.</p>
         * 举个例子:假设现在竖着拿着手机,后面摄像头传感器是横向(水平方向)的,你现在正在看屏幕
         * 如果摄像机传感器的顶部在自然方向上右边,那么这个值是90度(手机是竖屏,传感器是横屏的)* 
         * 如果前置摄像头的传感器顶部在手机屏幕的右边,那么这个值就是270度,也就是说这个值是相机图像顺时针
         * 旋转到设备自然方向一致时的角度。
         *
         */
        public int orientation;

        /**
         * <p>Whether the shutter sound can be disabled.</p>
         * 是否禁用开门声音
         */
        public boolean canDisableShutterSound;
    }; 
1.1.orientation

可能很多人对上面orientation解释有点懵,这里重点讲一下orientation,首先先知道四个方向:屏幕坐标方向,自然方向,图像传感器方向,相机预览方向。

1.1.1.屏幕坐标方向

屏幕方向

在Android系统中,以屏幕左上角为坐标系统的原点(0,0)坐标,向右延伸是X轴的正方向,向下延伸是y轴的正方向,如上图所示。

1.1.2.自然方向

每个设备都有一个自然方向,手机和平板自然方向不一样,在Android应用程序中,android:screenOrientation来控制activity启动时的方向,默认值unspecified即为自然方向,当然可以取值为:

  • unspecified,默认值,自然方向
  • landscape,强制横屏显示,正常拿设备的时候,宽比高长,这是平板的自然方向
  • portrait,正常拿着设备的时候,宽比高短,这是手机的自然方向
  • behind:和前一个Activity方向相同
  • sensor:根据物理传感器方向转动,用户90度,180度,270度旋转手机方向
  • sensorLandScape:横屏选择,一般横屏游戏会这样设置
  • sensorPortait:竖屏旋转
  • nosensor:旋转设备的时候,界面不会跟着旋转,初始化界面方向由系统控制
  • user:用户当前设置的方向

默认的话:平板的自然方向是横屏,而手机的自然方向是竖屏方向。

1.1.3.图像传感器方向

手机相机的图像数据都是来自于摄像头硬件的图像传感器,这个传感器在被固定到手机上后有一个默认的取景方向,方向一般是和手机横屏方向一致,如下图:

传感器方向

和竖屏应用方向呈90度。

1.1.4.相机预览方向

将图像传感器捕获的图像,显示在屏幕上的方向。在默认情况下,和图像传感器方向一致,在相机API中可以通过setDisplayOrientation(int degrees)设置预览方向(顺时针设置,不是逆时针)。默认情况下,这个值是0,在注释文档中:

 /**
     * Set the clockwise rotation of preview display in degrees. This affects
     * the preview frames and the picture displayed after snapshot. This method
     * is useful for portrait mode applications. Note that preview display of
     * front-facing cameras is flipped horizontally before the rotation, that
     * is, the image is reflected along the central vertical axis of the camera
     * sensor. So the users can see themselves as looking into a mirror.
     *
     * <p>This does not affect the order of byte array passed in {@link
     * PreviewCallback#onPreviewFrame}, JPEG pictures, or recorded videos. This
     * method is not allowed to be called during preview.
     *
     * 设置预览显示的顺时针旋转角度,会影响预览帧和拍拍照后显示的图片,这个方法对竖屏模式的应用 * 很有用,前置摄像头进行角度旋转之前,图像会进行一个水平的镜像翻转,用户在看预览图像的时候* 就像镜子一样了,这个不影响PreviewCallback的回调,生成JPEG图片和录像文件的方向。
     *
     */ 
1.1.4.1.后置

注意,对于手机来说:

  • 横屏下:因为屏幕方向和相机预览方向一致,所以预览图像和看到的实物方向一致
  • 竖屏下:屏幕方向和预览方向垂直,会造成旋转90度现象,无论怎么旋转手机,UI预览界面和实物始终是90度,为了得到一致的预览界面需要将相机预览方向旋转90度(setDisplayOrientation(90)),这样预览界面和实物方向一致。

下面举个简单例子:

相机预览界面坐标解析

这里重点讲解一下竖屏下:

相机和图像传感器方向

后置相机预览图像

需要结合上下两张图来看:

  • 当图像传感器获得图像后,就会知道这幅图像每个坐标的像素值,但是要显示到屏幕上就要根据屏幕自然方向的坐标来显示(竖屏下屏幕自然方向坐标系和后置相机图像传感器方向呈90度),所以图像会逆时针旋转旋转90度,显示到屏幕坐标系上。
  • 那么收集的图像时逆时针旋转了90度,那么这时候需要顺时针旋转90度才能和收集的自然方向保持一致,也就是和实物图方向一样。
1.1.4.2.前置

在Android中,对于前置摄像头,有以下规定:

  • 在预览图像是真实物体的镜像
  • 拍出的照片和真实场景一样

前置相机预览界面坐标解析

同理这里重点讲一下,前置竖屏:

前置相机和图像传感器方向

前置相机收集图像方向

前置相机预览界面坐标解析

前置相机预览图像方向

在前置相机中,预览图像和相机收集图像是镜像关系,上面图中Android图标中前置收集图像和预览图像时相反的,前置相机图像传感器方向和前置相机预览图像方向是左右相反的,上图也有体现。

  • 前置摄像头收集到图像后(没有经过镜像处理),但是要显示到屏幕上,就要按照屏幕自然方向的坐标系来进行显示,需要顺时针旋转270度(API没有提供逆时针90度的方法),才能和手机自然方向一致。
  • 在预览的时候,做了镜像处理,所以只需要顺时针旋转90度,就能和自然方向一致,因为摄像图像没有做水平翻转,所以前置摄像头拍出来的图片,你会发现跟预览的时候是左右翻转的,自己可以根据需求做处理。 上面把角度知识梳理了,后面会通过代码一步一步验证,下面按照最开始的思维导图继续看Camera内的方法:
1.2.facing

facing代表相机方向,可取值有二:

  • CAMREA_FACING_BACK,值为0,表示是后置摄像头
  • CAMERA_FACING_FRONT,值为1,表示是前置摄像头
1.3.canDisableShutterSound

是否禁用快门声音

2.PreviewCallback

2.1.void onPreviewFrame(byte[] data, Camera camera)

PreviewCallback是一个接口,可以给Camera设置Camrea.PreviewCallback,并且实现这个onPreviewFrame(byte[] data, Camera camera)这个方法,就可以去Camera预览图片时的数据,如果设置Camera.setPreviewCallback(callback),onPreviewFrame这个方法会被一直调用,可以在摄像头对焦成功后设置camera.setOneShotPreviewCallback(previewCallback),这样设置onPreviewFrame这个方法就会被调用异常,处理data数据,data是相机预览到的原始数据,可以保存下来当做一张照片。

3.AutoFocusCallback

3.1.onAutoFocus(boolean success,Camera camera)

AutoFocusCallback是一个接口,用于在相机自动对焦完成后时通知回调,第一个参数是相机是否自动对焦成功,第二个参数是相机对象

android.hardware.camera2 系列----CameraDevice 我们在之前的文章中介绍了 openCamera的流程,openCamera最终使CameraApp拿到了一个叫CameraDevice的对象,后面我们在创建会话、开启预览、拍照等流程中均看到这个CameraDvice的身影,今天我们来详细看这个在Camera中占据重要地位的对象:CameraDevice。 打开:frameworks\base\core\java\android\hardware\camera2\CameraDevice.java 开篇来了一个枚举的Template: @IntDef(pre 阅读详情

相关推荐

从Camera1到CameraX:Android相机API演进与实战指南

本文系统梳理了Android相机API从Camera1、Camera2到CameraX的演进历程,分析了各代API的核心特点、优缺点及适用场景。重点介绍了官方主推的CameraX如何通过生命周期感知、用例驱动等特性,极大简化开发流程并提升设备兼容性,为开发者提供了从复杂到优雅的实战解决方案。

weixin_28347369的博客 558

Android Camere开发入门(1):初识Camera

通过了解Camera1的初始化、预览、拍照以及帧回调的过程,我们可以更好地理解和掌握Camera1 API的使用方法。此外,在实际的应用开发中,我们可以根据具体需求进一步扩展和优化相机功能。如聚焦、夜视模式、手电筒等等,具体可参见官网。相机应用程序的开发是一个充满创造力和挑战性的过程,希望这篇博文能为你提供更多的参考和启示。

挨T工作室的博客 2003

MTK 下 使用Camera1 完成预览-拍照-录像-USBCamera功能

通用平台底层都支持Camera1 的,那么Camera1 开发USBCamera 相机就能在不同平台通用了简单的预览-拍照-录像 需求可以使用Camera1 来处理 复杂的效果 性能 还是用Camera2 API 实现Camera1 毕竟是在Android5 及 以前使用,已经废弃了,只是能用。如果平台支持如RK 平台还是建议用Camera2API, 不支持的情况下可以选择Camera1 API来实现。

十年饮冰,难凉热血 1568

Android 使用Camera1实现相机预览、拍照、录像

本文介绍在Android中,如何使用Camera1 API实现相机预览、拍照和录制视频,以及提供可以接入使用的Camera1工具类

朱豪凯的博客 1万+

Android Camera1 Demo - 实现预览、拍照、录制视频功能

由于工作中需要用到Camera1,所以花了两天时间研究了以下,使用Android Camera1 API实现了相机预览、拍照和录制视频的功能。 资源中有个MyCamera1Demo.apk可以直接安装运行,MyCamera1Demo.zip是Demo源码。 具体详见我的博客 : https://blog.youkuaiyun.com/EthanCo/article/details/132651833 使用的Android Studio版本是Android Studio Giraffe | 2022.3.1

SpotBugs使用

spotbugs命令行参数解析

javajingling的专栏 2947

Web端百度离线地图3.0实战:从零搭建到私有化部署

本文详细介绍了Web端百度离线地图3.0的完整实战流程,从核心SDK本地化、功能模块下载到地图瓦片部署。通过逐步修改代码与配置,实现在无外网环境下的私有化部署,解决了内网或网络不稳定场景下的地图应用需求,并提供了关键的避坑指南。

n7o8p的博客 714

从IMC层到应力点:手把手教你用SEM/EDS给BGA焊点做一次‘体检’

本文详细介绍了如何使用SEM/EDS技术对BGA焊点进行全面失效分析,从样品制备到SEM观察、EDS分析,再到综合诊断,手把手教你识别焊点的微观特征和成分异常。文章特别强调了IMC层分析在BGA焊接失效诊断中的关键作用,并提供了实用的实验室技巧和常见失效模式对照表,帮助工程师快速定位问题根源。

weixin_42685438的博客 379

zynq的irq_f2p 如何增加或修改中断引脚个数(宽度)

ZYNQ开发过程中,如果使用PL到PS的中断,会产生一个疑问,设置界面显示可以有[91:84]、[68:61]共16个中断引脚,但是并没有设置中断口的宽度,如果使用多个中断引脚,应该怎么办?如果通过concat连接多个引脚,则自动调整为对应的引脚数。例如连接3个中断信号,则自动调整为:IRQ_F2P[2:0]

FPGA艺术家的博客 833

Python爬虫实战:2026最新版淘宝商品详情页数据抓取与价格监控

在2026年的今天,电商数据已经成为商业决策、市场分析和价格策略制定的核心资产。淘宝作为中国最大的电商平台之一,其商品详情页包含了海量有价值的信息:商品标题、价格、销量、评价数、店铺信息、SKU属性等。对于从事电商运营、竞品分析、价格监控的从业者来说,能够高效、稳定地获取这些数据至关重要。然而,淘宝平台的反爬虫策略在2026年已经演进到了相当成熟的阶段。

2201_76125261的博客 890

Python 爬虫实战:抓取应届生求职网校招岗位信息,助力学子就业

应届生求职网作为国内知名的招聘平台,汇聚了大量企业的校招岗位信息。了解这些岗位信息,对于应届毕业生制定求职策略、企业制定招聘计划以及相关就业市场分析等都具有重要意义。因此,本文将深入探讨如何运用 Python 爬虫技术从应届生求职网平台抓取校招岗位信息,为应届毕业生提供有益的就业信息支持。本文深入探究了利用 Python 爬虫技术从应届生求职网平台抓取校招岗位信息的全流程。从前期的环境搭建、模拟登录,到核心的数据抓取、存储,再到后续的数据分析与可视化,都详细展开讲解并提供代码支持。

u014481728的博客 1300

RH850从0搭建Autosar开发环境系列讲解 - 总目录

Davinci Autosar实战开发从0构建开发能力。OS,COM,DCM,BSWMM,ECUM,VLINK,XCP,MEMMAP等模块配置,带你熟悉运行的autosar代码,包括MICROSAR的启动运行,使用GreenHills生成运行的hex。

weixin_42412049的博客 1万+

【PyTorch项目实战】之ResNet系列:resnet18、resnet34、resnet50、resnet101、resnet152

ResNet (Residual Network) :是一种深度卷积神经网络(CNN)架构,其核心思想是引入残差学习(Residual Learning)机制,通过跳跃连接(skip connections)来解决深层网络训练中的退化问题。

📷 图像处理践行者 | 传统算法 · 深度学习 · 多模态 | 分享实战经验与技术洞见,探索从像素到智能的无限可能。 6374

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

上一篇: [译] Android Dev Summit 2018 应用(instant app 的总结 + 开源)
下一篇: 总结UI原理和高级的UI优化方式
普通网友
博客等级 码龄5年 1粉丝 7原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值