当前位置: 首页 > article >正文

安卓开发相机功能

相机功能

安卓中的相机调用功能也经历了很多的方案升级,目前可选的官方方案是CameraX、Camera2、Camera(废弃),还有一些第三方免费或者是付费的相机库。对于大多数开发者,建议使用 CameraX。

CameraX

CameraX 是 Android Jetpack 库的一部分,旨在简化相机应用的开发。它构建在 Camera2 API 之上,为开发者提供了更简洁的接口,相比于Camera和Camera2,有更好的设备兼容性。

  • 简单易用:相比 Camera2,CameraX 简化了相机操作,提供了更直观的 API,可以更快实现常见的相机功能。
  • 向后兼容性:CameraX 支持 Android 5.0 (API 21) 及以上版本,解决了 Camera2 在一些设备上的兼容性问题。
  • 生命周期感知:CameraX 会自动处理生命周期问题,例如当用户切换到后台时停止相机,回到前台时重新启动。
  • 内置扩展:CameraX 提供了诸如 HDR、夜间模式、美颜等功能,支持基于不同设备硬件的特性自动调整。不过这个需要看手机型号,很多手机并不支持。

CameraX拍照

  1. 项目依赖配置

在 build.gradle 文件中添加 CameraX 相关依赖:

def camerax_version = "1.2.0-alpha04" implementation "androidx.camera:camera-core:$camerax_version"//核心库 implementation "androidx.camera:camera-camera2:$camerax_version"//基于 Camera2 的实现模块 implementation "androidx.camera:camera-lifecycle:$camerax_version"//自动管理相机的生命周期 implementation "androidx.camera:camera-view:1.0.0-alpha31"//显示相机预览的 UI 组件 implementation "androidx.camera:camera-extensions:1.0.0-alpha31"//额外的高级相机功能如 HDR 和美颜

  1. 权限配置(AndroidManifest.xml)

运行相机需要对相机权限做出声明:

<uses-permission android:name="android.permission.CAMERA" /> <uses-feature android:name="android.hardware.camera" android:required="false" />

android:required="false":这意味着相机功能并不是应用的必需条件。如果设备没有相机,应用仍然可以安装和运行。如果是true,而设备本身没有相机,那应用就无法正常运行。

  1. 布局文件(activity_main.xml)

<!-- CameraX 预览控件 --> <androidx.camera.view.PreviewView android:id="@+id/previewView" android:layout_width="0dp" android:layout_height="0dp" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toTopOf="@+id/captureButton" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" /> <!-- 拍照按钮 --> <Button android:id="@+id/captureButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="拍照" app:layout_constraintTop_toBottomOf="@+id/previewView" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" />

  1. Activity中

