人脸识别作为生物识别技术的核心分支,已广泛应用于考勤打卡、身份验证、支付安全等场景。在 Android 平台,实现人脸识别需要兼顾准确性、实时性和设备兼容性三大挑战。本文将系统讲解 Android 人脸识别的技术选型、核心实现、性能优化及安全加固,提供从 0 到 1 的完整解决方案,包含 Google ML Kit 实战代码、活体检测方案和隐私合规指南。

一、技术选型:三大方案对比与决策指南

Android 人脸识别存在多种技术路径,选择合适的方案是项目成功的关键。以下从准确性、性能、集成难度三个维度对比主流方案:

技术方案

核心优势

典型场景

性能表现

集成难度

Google ML Kit

无需训练、跨设备兼容、实时性强

人脸检测、特征点识别

中端机型可实现 30fps

★★☆☆☆

设备原生生物识别

系统级安全、支持锁屏集成

身份验证、支付确认

毫秒级响应(基于硬件)

★★★☆☆

开源框架(OpenCV+Dlib)

自定义程度高、算法可控

特殊场景识别、学术研究

高端机型 15-20fps

★★★★☆

1.1 Google ML Kit:快速落地首选

ML Kit 是 Google 推出的移动端机器学习 SDK,人脸识别模块封装了成熟的检测算法,无需后端支持即可本地运行。其核心能力包括:

  • 实时检测人脸边界框、21 个特征点(眼睛、鼻子、嘴巴等)
  • 识别面部表情(微笑、睁眼 / 闭眼)
  • 支持多个人脸同时检测
  • 自动适应不同光线条件

适合场景:社交应用美颜、相机特效、简单身份验证。

1.2 设备原生生物识别:安全优先选择

Android 10(API 29)引入的BiometricPrompt框架支持系统级人脸识别(需设备硬件支持),优势在于:

  • 通过 TEE(可信执行环境)保障识别安全
  • 防照片 / 视频欺骗(部分设备支持)
  • 与系统锁屏深度集成
  • 符合金融级安全标准

适合场景:支付验证、应用锁、敏感操作授权。

1.3 开源方案:深度定制需求

基于 OpenCV+Dlib 的组合方案适合需要算法定制的场景:

  • 可训练自定义模型提升特定场景准确率
  • 支持复杂特征提取(如性别、年龄预测)
  • 完全掌控识别流程和参数调整

缺点是集成复杂,需要处理模型训练、性能优化等问题,适合技术团队较强的项目。

二、ML Kit 实战:实时人脸检测与特征提取

以 Google ML Kit 为例,详解 Android 人脸识别的完整实现流程,包含相机预览、人脸检测、特征点追踪三大核心步骤。

2.1 环境配置与权限申请

添加依赖