package com.example.cameraxdemo; import android.Manifest; import android.content.pm.PackageManager; import android.os.Bundle; import android.util.Log; import android.widget.Button; import android.widget.Toast; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import androidx.camera.core.Camera; import androidx.camera.core.CameraSelector; import androidx.camera.core.ImageCapture; import androidx.camera.core.ImageCaptureException; import androidx.camera.core.Preview; import androidx.camera.lifecycle.ProcessCameraProvider; import androidx.camera.view.PreviewView; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; import com.google.common.util.concurrent.ListenableFuture; import java.io.File; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class MainActivity extends AppCompatActivity { private static final int REQUEST_CODE_PERMISSIONS = 10; private static final String[] REQUIRED_PERMISSIONS = new String[]{Manifest.permission.CAMERA}; private PreviewView previewView; private ImageCapture imageCapture; private ExecutorService cameraExecutor; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); previewView = findViewById(R.id.previewView); Button captureButton = findViewById(R.id.captureButton); // 请求相机权限,如果有权限直接启动相机 if (allPermissionsGranted()) { startCamera(); } else { ActivityCompat.requestPermissions(this, REQUIRED_PERMISSIONS, REQUEST_CODE_PERMISSIONS); } // 点击拍照按钮时执行拍照 captureButton.setOnClickListener(view -> takePhoto()); cameraExecutor = Executors.newSingleThreadExecutor(); } // 初始化相机 private void startCamera() { ListenableFuture<ProcessCameraProvider> cameraProviderFuture = ProcessCameraProvider.getInstance(this); cameraProviderFuture.addListener(() -> { try { // 获取 CameraProvider ProcessCameraProvider cameraProvider = cameraProviderFuture.get(); // 创建预览 Preview preview = new Preview.Builder().build(); // 创建 ImageCapture,用于拍照 imageCapture = new ImageCapture.Builder().build(); // 选择后置摄像头 CameraSelector cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA; // 将预览与 PreviewView 绑定 preview.setSurfaceProvider(previewView.getSurfaceProvider()); // 绑定预览和 ImageCapture 到相机生命周期 cameraProvider.unbindAll(); Camera camera = cameraProvider.bindToLifecycle(this, cameraSelector, preview, imageCapture); } catch (ExecutionException | InterruptedException e) { Log.e("CameraXDemo", "Error starting camera: ", e); } }, ContextCompat.getMainExecutor(this)); } // 拍照逻辑 private void takePhoto() { if (imageCapture == null) { return; } // 创建保存文件 File photoFile = new File(getExternalFilesDir(null), System.currentTimeMillis() + ".jpg"); // 设置拍照输出选项 ImageCapture.OutputFileOptions outputFileOptions = new ImageCapture.OutputFileOptions.Builder(photoFile).build(); // 执行拍照 imageCapture.takePicture(outputFileOptions, cameraExecutor, new ImageCapture.OnImageSavedCallback() { @Override public void onImageSaved(@NonNull ImageCapture.OutputFileResults outputFileResults) { runOnUiThread(() -> Toast.makeText(MainActivity.this, "Photo saved: " + photoFile.getAbsolutePath(), Toast.LENGTH_SHORT).show()); } @Override public void onError(@NonNull ImageCaptureException exception) { Log.e("CameraXDemo", "Photo capture failed: " + exception.getMessage(), exception); } }); } // 检查是否已经获得所有权限 private boolean allPermissionsGranted() { for (String permission : REQUIRED_PERMISSIONS) { if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) { return false; } } return true; } // 权限请求结果回调 @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { if (requestCode == REQUEST_CODE_PERMISSIONS) { if (allPermissionsGranted()) { startCamera(); } else { Toast.makeText(this, "Permissions not granted by the user.", Toast.LENGTH_SHORT).show(); finish(); } } } @Override protected void onDestroy() { super.onDestroy(); cameraExecutor.shutdown(); } }

使用MediaStore,遵循分区存储:

// 创建 ContentValues ContentValues contentValues = new ContentValues(); contentValues.put(MediaStore.Images.Media.DISPLAY_NAME, System.currentTimeMillis() + ".jpg"); contentValues.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg"); contentValues.put(MediaStore.Images.Media.RELATIVE_PATH, Environment.DIRECTORY_PICTURES + "/CameraXDemo"); // 设置输出选项 ImageCapture.OutputFileOptions outputFileOptions = new ImageCapture.OutputFileOptions.Builder(getContentResolver(), MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues).build(); // 拍照 imageCapture.takePicture(outputFileOptions, cameraExecutor, new ImageCapture.OnImageSavedCallback() { @Override public void onImageSaved(@NonNull ImageCapture.OutputFileResults outputFileResults) { Uri savedUri = outputFileResults.getSavedUri(); if (savedUri != null) { runOnUiThread(() -> Toast.makeText(CameraActivity.this, "Photo saved to MediaStore: " + savedUri, Toast.LENGTH_SHORT).show()); } else { Log.e(TAG, "Image not saved properly."); } } @Override public void onError(@NonNull ImageCaptureException exception) { Log.e(TAG, "Photo capture failed: " + exception.getMessage(), exception); } });

切换前后置摄像头

主要思路是重新绑定摄像头,在重新绑定之前切换前后摄像头参数即可:

public class MainActivity extends AppCompatActivity { private PreviewView previewView; private ImageCapture imageCapture; private ProcessCameraProvider cameraProvider; private CameraSelector cameraSelector; private boolean isFrontCamera = false; // 默认后置摄像头 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); previewView = findViewById(R.id.previewView); // 启动相机 startCamera(); // 切换摄像头按钮点击事件 findViewById(R.id.switchCameraButton).setOnClickListener(v -> { isFrontCamera = !isFrontCamera; switchCamera(); }); } private void startCamera() { // 获取 CameraProvider ListenableFuture<ProcessCameraProvider> cameraProviderFuture = ProcessCameraProvider.getInstance(this); cameraProviderFuture.addListener(() -> { try { cameraProvider = cameraProviderFuture.get(); // 默认使用后置摄像头 cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA; bindCameraUseCases(); } catch (ExecutionException | InterruptedException e) { e.printStackTrace(); } }, ContextCompat.getMainExecutor(this)); } private void bindCameraUseCases() { // 创建预览 Preview preview = new Preview.Builder().build(); // 将 Preview 连接到 PreviewView preview.setSurfaceProvider(previewView.getSurfaceProvider()); // 拍照设置 imageCapture = new ImageCapture.Builder() .setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY) .build(); // 解绑之前的所有用例 cameraProvider.unbindAll(); // 绑定预览和拍照功能到相机 cameraProvider.bindToLifecycle((LifecycleOwner) this, cameraSelector, preview, imageCapture); } private void switchCamera() { // 切换前后置摄像头 if (isFrontCamera) { cameraSelector = CameraSelector.DEFAULT_FRONT_CAMERA; } else { cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA; } // 重新绑定摄像头 bindCameraUseCases(); } // 拍照方法 private void takePicture() { if (imageCapture != null) { ContentValues contentValues = new ContentValues(); contentValues.put(MediaStore.Images.Media.DISPLAY_NAME, "my_image_" + System.currentTimeMillis() + ".jpg"); contentValues.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg"); ImageCapture.OutputFileOptions outputFileOptions = new ImageCapture.OutputFileOptions.Builder(getContentResolver(), MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues).build(); imageCapture.takePicture(outputFileOptions, ContextCompat.getMainExecutor(this), new ImageCapture.OnImageSavedCallback() { @Override public void onImageSaved(ImageCapture.OutputFileResults outputFileResults) { Uri savedUri = outputFileResults.getSavedUri(); Log.d("CameraXApp", "Image saved: " + savedUri); } @Override public void onError(ImageCaptureException exception) { Log.e("CameraXApp", "Error saving image: " + exception.getMessage()); } }); } } }

CameraX视频拍摄

  1. 项目依赖配置

除了CameraX的基础依赖库,还需要新增下面的库:

implementation "androidx.camera:camera-video:$camerax_version" // 视频录制相关库

  1. 权限配置

录制视频,除了需要获取相机权限,还需要额外添加录音权限

<uses-permission android:name="android.permission.RECORD_AUDIO" />