// 项目级build.gradle
allprojects {repositories {google()// 其他仓库}
}// 模块级build.gradle
dependencies {// ML Kit人脸识别implementation 'com.google.mlkit:face-detection:16.1.5'// 相机X(用于预览)implementation 'androidx.camera:camera-camera2:1.3.1'implementation 'androidx.camera:camera-lifecycle:1.3.1'implementation 'androidx.camera:camera-view:1.3.1'
}

权限配置(AndroidManifest.xml):

<!-- 相机权限 -->
<uses-permission android:name="android.permission.CAMERA" />
<!-- Android 13+需添加媒体权限 -->
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" /><application ...><activityandroid:name=".FaceDetectionActivity"android:exported="true"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity>
</application>

动态权限申请

// 权限请求代码
private val REQUIRED_PERMISSIONS = arrayOf(Manifest.permission.CAMERA)
private val REQUEST_CODE_PERMISSIONS = 101fun checkPermissions() {if (allPermissionsGranted()) {startCamera()} else {ActivityCompat.requestPermissions(this, REQUIRED_PERMISSIONS, REQUEST_CODE_PERMISSIONS)}
}private fun allPermissionsGranted() = REQUIRED_PERMISSIONS.all {ContextCompat.checkSelfPermission(baseContext, it) == PackageManager.PERMISSION_GRANTED
}override fun onRequestPermissionsResult(requestCode: Int,permissions: Array<String>,grantResults: IntArray
) {if (requestCode == REQUEST_CODE_PERMISSIONS) {if (allPermissionsGranted()) {startCamera()} else {Toast.makeText(this, "权限被拒绝,无法使用相机", Toast.LENGTH_SHORT).show()}}
}

2.2 相机预览与帧处理

使用 CameraX 实现相机预览,并将每一帧数据传递给 ML Kit 进行处理:

private fun startCamera() {// 配置相机预览val preview = Preview.Builder().setTargetAspectRatio(AspectRatio.RATIO_4_3).build()// 配置图像分析用例(处理每一帧)val imageAnalyzer = ImageAnalysis.Builder().setTargetAspectRatio(AspectRatio.RATIO_4_3).setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST) // 只处理最新帧.build().also {it.setAnalyzer(cameraExecutor, FaceAnalyzer())}// 绑定生命周期val cameraProviderFuture = ProcessCameraProvider.getInstance(this)cameraProviderFuture.addListener({val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get()// 选择前置摄像头val cameraSelector = CameraSelector.DEFAULT_FRONT_CAMERAtry {cameraProvider.unbindAll()// 绑定预览和分析用例cameraProvider.bindToLifecycle(this, cameraSelector, preview, imageAnalyzer)// 连接预览视图preview.setSurfaceProvider(binding.viewFinder.surfaceProvider)} catch (e: Exception) {Log.e(TAG, "相机绑定失败", e)}}, ContextCompat.getMainExecutor(this))
}

2.3 人脸检测与特征提取

private inner class FaceAnalyzer : ImageAnalysis.Analyzer {// 配置ML Kit人脸检测器private val options = FaceDetectorOptions.Builder().setPerformanceMode(FaceDetectorOptions.PERFORMANCE_MODE_FAST) // 优先速度.setLandmarkMode(FaceDetectorOptions.LANDMARK_MODE_ALL) // 检测所有特征点.setClassificationMode(FaceDetectorOptions.CLASSIFICATION_MODE_ALL) // 检测表情.build()private val detector = FaceDetection.getClient(options)@SuppressLint("UnsafeOptInUsageError")override fun analyze(imageProxy: ImageProxy) {val mediaImage = imageProxy.image ?: run {imageProxy.close()return}// 将CameraX的Image转换为ML Kit可处理的InputImageval image = InputImage.fromMediaImage(mediaImage,imageProxy.imageInfo.rotationDegrees)// 执行人脸检测detector.process(image).addOnSuccessListener { faces ->processFaces(faces)}.addOnFailureListener { e ->Log.e(TAG, "检测失败", e)}.addOnCompleteListener {imageProxy.close() // 必须关闭以释放资源}}// 处理检测到的人脸private fun processFaces(faces: List<Face>) {if (faces.isEmpty()) {// 未检测到人脸updateUI(null)return}// 取第一个检测到的人脸(默认只处理单人脸)val face = faces[0]// 提取人脸特征val faceData = FaceData(boundingBox = face.boundingBox, // 人脸边界框leftEye = face.getLandmark(FaceLandmark.LEFT_EYE)?.position,rightEye = face.getLandmark(FaceLandmark.RIGHT_EYE)?.position,smileProbability = face.smilingProbability ?: 0f, // 微笑概率(0-1)leftEyeOpenProbability = face.leftEyeOpenProbability ?: 0f,rightEyeOpenProbability = face.rightEyeOpenProbability ?: 0f)// 更新UIrunOnUiThread {updateUI(faceData)}}
}// 数据类存储人脸信息
data class FaceData(val boundingBox: Rect,val leftEye: PointF?,val rightEye: PointF?,val smileProbability: Float,val leftEyeOpenProbability: Float,val rightEyeOpenProbability: Float
)

2.4 可视化人脸特征

在自定义 View 中绘制人脸框和特征点,实现直观的视觉反馈:

class FaceOverlayView @JvmOverloads constructor(context: Context,attrs: AttributeSet? = null,defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {private val facePaint = Paint().apply {color = Color.GREENstyle = Paint.Style.STROKEstrokeWidth = 4f}private val landmarkPaint = Paint().apply {color = Color.REDstyle = Paint.Style.FILLstrokeWidth = 2f}private var faceData: FaceData? = nullfun updateFaceData(data: FaceData?) {faceData = datainvalidate() // 重绘}override fun onDraw(canvas: Canvas) {super.onDraw(canvas)faceData?.let { data ->// 绘制人脸框canvas.drawRect(data.boundingBox, facePaint)// 绘制特征点(眼睛)data.leftEye?.let {canvas.drawCircle(it.x, it.y, 10f, landmarkPaint)}data.rightEye?.let {canvas.drawCircle(it.x, it.y, 10f, landmarkPaint)}// 绘制表情信息val text = "微笑: ${(data.smileProbability * 100).toInt()}% " +"左眼: ${if (data.leftEyeOpenProbability > 0.5) "睁开" else "闭上"}"canvas.drawText(text, 50f, 50f, facePaint)}}
}

三、活体检测:防止照片 / 视频欺骗

基础人脸识别容易被照片、视频等手段欺骗,活体检测通过判断 "是否为真实活人" 提升安全性。移动端常用的活体检测方案有三种:

3.1 动作活体:指令配合验证

要求用户完成指定动作(如眨眼、转头、张嘴),通过连续帧分析判断是否为真人:

// 动作活体检测状态机
enum class LivenessState {INIT, // 初始状态WAITING_FOR_SMILE, // 等待微笑WAITING_FOR_EYE_CLOSE, // 等待闭眼SUCCESS, // 验证成功FAILED // 验证失败
}class LivenessDetector {private var currentState = LivenessState.INITprivate var smileDetected = falseprivate var eyeClosedDetected = false// 处理每帧人脸数据fun processFace(faceData: FaceData): LivenessState {when (currentState) {LivenessState.INIT -> {// 初始状态:提示用户微笑currentState = LivenessState.WAITING_FOR_SMILE}LivenessState.WAITING_FOR_SMILE -> {// 检测到微笑(概率>70%)if (faceData.smileProbability > 0.7) {smileDetected = truecurrentState = LivenessState.WAITING_FOR_EYE_CLOSE}}LivenessState.WAITING_FOR_EYE_CLOSE -> {// 检测到双眼闭合(概率>80%)if (faceData.leftEyeOpenProbability < 0.2 && faceData.rightEyeOpenProbability < 0.2) {eyeClosedDetected = truecurrentState = LivenessState.SUCCESS}}else -> {}}return currentState}// 重置检测状态fun reset() {currentState = LivenessState.INITsmileDetected = falseeyeClosedDetected = false}
}

3.2 纹理活体:利用皮肤特性

真实皮肤具有特殊的亚表面散射特性,可通过闪光灯切换拍摄两张图片分析差异:

// 简化的纹理活体检测
suspend fun detectSkinTexture(cameraController: CameraController): Boolean {// 关闭闪光灯拍摄cameraController.enableFlash(false)val image1 = cameraController.takePicture()// 开启闪光灯拍摄cameraController.enableFlash(true)val image2 = cameraController.takePicture()// 分析两张图片的亮度差异(真实皮肤会有特定散射模式)val textureScore = calculateTextureScore(image1, image2)// 关闭闪光灯cameraController.enableFlash(false)// 阈值判断(实际应用需大量样本训练确定)return textureScore > 0.7
}// 计算纹理得分(简化实现)
private fun calculateTextureScore(image1: Bitmap, image2: Bitmap): Float {// 1. 提取ROI(人脸区域)// 2. 计算亮度差异方差// 3. 归一化得分(0-1)return 0.8f // 实际项目需实现真实算法
}

3.3 3D 结构光:硬件级安全

高端设备(如搭载 Google Pixel 4 及以上)支持 3D 结构光扫描,通过投射不可见光点图案构建人脸 3D 模型,彻底杜绝平面欺骗。集成方式如下:

// 3D人脸识别(需设备支持)
private val faceManager = FaceManager(this)fun start3DFaceAuth() {if (!faceManager.is3DFaceSupported) {showUnsupportedMessage()return}faceManager.authenticate(object : FaceAuthCallback {override fun onSuccess(faceAuthResult: FaceAuthResult) {// 验证成功,获取置信度得分val confidence = faceAuthResult.confidenceScoreif (confidence > 0.9) {// 高置信度通过handleAuthSuccess()}}override fun onFailure(error: FaceAuthError) {Log.e(TAG, "3D验证失败: ${error.message}")}})
}

四、性能优化:从卡顿到流畅的关键技巧

人脸识别对实时性要求极高(建议≥24fps),以下优化策略可显著提升性能:

4.1 降低处理负载

1.缩小检测区域:只在屏幕中心区域检测人脸,减少处理像素:

// 配置检测区域为中心50%区域
val options = FaceDetectorOptions.Builder().setPerformanceMode(FaceDetectorOptions.PERFORMANCE_MODE_FAST).setDetectionMode(FaceDetectorOptions.DETECTION_MODE_SINGLE) // 只检测单人脸.build()

2.降低相机分辨率:根据需求选择合适分辨率,平衡清晰度和性能:

// 配置相机为720p(足够人脸识别使用)
val imageAnalyzer = ImageAnalysis.Builder().setTargetResolution(Size(1280, 720)).build()

3.帧采样处理:每 2-3 帧处理一次,减少计算量:

private var frameCount = 0
override fun analyze(imageProxy: ImageProxy) {frameCount++// 每2帧处理一次if (frameCount % 2 != 0) {imageProxy.close()return}// 正常处理逻辑...
}

4.2 线程优化

1.使用专用线程池:避免与 UI 线程冲突:

// 创建相机处理线程池
private val cameraExecutor = Executors.newSingleThreadExecutor()

2.异步模型加载:提前初始化 ML Kit 检测器:

// 在Application中预加载模型
class MyApplication : Application() {lateinit var faceDetector: FaceDetectoroverride fun onCreate() {super.onCreate()// 预初始化检测器val options = FaceDetectorOptions.Builder().setPerformanceMode(FaceDetectorOptions.PERFORMANCE_MODE_FAST).build()faceDetector = FaceDetection.getClient(options)}
}

4.3 设备分级适配

针对不同性能设备采用差异化策略:

// 根据设备性能调整策略
fun getDetectionStrategy(): DetectionStrategy {val devicePerformance = getDevicePerformanceLevel() // 自定义设备分级return when (devicePerformance) {PerformanceLevel.HIGH -> {// 高端设备:全特征检测+30fpsDetectionStrategy.FULL_FEATURES}PerformanceLevel.MEDIUM -> {// 中端设备:基础特征+20fpsDetectionStrategy.BASIC_FEATURES}else -> {// 低端设备:仅人脸框检测+15fpsDetectionStrategy.MINIMAL}}
}

五、隐私合规与安全加固

人脸识别涉及敏感生物数据,必须严格遵守 GDPR、CCPA 等隐私法规,同时采取技术手段防止数据泄露。

5.1 数据处理合规要点

1.明确用户授权

  • 收集人脸数据前必须获得用户明确同意
  • 提供清晰的隐私政策说明数据用途和保存期限
  • 允许用户随时删除已存储的人脸数据

2.本地处理优先

  • 尽量在设备本地完成识别,避免上传原始人脸数据
  • 必须传输时,采用端到端加密:
// 使用加密传输人脸特征
val encryptedFeature = encryptFeature(faceFeature) // 自定义加密算法
apiClient.uploadFeature(encryptedFeature)

3.数据最小化

  • 只收集必要的人脸特征(如仅保存特征向量而非原始图像)
  • 设定自动删除机制:
// 定期清理人脸数据
fun scheduleDataCleanup() {WorkManager.getInstance(context).enqueueUniqueWork("face_data_cleanup",ExistingWorkPolicy.REPLACE,OneTimeWorkRequestBuilder<FaceDataCleaner>().setInitialDelay(30, TimeUnit.DAYS) // 30天后清理.build())
}

5.2 安全加固措施

1.防止 Root 设备滥用

// 检测Root环境
fun isDeviceRooted(): Boolean {return try {val su = File("/system/bin/su")su.exists()} catch (e: Exception) {false}
}// 根设备禁止使用人脸识别
if (isDeviceRooted()) {disableFaceRecognition()showToast("出于安全考虑,Root设备不支持人脸识别")
}

2.特征值加密存储

// 使用AndroidKeyStore加密存储人脸特征
fun encryptAndSaveFeature(faceFeature: FloatArray) {val keyStore = KeyStore.getInstance("AndroidKeyStore")keyStore.load(null)// 获取或创建密钥val secretKey = if (keyStore.containsAlias("face_key")) {keyStore.getEntry("face_key", null) as SecretKeyEntry} else {// 创建新密钥val keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore")keyGenerator.init(KeyGenParameterSpec.Builder("face_key",KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT).setBlockModes(KeyProperties.BLOCK_MODE_GCM).setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE).build())keyGenerator.generateKey()keyStore.getEntry("face_key", null) as SecretKeyEntry}// 加密特征值val cipher = Cipher.getInstance("AES/GCM/NoPadding")cipher.init(Cipher.ENCRYPT_MODE, secretKey.secretKey)val iv = cipher.iv // 保存IV用于解密val encrypted = cipher.doFinal(faceFeature.toByteArray())// 保存加密数据和IVsaveToSecureStorage(encrypted, iv)
}

六、实战案例:考勤打卡应用集成

结合前文技术,实现一个完整的人脸识别考勤系统,包含以下功能:

  1. 员工人脸录入(提取特征值存储)
  2. 实时人脸识别(匹配员工库)
  3. 活体检测(防止代打卡)
  4. 打卡记录上传

核心匹配算法实现:

class FaceMatcher {// 存储员工人脸特征库(实际项目应从服务器加载)private val employeeFeatures = mutableMapOf<String, FloatArray>() // 工号 -> 特征向量// 添加员工人脸特征fun enrollEmployee(employeeId: String, feature: FloatArray) {employeeFeatures[employeeId] = feature}// 人脸匹配(计算余弦相似度)fun matchFace(unknownFeature: FloatArray, threshold: Float = 0.7f): String? {var bestMatchId: String? = nullvar maxSimilarity = 0femployeeFeatures.forEach { (id, feature) ->val similarity = calculateSimilarity(unknownFeature, feature)if (similarity > maxSimilarity && similarity >= threshold) {maxSimilarity = similaritybestMatchId = id}}return bestMatchId}// 计算余弦相似度(值越大越相似)private fun calculateSimilarity(feature1: FloatArray, feature2: FloatArray): Float {var dotProduct = 0fvar norm1 = 0fvar norm2 = 0ffor (i in feature1.indices) {dotProduct += feature1[i] * feature2[i]norm1 += feature1[i] * feature1[i]norm2 += feature2[i] * feature2[i]}return dotProduct / (sqrt(norm1) * sqrt(norm2))}
}

七、未来趋势与技术选型建议

Android 人脸识别技术正朝着以下方向发展:

  • 多模态融合:结合虹膜、声音等其他生物特征提升准确性
  • 边缘 AI 加速:依托 Android NNAPI 和设备 NPU 实现本地化高效推理
  • 隐私计算:联邦学习技术实现 "数据不动模型动" 的安全协作

技术选型建议

  • 快速原型验证:优先选择 Google ML Kit
  • 安全敏感场景:使用设备原生生物识别 + 活体检测
  • 定制化需求:基于 TensorFlow Lite 部署自定义训练模型

人脸识别技术在提升便利性的同时,必须平衡用户隐私保护。开发者应始终遵循 "必要最小化" 原则,仅收集和使用必要的人脸数据,通过技术手段保障数据安全,才能构建用户信任的应用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/94094.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/94094.shtml
英文地址,请注明出处:http://en.pswp.cn/bicheng/94094.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

STM32项目分享:基于STM32单片机驾驶安全监测系统设计

“我们不做一锤子买卖&#xff0c;只做技术成长的长期伙伴&#xff01;” 目录 一、视频展示 二、项目简介 三、原理图设计 四、PCB硬件设计 五、程序设计 六、资料分享 一、视频展示 基于stm32单片机驾驶行为监测系统设计 -视频分享二、项目简介 题目&#xff1a;基于s…

【GaussDB】使用gdb定位GaussDB编译package报错

【GaussDB】使用gdb定位GaussDB编译package报错 背景 在某次迁移Oracle到GaussDB时&#xff0c;应用开发人员将改好的package在GaussDB里进行创建&#xff0c;没有ERROR也没有WARNING&#xff0c;但是编译无效对象的时候报错了。虽然已经找到了是哪个包编译报错&#xff0c;但…

One Commander:强大的Windows文件管理器

在日常使用电脑的过程中&#xff0c;文件管理和浏览是必不可少的任务。One Commander作为一款功能强大的Windows文件管理器&#xff0c;提供了丰富的功能和便捷的操作方式&#xff0c;帮助用户更高效地管理和浏览文件。它不仅支持多种文件操作&#xff0c;还提供了丰富的自定义…

SPUpDate Application 程序卸载

我安装了 EzvizStudioSetups.exe 软件&#xff0c;卸载后会在电脑遗留 SPUpDate Application 程序&#xff1b;在某一时刻会占用 CPU 资源&#xff1b;应用卸载方法一&#xff1a;在任务管理器搜索 SPUpDate Application&#xff1b;定位到文件位置&#xff1b;我的路径如下C:\…

算法题(187):程序自动分析

审题&#xff1a; 本题需要我们判断是否可以同时满足题目给定的若干等式或不等式&#xff0c;判断出后根据结果输出YES或NO 思路&#xff1a; 方法一&#xff1a;离散化并查集 使用并查集&#xff1a;其实题目中只存在两者相等或不等两种情况&#xff0c;而等于具有传递性&…

strcasecmp函数详解

strcasecmp 是 C 语言中用于不区分大小写比较两个字符串的函数&#xff0c;主要用于忽略字符大小写差异的场景&#xff08;如用户输入验证、不区分大小写的字符串匹配等&#xff09;。它属于 POSIX 标准库&#xff0c;定义在 <string.h> 头文件中。 一、函数原型与参数 函…

Voronoi图

本文将详细解释 Voronoi 图&#xff0c;它在空间分析和插值中非常常用。1. 概念 Voronoi 图是一种空间划分方法&#xff0c;它把平面&#xff08;或空间&#xff09;划分成若干个区域&#xff0c;使得每个区域内的任意一点都比该区域外的任何一点更靠近该区域的“生成点”&…

BioScientist Agent:用于药物重定位和作用机制解析的知识图谱增强型 LLM 生物医学代理技术报告

BioScientist Agent:用于药物重定位和作用机制解析的知识图谱增强型 LLM 生物医学代理技术报告 一、项目概述 药物研发是一个周期长、成本高的过程,平均需要超过 10 年时间和 20 亿美元才能将一种新药推向市场,且 90% 以上的候选药物最终失败(1)。这种低成功率主要归因于对…

5G视频终端详解 无人机图传 无线图传 便携式5G单兵图传

前言单兵图传设备&#xff0c;是一种集视频采集、编码压缩、无线传输等多种功能于一体的便携式通信终端。它以嵌入式系统为基础&#xff0c;搭载高性能 H.265 编解码处理器&#xff0c;能够将现场的音视频信息进行高效处理后&#xff0c;通过无线网络快速稳定地传输至后端指挥中…

【苹果软件】Prism Mac 9.4苹果系统免费安装包英文版 Graphpad Prism for Mac 9.4软件免费下载与详细图文教程!!

软件下载与系统要求 软件&#xff1a;Prism9.4 语言&#xff1a;英文 大小&#xff1a;103.41M 安装环境&#xff1a;MacOS12.0&#xff08;或更高&#xff0c;支持IntelM芯片&#xff09; MacOS苹果系统GraphPad Prism&#xff08;科学数据分析与图形绘制&#xff09;&am…

Redis 奇葩问题

先贴错误码Unexpected exception while processing command这个奇葩的问题查了很久&#xff0c;后面突然顿悟&#xff0c;应该是Redis记住了第一次的数据类型&#xff0c;后面即使换了数据类型也不会改变之前的数据类型。跟代码发现是codec变成了默认的了后续public RedissonBa…

C ++代码学习笔记(一)

1、GetStringUTFChars用于将 Java 字符串&#xff08;jstring&#xff09;转换为 UTF-8 编码的 C 风格字符串&#xff08;const char*&#xff09;。必须在使用完后调用 ReleaseStringUTFChars 释放内存&#xff0c;否则可能导致内存泄漏。std::string data_converter::convert…

【学习嵌入式day-29-网络】

进程和线程的区别&#xff1a;都是系统执行的任务进程是资源分配的基本单位线程是调度执行的最小单位进程的创建和切换的开销大&#xff0c;速度慢&#xff0c;效率低空间独立、----- 安全&#xff0c;稳定进程间通信不方便线程创建和切换的开销小&#xff0c;速度快&#xff0…

Eino 框架组件协作指南 - 以“智能图书馆建设手册”方式理解

Eino 框架组件关系 - 形象比喻指南 &#x1f3d7;️ 项目概览&#xff1a;构建一个智能图书馆 想象一下&#xff0c;你要建设一个现代化的智能图书馆&#xff0c;能够帮助用户快速找到所需信息并提供智能问答服务。Eino 框架就像是这个智能图书馆的建设工具包&#xff0c;每个组…

网络打印机自动化部署脚本

下面是一个全面的、交互式的PowerShell脚本&#xff0c;用于自动化网络打印机部署过程。这个脚本提供了图形化界面&#xff0c;让用户可以轻松地搜索、选择和安装网络打印机。 备注&#xff1a;这个脚本未在生产环境测试过&#xff0c;请大家测试一下&#xff0c;有问题或优化&…

探索工业自动化核心:ZMC 系列 EtherCAT 主站控制器

ZLG致远电子的ZMC系列EtherCAT主站控制器&#xff0c;凭借多元内核、丰富接口、卓越通信能力及开放开发环境&#xff0c;为工业自动化提供全方位解决方案&#xff0c;助力企业智能化升级。 前言在工业自动化领域不断演进的今天&#xff0c;可靠且高效的控制解决方案成为企业提…

rt-thread使用sfud挂载qspi flash的trace分析

说明 trace log先贴在这里&#xff0c;待分析完成后&#xff0c;完善文章。 [0m[D/drv.sdram] sdram init success, mapped at 0xC0000000, size is 33554432 bytes, data width is 16[0m\ | / - RT - Thread Operating System/ | \ 5.2.0 build Aug 21 2025 14:44:332…

服务发现与负载均衡:Kubernetes Service核心机制深度解析

目录 专栏介绍 作者与平台 您将学到什么&#xff1f; 学习特色 一、 服务发现与负载均衡&#xff1a;云原生应用的核心支柱 1.1 Kubernetes Service的设计哲学 1.2 服务发现的核心组件 二、 Service核心类型深度解析&#xff1a;从ClusterIP到LoadBalancer 2.1 ClusterI…

【基础排序】CF - 赌场游戏Playing in a Casino

题目描述 在整个太阳系都很有名的赌场 Galaxy Luck 推出了一种新的纸牌游戏。 在这个游戏中&#xff0c;有一副由 nnn 张牌组成的牌堆。每张牌上写有 mmm 个整数。nnn 位玩家各自从牌堆中获得一张牌。 然后所有玩家两两对局&#xff0c;每一对玩家恰好对局一次。 例如&#…

Jenkins启动端口修改失败查找日志

# 查看Jenkins服务启动时的环境变量sudo systemctl show jenkins | grep -i port从systemd服务信息可以看到&#xff0c;Jenkins的环境变量中 JENKINS_PORT8080&#xff0c;这说明systemd服务配置覆盖了 /etc/default/jenkins 文件中的设置1. 查找Jenkins的systemd服务文件# 查…