  1. Activity中

public class VideoRecordActivity extends AppCompatActivity { private static final String TAG = "VideoRecordActivity"; private PreviewView previewView;// 预览摄像头捕获内容的视图 private ExecutorService cameraExecutor;// 用于处理相机操作的后台线程 private boolean isRecording; // 记录否正在录制的状态 private VideoCapture<Recorder> videoCapture; //捕获视频的核心组件 // private Recording recording; private ProcessCameraProvider cameraProvider;// 相机的生命周期管理组件 private CameraSelector cameraSelector;// 前置或后置摄像头 private Recording recording;//当前正在进行的录制实例 private ImageView ivRecord; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_video_record); previewView = findViewById(R.id.preview); //拍照 ivRecord = findViewById(R.id.tv_take); ivRecord.setOnClickListener(view -> { // 如果当前正在录制,点击按钮停止录制,否则就是开始录制 if (isRecording) { stopRecording(); } else { startRecording(); } }); // 创建单线程后台线程池 cameraExecutor = Executors.newSingleThreadExecutor(); startCamera(); requestPermissions(new String[]{Manifest.permission.RECORD_AUDIO}, 11); } // 启动相机预览 private void startCamera() { ListenableFuture<ProcessCameraProvider> cameraProviderFuture = ProcessCameraProvider.getInstance(this); // 异步获取摄像头的命周期管理器实例 cameraProviderFuture.addListener(() -> { try { // 获取摄像头生命周期管理器实例 cameraProvider = cameraProviderFuture.get(); // 创建预览实例 Preview preview = new Preview.Builder().build(); // 将预览内容绑定到 PreviewView 上 preview.setSurfaceProvider(previewView.getSurfaceProvider()); // 视频录制用例 Recorder recorder = new Recorder.Builder() .setQualitySelector(QualitySelector.from(Quality.HD)) // 设置录制质量为 HD .build(); // 创建 VideoCapture 用例,这个一个获取视频的核心组件 videoCapture = VideoCapture.withOutput(recorder); // 默认使用后置摄像头 cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA; //解绑所有之前的摄像头用例 cameraProvider.unbindAll(); // 将预览和视频录制绑定到生命周期 cameraProvider.bindToLifecycle(VideoRecordActivity.this, cameraSelector, preview, videoCapture); } catch (ExecutionException | InterruptedException e) { Log.e(TAG, "Error starting camera", e); } }, ContextCompat.getMainExecutor(this));// 在主线程执行 } private void startRecording() { if (isRecording) { Toast.makeText(this, "Recording is already in progress", Toast.LENGTH_SHORT).show(); return; } // 创建保存视频的 ContentValues,指定文件名和文件类型 ContentValues contentValues = new ContentValues(); contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, "video_" + System.currentTimeMillis()); contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "video/mp4"); // 使用 MediaStoreOutputOptions 指定输出位置 MediaStoreOutputOptions options = new MediaStoreOutputOptions.Builder(getContentResolver(), MediaStore.Video.Media.EXTERNAL_CONTENT_URI) .setContentValues(contentValues).build(); // 准备录制前检查录音权限 if (ActivityCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) { Toast.makeText(this, "请先获取录音权限", Toast.LENGTH_SHORT).show(); return; } // 准备录制视频,并启用音频录制 PendingRecording pendingRecording = videoCapture.getOutput() .prepareRecording(VideoRecordActivity.this, options) .withAudioEnabled(); // 如果需要音频录制,调用该方法 // 启动录制,并且设定录制回调 //回调中的videoRecordEvent会有下面几种状态: //VideoRecordEvent.Start:录制开始。 //VideoRecordEvent.Pause:录制暂停。 //VideoRecordEvent.Resume:录制恢复。 //VideoRecordEvent.Finalize:录制完成(停止或失败)。 //VideoRecordEvent.Status:录制状态更新(持续获取统计信息)。 recording = pendingRecording.start(ContextCompat.getMainExecutor(this), videoRecordEvent -> { Log.d(TAG, "Recording videoRecordEvent " + videoRecordEvent); Log.d(TAG, "Recording videoRecordEvent getRecordingStats" + videoRecordEvent.getRecordingStats()); if (videoRecordEvent instanceof VideoRecordEvent.Start) { Log.d(TAG, "Recording started"); isRecording = true; refreshUI(videoRecordEvent); } else if (videoRecordEvent instanceof VideoRecordEvent.Finalize) { Log.d(TAG, "Recording finalized"); Toast.makeText(this, "已保存", Toast.LENGTH_SHORT).show(); isRecording = false; refreshUI(videoRecordEvent); } }); } private void stopRecording() { if (recording != null && isRecording) { recording.stop(); // 停止录制 recording = null; } } //更新UI private void refreshUI(VideoRecordEvent videoRecordEvent) { if (videoRecordEvent instanceof VideoRecordEvent.Start) { //开始录制,把相关的ui换成录制的效果 ivRecord.setImageResource(R.mipmap.icon_stop_record); } else if (videoRecordEvent instanceof VideoRecordEvent.Finalize) { //结束录制 ivRecord.setImageResource(R.mipmap.icon_record); }else{ //这里可以自行扩展其他的状态 } } @Override protected void onDestroy() { super.onDestroy(); cameraExecutor.shutdown(); } }

相关文章:

安卓开发相机功能

相机功能 安卓中的相机调用功能也经历了很多的方案升级&#xff0c;目前可选的官方方案是CameraX、Camera2、Camera&#xff08;废弃&#xff09;&#xff0c;还有一些第三方免费或者是付费的相机库。对于大多数开发者&#xff0c;建议使用 CameraX。 CameraX CameraX 是 An…...

Zookeeper 及 基于ZooKeeper实现的分布式锁

1 ZooKeeper 1.1 ZooKeeper 介绍 ZooKeeper是一个开源的分布式协调服务&#xff0c;它的设计目标是将那些复杂且容易出错的分布式一致性服务封装起来&#xff0c;构成一个高效可靠的原语集&#xff0c;并以一系列简单易用的接口提供给用户使用。 原语&#xff1a;操作系统或…...

Ubuntu20.04双系统安装及软件安装(五):VSCode

Ubuntu20.04双系统安装及软件安装&#xff08;五&#xff09;&#xff1a;VSCode 打开VScode官网&#xff0c;点击中间左侧的deb文件下载&#xff1a; 系统会弹出下载框&#xff0c;确定即可。 在文件夹的**“下载”目录**&#xff0c;可看到下载的安装包&#xff0c;在该目录下…...

【计算机网络入门】初学计算机网络(十一)重要

目录 1. CIDR无分类编址 1.1 CIDR的子网划分 1.1.1 定长子网划分 1.1.2 变长子网划分 2. 路由聚合 2.1 最长前缀匹配原则 3. 网络地址转换NAT 3.1 端口号 3.2 IP地址不够用&#xff1f; 3.3 公网IP和内网IP 3.4 NAT作用 4. ARP协议 4.1 如何利用IP地址找到MAC地址…...

Android Flow操作符分类

Flow操作符分类...

经验分享:用一张表解决并发冲突!数据库事务锁的核心实现逻辑

背景 对于一些内部使用的管理系统来说&#xff0c;可能没有引入Redis&#xff0c;又想基于现有的基础设施处理并发问题&#xff0c;而数据库是每个应用都避不开的基础设施之一&#xff0c;因此分享个我曾经维护过的一个系统中&#xff0c;使用数据库表来实现事务锁的方式。 之…...

C#项目文件.csproj 文件结构解析

以下是对提供的 .csproj 文件内容的详细解析&#xff1a; 1. ‌项目根元素‌ <Project ToolsVersion"12.0" DefaultTargets"Build" xmlns"http://schemas.microsoft.com/developer/msbuild/2003"> ToolsVersion"12.0": 指定使…...

C++-第二十章:智能指针

目录 第一节&#xff1a;std::auto_ptr 第二节&#xff1a;std::unique_ptr 第三节&#xff1a;std::shared_ptr 第四节&#xff1a;std::shared_ptr的缺陷 4-1.循环引用 4-2.删除器 下期预告&#xff1a; 智能指针的作用是防止指针出作用域时忘记释放内存而造成内存泄漏&…...

chrome Vue.js devtools 提示不支持该扩展组件,移除

可能是版本不兼容&#xff0c;可以重新安装&#xff0c;推荐网址极简插件官网_Chrome插件下载_Chrome浏览器应用商店 直接搜索vue&#xff0c;下载旧版&#xff0c;vue2、vue3都支持&#xff0c;上面那个最新版本试了下&#xff0c;vue2的肯定是不能用...

C# 中的Action和Func是什么?Unity 中的UnityAction是什么? 他们有什么区别?

所属范围&#xff1a;Action 和 Func 是 C# 语言标准库中的委托类型&#xff0c;可在任何 C# 项目里使用&#xff1b;UnityAction 是 Unity 引擎专门定义的委托类型&#xff0c;只能在 Unity 项目中使用。 返回值&#xff1a;Action 和 UnityAction 封装的方法没有返回值&…...

【流行病学】Melodi-Presto因果关联工具

title: “[流行病学] Melodi Presto因果关联工具” date: 2022-12-08 lastmod: 2022-12-08 draft: false tags: [“流行病学”,“因果关联工具”] toc: true autoCollapseToc: true 阅读介绍 Melodi-Presto: A fast and agile tool to explore semantic triples derived from …...

Stream在Swift 和 Flutter上的对比

Swift 和 Flutter 都是跨平台开发框架&#xff0c;它们各自提供了强大的工具来处理数据流&#xff0c;尤其是在移动应用开发中。虽然 Swift 主要用于 iOS 开发&#xff0c;而 Flutter 主要用于移动应用的开发&#xff08;包括 iOS 和 Android&#xff09;&#xff0c;但它们各自…...

Vue3 TransitionGroup组件深入解析:结合Element Plus实践指南

引言 在动态列表交互场景中&#xff0c;元素的增删排序需要优雅的过渡效果。Vue3的TransitionGroup组件为这类需求提供了专业解决方案。本文将通过Element Plus等流行UI库的实战案例&#xff0c;深入剖析TransitionGroup的应用技巧。 一、TransitionGroup核心特性 1.1 与Tran…...

关于opencv中solvepnp中UPNP与DLS与EPNP的参数

The methods SOLVEPNP_DLS and SOLVEPNP_UPNP cannot be used as the current implementations are unstable and sometimes give completely wrong results. If you pass one of these two flags, SOLVEPNP_EPNP method will be used instead.、 由于当前的实现不稳定&#x…...

Versal - XRT(CPP) 2024.1

目录 1.简介 2. XRT 2.1 XRT vs OpenCL 2.2 Takeways 2.3 XRT C APIs 2.4 Device and XCLBIN 2.5 Buffers 2.5.1 Buffer 创建 2.5.1.1 普通 Buffer 2.5.1.2 特殊 Buffer 2.5.1.3 用户指针 Buffer 2.5.2 Data Transfer 2.5.2.1 read/write API 2.5.2.2 map API 2…...

【零基础到精通Java合集】第十八集:多线程与并发编程-线程池与Callable/Future应用

课程标题:线程池与Callable/Future应用(15分钟) 目标:掌握线程池的创建与管理,理解Callable任务与Future异步结果处理机制 0-1分钟:课程引入与线程池意义 以“银行窗口服务”类比线程池:复用固定资源(柜员)处理多任务(客户)。说明线程池的核心价值——避免频繁创建…...

windows下安装Open Web UI

windows下安装openwebui有三种方式,docker,pythonnode.js,整合包. 这里我选择的是第二种,非docker. 非Docker方式安装 1. 安装Python&#xff1a; 下载并安装Python 3.11&#xff0c;建议安装路径中不要包含中文字符&#xff0c;并勾选“Add python 3.11 to Path”选项。 安…...

【自用】NLP算法面经(4)

一、deepseek 1、MLA &#xff08;1&#xff09;LLM推理过程 prefill阶段&#xff1a;模型对全部的prompt tokens一次性并行计算&#xff0c;最终生成第一个输出token。decode阶段&#xff1a;每次生成一个token&#xff0c;直到生成EOS&#xff08;end-of-sequence&#xf…...

LeetCode热题100JS(20/100)第四天|​41. 缺失的第一个正数​|​73. 矩阵置零​|​54. 螺旋矩阵​|​48. 旋转图像​

41. 缺失的第一个正数 题目链接&#xff1a;41. 缺失的第一个正数 难度&#xff1a;困难 刷题状态&#xff1a;1刷 新知识&#xff1a; 解题过程 思考 示例 1&#xff1a; 输入&#xff1a;nums [1,2,0] 输出&#xff1a;3 解释&#xff1a;范围 [1,2] 中的数字都在数组中…...

【银河麒麟高级服务器操作系统实际案例分享】数据库资源重启现象分析及处理全过程

更多银河麒麟操作系统产品及技术讨论&#xff0c;欢迎加入银河麒麟操作系统官方论坛 https://forum.kylinos.cn 了解更多银河麒麟操作系统全新产品&#xff0c;请点击访问 麒麟软件产品专区&#xff1a;https://product.kylinos.cn 开发者专区&#xff1a;https://developer…...

开源架构与人工智能的融合:开启技术新纪元

最近五篇文章推荐&#xff1a; 开源架构的自动化测试策略优化版&#xff08;New&#xff09; 开源架构的容器化部署优化版&#xff08;New&#xff09; 开源架构的微服务架构实践优化版&#xff08;New&#xff09; 开源架构中的数据库选择优化版&#xff08;New&#xff09; 开…...

缓存那些事儿

为什么要使用缓存 性能 我们在碰到需要执行耗时特别久&#xff0c;且结果不频繁变动的SQL&#xff0c;就特别适合将运行结果放入缓存。这样&#xff0c;后面的请求就去缓存中读取&#xff0c;使得请求能够迅速响应。 并发 在大并发的情况下&#xff0c;所有的请求直接访问数…...

【弹性计算】弹性裸金属服务器和神龙虚拟化(二):适用场景

《弹性裸金属服务器》系列&#xff0c;共包含以下文章&#xff1a; 弹性裸金属服务器和神龙虚拟化&#xff08;一&#xff09;&#xff1a;功能特点弹性裸金属服务器和神龙虚拟化&#xff08;二&#xff09;&#xff1a;适用场景弹性裸金属服务器和神龙虚拟化&#xff08;三&a…...

通往 AI 之路:Python 机器学习入门-语法基础

第一章 Python 语法基础 Python 是一种简单易学的编程语言&#xff0c;广泛用于数据分析、机器学习和人工智能领域。在学习机器学习之前&#xff0c;我们需要先掌握 Python 的基本语法。本章将介绍 Python 的变量与数据类型、条件语句、循环、函数以及文件操作&#xff0c;帮助…...

FastGPT 引申:信息抽取到知识图谱的衔接流程

文章目录 信息抽取到知识图谱的衔接流程步骤1&#xff1a;原始信息抽取结果步骤2&#xff1a;数据标准化处理&#xff08;Python示例&#xff09;步骤3&#xff1a;Cypher代码动态生成&#xff08;Python驱动&#xff09; 关键衔接逻辑说明1. 唯一标识符生成规则2. 数据映射策略…...

计算机毕业设计SpringBoot+Vue.js保险合同管理系统(源码+文档+PPT+讲解)

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…...

58、深度学习-自学之路-自己搭建深度学习框架-19、RNN神经网络梯度消失和爆炸的原因(从公式推导方向来说明),通过RNN的前向传播和反向传播公式来理解。

一、RNN神经网络的前向传播图如下&#xff1a; 时间步 t1: x₁ → (W_x) → [RNN Cell] → h₁ → (W_y) → y₁ ↑ (W_h) h₀ (初始隐藏状态) 时间步 t2: x₂ → (W_x) → [RNN Cell] → h₂ → (W_y) → y₂ ↑ (W_h) h₁ 时间…...

什么是 Cholesky 分解?兼谈正定矩阵和二次型

Cholesky 分解在深度学习中的应用与理解 Cholesky 分解是一种用于对称正定矩阵的特殊分解方法&#xff0c;在线性代数和概率模型中有广泛应用。对于深度学习研究者来说&#xff0c;理解 Cholesky 分解不仅有助于掌握矩阵运算的理论基础&#xff0c;还能在高斯过程、变分方法&a…...

在单位,领导不说,但自己得懂的7个道理

如果你感到很难继续适应旧模式、旧关系、旧想法&#xff0c;开始厌倦生活&#xff0c;你很可能到了该蜕皮的时候。把“不是自己”的那部分舍弃掉&#xff0c;你就能看见“自己是谁”了。 ——奥赞瓦罗尔&#xff0c;《读者》2024年第11期 前几天听部门里一个新来的小姑娘抱怨&a…...

bge-large-zh-v1.5 与Pro/BAAI/bge-m3 区别

ge-large-zh-v1.5 和 Pro/BAAI/bge-m3 是两种不同的模型&#xff0c;主要区别在于架构、性能和应用场景。以下是它们的对比&#xff1a; 1. 模型架构 bge-large-zh-v1.5&#xff1a; 基于Transformer架构&#xff0c;专注于中文文本的嵌入表示。 参数量较大&#xff0c;适合处…...