氛围灯动态屏保取色方案

news/2025/10/16 15:34:26/文章来源:https://www.cnblogs.com/LiuZhen/p/19145784

这是屏保联动时,从屏保图片中动态获取主色,同步到氛围灯,切换时跟氛围灯联动效果

解析图片动态取色,耗时较长,需要预加载处理,所以在每次变更主题时便要开始取色,然后切换时同步到氛围灯

而氛围灯并不支持所有的颜色,只能支持256色,所以在取到图片颜色后需要根据结果颜色去跟氛围灯所支持的256色对比,取最接近的结果色,然后同步到氛围灯显示

取色流程

取色需要用到原生 Palette.from(bitmap).generate() 方法,通过量化算法分析位图的像素颜色分布,提取最具代表性的颜色组合,也有异步获取方法,下面方法都处于子线程,所以这里直接使用同步方法

查看 androidx.palette.graphics.Palette 源码可以得知,该方法默认提取16种颜色样本

image

需要确保取色精准度,16可能错过次要但视觉显著的颜色,过高又会导致耗时,所以这里使用24

针对原图还需要缩放处理,但是不宜过度,否则对准确度会有影响,这里对2560分辨率的图片缩小三分之一处理

private val mWidth = ScreenUtils.getScreenWidth() / 2
private val mHeight = ScreenUtils.getScreenHeight() / 2Glide.with(Utils.getApp()).asBitmap().load(new File(path)).override(width, height).centerCrop().skipMemoryCache(true).diskCacheStrategy(DiskCacheStrategy.NONE).submit(width, height).get();
View Code

对氛围灯的256色进行缓存处理,先新建 color_rgb_256.json 文件,将rgb色值保存,用于后续转换对比

image

初始化时解析成hsv缓存到本地集合中

    private fun saveHsvColor(): MutableList<HsvColor> {log("saveHsvColor")val hsvList = mutableListOf<HsvColor>()runCatching {val assetManager = Utils.getApp().assetsval file = assetManager.open("color_rgb_256.json")val jsonStr = file.bufferedReader().readText()file.close()val bean = Gson().fromJson(jsonStr, AmbientLightList::class.java)val hsvColors = FloatArray(3)for (i in 0 until bean.list.size) {bean.list[i].apply {val myColor = Color.rgb(r, g, b)Color.colorToHSV(myColor, hsvColors)hsvList.add(HsvColor(hsvColors[0], hsvColors[1], hsvColors[2]))}}val json = Gson().toJson(hsvList)log("saveHsvColor hsvListSize=${hsvList.size}")SharedPreferencesUtils.setRGB256HsvColor(Utils.getApp(), json)}.getOrElse {Log.e(TAG, "saveHsvColor Exception ${it.message}")}return hsvList}
View Code

此文件颜色不会变,所以不用重复操作,判断首次转换就行

private fun initHsvColor() {if (hsvTableList.isEmpty()) {runCatching {val json = SharedPreferencesUtils.getRGB256HsvColor(Utils.getApp())val listType = object : TypeToken<MutableList<HsvColor>>() {}.typeGson().fromJson<MutableList<HsvColor>>(json, listType)?.let {hsvTableList.addAll(it)log("initHsvColor xml list size=${hsvTableList.size}")}}.getOrElse {Log.e(TAG, "initHsvColor Exception ${it.message}")}}if (hsvTableList.isEmpty()) {saveHsvColor().let {if (it.isNotEmpty()) {hsvTableList.addAll(it)}}log("initHsvColor json list size=${hsvTableList.size}")}}
View Code

耗时操作需要放在子线程

    @JvmStaticfun init() {log("$TAG init")scope.launch(Dispatchers.IO) {hsvTableList.clear()initHsvColor()}}
View Code

后面对图片进行取色,见下面方案

取色后,跟256色进行就近查找,所以需要转换成hsv,取 hue 进行对比

private fun findColor(bgHue: Float): ColorTipBean {if (hsvTableList.isEmpty()) {Log.w(TAG, "findColor hsvList is null")return ColorTipBean(Color.WHITE)}var result = hsvTableList[0]var minDiff = abs(result.hue - bgHue)for (i in 0 until hsvTableList.size) {val currentDiff = abs(hsvTableList[i].hue - bgHue)if (currentDiff < minDiff) {minDiff = currentDiffresult = hsvTableList[i]}}log("findColor bgHue=$bgHue,result=$result")return ColorTipBean(Color.HSVToColor(floatArrayOf(result.hue, result.saturation, result.value)))}
View Code

拿到结果后,通过信号下设到氛围灯显示

准确度

想要达到联动效果,需要确保取色结果的准确度,原生方案使用 getDominantColor 直接获取主色,但是大部分结果差异较大,下面提供了几种方案对比

方案一:

通过原生提供的方法直接获取图片主色

Palette.from(newMap).generate().apply {val dominantColor = getDominantColor(Color.WHITE)val hsvColorArray = FloatArray(3)val hsv = colorToHSV(dominantColor, hsvColorArray)Log.d(TAG, "dominantColor $dominantColor hsv $hsv")result.fill(hsv)
}
View Code

getDominantColor 方法直接取的 mDominantSwatch.getRgb

    /*** Returns the color of the dominant swatch from the palette, as an RGB packed int.** @param defaultColor value to return if the swatch isn't available* @see #getDominantSwatch()*/@ColorIntpublic int getDominantColor(@ColorInt int defaultColor) {return mDominantSwatch != null ? mDominantSwatch.getRgb() : defaultColor;}
View Code

而 mDominantSwatch 则根据色块 population 排序的结果

    Palette(List<Swatch> swatches, List<Target> targets) {mSwatches = swatches;mTargets = targets;mUsedColors = new SparseBooleanArray();mSelectedSwatches = new ArrayMap<>();mDominantSwatch = findDominantSwatch();}@Nullableprivate Swatch findDominantSwatch() {int maxPop = Integer.MIN_VALUE;Swatch maxSwatch = null;for (int i = 0, count = mSwatches.size(); i < count; i++) {Swatch swatch = mSwatches.get(i);if (swatch.getPopulation() > maxPop) {maxSwatch = swatch;maxPop = swatch.getPopulation();}}return maxSwatch;}
View Code

假设氛围灯需要多个取色,可以直接从 mSwatches 颜色集合中按 population 排序获取

image

Swatch 代表的颜色在图片中的权重占比(多个小红点可能被聚类到同一个红色 Swatch)

经自测验证,改方案准确度不够,偏差较大,特别是在氛围灯所支持的256色中,查找出的相近结果出入较大,整体准确度不够

因为实际环境中无法看到氛围灯(车机上效果),所以在左上角显示测试结果,方便查看

image

图片中,左上角测试区域,中间上面是图片主色,下面是通过主色映射的氛围灯颜色,很显然跟图片差异较大

方案二:

在原生基础上使用饱和度跟亮度参与计算,避免过暗或过亮的颜色

fun getPerceptuallyDominantColor(bitmap: Bitmap): Int {val palette = Palette.from(bitmap).maximumColorCount(24).clearFilters().generate()val swatches = palette.swatchesif (swatches.isEmpty()) return Color.WHITEvar bestSwatch: Swatch? = nullvar maxScore = 0ffor (swatch in swatches) {val hsl = swatch.getHsl()val saturation = hsl[1] // 饱和度 (0-1)val luminance = hsl[2] // 亮度 (0-1)val population = swatch.population// 评分公式:人口占比 * 饱和度 * 亮度因子// 亮度因子确保避免过暗或过亮的颜色(0.1-0.9为理想范围)val luminanceFactor = 1f - abs(luminance - 0.5f) * 1.8fval score = population * saturation * luminanceFactorif (score > maxScore) {maxScore = scorebestSwatch = swatch}}return bestSwatch?.rgb ?: palette.getDominantColor(Color.WHITE)}
View Code

该方案将纯黑白色过滤(实际图片中纯黑白色占比很少,但是很印象色块,容易出现误差),同时避免了过亮的颜色,更突出我们肉眼看到的颜色

其它方案:

1、在方案二的基础上,加入色相,改进计算公式

2、调整图片,缩小区域,针对中心区域进行取色

3、自定义过滤器,针对业务情况单独处理某些图片

image

image

image

左上角,上面的方格代表直接从图片中读取的色值,下面的方格是映射后的色值,最左边的是方案二,中间的是方案一,右边的是替补方案

结论图片不多展示,经过大量图片验证,准确度最高的是方案二

import android.graphics.Bitmap
import android.graphics.Color
import android.util.Log
import androidx.palette.graphics.Palette
import androidx.palette.graphics.Palette.Swatch
import com.blankj.utilcode.util.GsonUtils
import com.blankj.utilcode.util.ScreenUtils
import com.blankj.utilcode.util.Utilsimport com.google.gson.Gson
import com.google.gson.annotations.SerializedName
import com.google.gson.reflect.TypeTokenimport kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.launch
import java.util.Collections
import java.util.concurrent.CopyOnWriteArrayList
import kotlin.math.abs
import kotlin.math.sqrt
import androidx.core.graphics.getobject AmbientLightColorPickManager {private const val TAG = "AmbientLightColorPickManager"private var scope = MainScope()private val mWidth = ScreenUtils.getScreenWidth() / 2private val mHeight = ScreenUtils.getScreenHeight() / 2private val hsvTableList = mutableListOf<HsvColor>()private val hueList = CopyOnWriteArrayList<FloatArray>()private val test1List = CopyOnWriteArrayList<FloatArray>()private val test2List = CopyOnWriteArrayList<FloatArray>()private val test3List = CopyOnWriteArrayList<FloatArray>()var test1Listener: ((Int, Int, Int) -> Unit)? = nullvar test2Listener: ((Int, Int, Int) -> Unit)? = null@JvmStaticfun init() {log("$TAG init")scope.launch(Dispatchers.IO) {hsvTableList.clear()initHsvColor()}}private fun initHsvColor() {if (hsvTableList.isEmpty()) {runCatching {val json = SharedPreferencesUtils.getRGB256HsvColor(Utils.getApp())val listType = object : TypeToken<MutableList<HsvColor>>() {}.typeGson().fromJson<MutableList<HsvColor>>(json, listType)?.let {hsvTableList.addAll(it)log("initHsvColor xml list size=${hsvTableList.size}")}}.getOrElse {Log.e(TAG, "initHsvColor Exception ${it.message}")}}if (hsvTableList.isEmpty()) {saveHsvColor().let {if (it.isNotEmpty()) {hsvTableList.addAll(it)}}log("initHsvColor json list size=${hsvTableList.size}")}}/** 将本地rgb色值转换成hsv保存到本地 */private fun saveHsvColor(): MutableList<HsvColor> {log("saveHsvColor")val hsvList = mutableListOf<HsvColor>()runCatching {val assetManager = Utils.getApp().assetsval file = assetManager.open("color_rgb_256.json")val jsonStr = file.bufferedReader().readText()file.close()val bean = Gson().fromJson(jsonStr, AmbientLightList::class.java)val hsvColors = FloatArray(3)for (i in 0 until bean.list.size) {bean.list[i].apply {val myColor = Color.rgb(r, g, b)Color.colorToHSV(myColor, hsvColors)hsvList.add(HsvColor(hsvColors[0], hsvColors[1], hsvColors[2]))}}val json = Gson().toJson(hsvList)log("saveHsvColor hsvListSize=${hsvList.size}")SharedPreferencesUtils.setRGB256HsvColor(Utils.getApp(), json)}.getOrElse {Log.e(TAG, "saveHsvColor Exception ${it.message}")}return hsvList}/** 设置氛围灯 */@JvmStaticfun setAmbientLight(displayId: Int, index: Int) {if (displayId != DisplayParameter.DISPLAY_CSD.displayId) returnlog("setAmbientLight displayId=$displayId")scope.launch(Dispatchers.IO) {if (hueList.isEmpty()) {Log.w(TAG, "setAmbientLight hueList is null")return@launch}if (index < 0 || index >= hueList.size) {Log.w(TAG, "setAmbientLight 索引异常")return@launch}// 氛围灯取色
            setBytesFunctionValue(index)}}@JvmStaticfun switchLight(isOn: Boolean) {log("switchLight isOn=$isOn")}private fun findColor(bgHue: Float): ColorTipBean {if (hsvTableList.isEmpty()) {Log.w(TAG, "findColor hsvList is null")return ColorTipBean(Color.WHITE)}var result = hsvTableList[0]var minDiff = abs(result.hue - bgHue)for (i in 0 until hsvTableList.size) {val currentDiff = abs(hsvTableList[i].hue - bgHue)if (currentDiff < minDiff) {minDiff = currentDiffresult = hsvTableList[i]}}log("findColor bgHue=$bgHue,result=$result")return ColorTipBean(Color.HSVToColor(floatArrayOf(result.hue, result.saturation, result.value)))}/** 初始化资源 */@JvmStaticfun loadData(displayId: Int, pictures: List<String>) {if (displayId != DisplayParameter.DISPLAY_CSD.displayId) returnlog("loadData pictures size=${pictures.size} pictures $pictures")hueList.clear()test1List.clear()test2List.clear()test3List.clear()for ((index, picture) in pictures.withIndex()) {runCatching {val bitmap = GlideCacheUtils.loadImageAsBitmap(picture, mWidth, mHeight)testGenerate(bitmap)val result = generate(bitmap)hueList.add(result)log("loadData add index=$index,colors=${GsonUtils.toJson(result)}")}.getOrElse {Log.e(TAG, "loadData exception ${it.message}")}}log("loadData hueList size=${hueList.size}")}private fun setFunctionValue(functionId: Int, value: Int, zone: Int) {try {AdapterCarManager.iCarFunction.setFunctionValue(functionId, zone, value)} catch (e: Exception) {Log.e(TAG, "setFunctionValue Exception $e")}}private fun setBytesFunctionValue(index: Int) {try {test1Listener?.invoke(Color.HSVToColor(test1List[index]),Color.HSVToColor(test2List[index]),Color.HSVToColor(test3List[index]),)test2Listener?.invoke(findColor(test1List[index][0]).colorTip,findColor(test2List[index][0]).colorTip,findColor(test3List[index][0]).colorTip,)} catch (e: Exception) {Log.e(TAG, "setBytesFunctionValue Exception $e")}}private fun getColors(list: FloatArray): ByteArray {val result = mutableListOf<ColorTipBean>()list.forEach {result.add(findColor(it))}val json = GsonUtils.toJson(LightColorBean(result).list)log("setBytesFunctionValue json=$json")return json.toByteArray()}private fun generate(newMap: Bitmap): FloatArray {val result = FloatArray(3)Log.w(TAG, "------generate start")val dominantColor = getPerceptuallyDominantColor(newMap)val hsvColorArray = FloatArray(3)val hsv = colorToHSV(dominantColor, hsvColorArray)result.fill(hsv)Log.d(TAG, "dominantColor $dominantColor, hsv ${GsonUtils.toJson(hsvColorArray)}")return result}private fun testGenerate(newMap: Bitmap) {// 评分公式val dominantColor1 = getPerceptuallyDominantColor(newMap)val hsvColorArray1 = FloatArray(3)colorToHSV(dominantColor1, hsvColorArray1)test1List.add(hsvColorArray1)// 主色Palette.from(newMap).maximumColorCount(24).clearFilters().generate().apply {val hsvColorArray2 = FloatArray(3)val dominantColor2 = getDominantColor(Color.WHITE)colorToHSV(dominantColor2, hsvColorArray2)test2List.add(hsvColorArray2)}// 评分优化公式val dominantColor3 = getPerceptuallyDominantColor1(newMap)val hsvColorArray3 = FloatArray(3)colorToHSV(dominantColor3, hsvColorArray3)test3List.add(hsvColorArray3)}fun getPerceptuallyDominantColor(bitmap: Bitmap): Int {val palette = Palette.from(bitmap).maximumColorCount(24).clearFilters().generate()val swatches = palette.swatchesif (swatches.isEmpty()) return Color.WHITEvar bestSwatch: Swatch? = nullvar maxScore = 0ffor (swatch in swatches) {val hsl = swatch.getHsl()val saturation = hsl[1] // 饱和度 (0-1)val luminance = hsl[2] // 亮度 (0-1)val population = swatch.population// 评分公式:人口占比 * 饱和度 * 亮度因子// 亮度因子确保避免过暗或过亮的颜色(0.1-0.9为理想范围)val luminanceFactor = 1f - abs(luminance - 0.5f) * 1.8fval score = population * saturation * luminanceFactorif (score > maxScore) {maxScore = scorebestSwatch = swatch}}return bestSwatch?.rgb ?: palette.getDominantColor(Color.WHITE)}private fun isClear(bitmap: Bitmap): Boolean {val totalPixels = bitmap.width * bitmap.heightvar blackCount = 0.0var whiteCount = 0.0for (x in 0 until bitmap.width) {for (y in 0 until bitmap.height) {val pixel = bitmap[x, y]if (pixel == Color.BLACK) {blackCount++}if (pixel == Color.WHITE) {whiteCount++}}}val blackRatio = blackCount / totalPixelsval whiteRatio = whiteCount / totalPixelsval isClear = blackRatio > 0.3 || whiteRatio > 0.3Log.d(TAG, "isClear=$isClear totalPixels=$totalPixels,blackCount=$blackCount, blackRatio=${String.format("%.2f", blackRatio)},whiteRatio=${String.format("%.2f", whiteRatio)}")return isClear}private fun calculateSwatchScore(hue: Float,saturation: Float,luminance: Float,population: Float): Float {// 1. 人口权重 (标准化)val populationWeight = population / 1000000f// 2. 饱和度权重 - 适度重视但不过度val saturationWeight = sqrt(saturation) // 使用平方根降低过高饱和度的优势// 3. 亮度权重 - 偏好中等亮度范围val luminanceWeight = when {luminance < 0.15f -> 0.2f  // 太暗的惩罚luminance > 0.85f -> 0.3f  // 太亮的惩罚else -> 1.0f - abs(luminance - 0.5f) * 1.5f}// 4. 色相权重 - 可选:降低过于鲜艳的红色/蓝色的优势val hueWeight = when {// 红色范围 (330-30度)(hue >= 330f || hue <= 30f) -> 0.8f// 蓝色范围 (210-270度)hue in 210f..270f -> 0.9felse -> 1.0f}return populationWeight * saturationWeight * luminanceWeight * hueWeight}fun getPerceptuallyDominantColor1(bitmap: Bitmap): Int {val palette = Palette.from(bitmap).maximumColorCount(24).clearFilters().generate()val swatches = palette.swatchesif (swatches.isEmpty()) return Color.WHITEvar bestSwatch: Swatch? = nullvar maxScore = 0ffor (swatch in swatches) {val hsl = swatch.hslval hue = hsl[0]        // 色相 (0-360)val saturation = hsl[1] // 饱和度 (0-1)val luminance = hsl[2] // 亮度 (0-1)val population = swatch.population.toFloat()// 改进的评分公式val score = calculateSwatchScore(hue, saturation, luminance, population)if (score > maxScore) {maxScore = scorebestSwatch = swatch}}return bestSwatch?.rgb ?: palette.getDominantColor(Color.WHITE)}private fun colorToHSV(rgb: Int, hsvColorArray: FloatArray): Float {Color.colorToHSV(rgb, hsvColorArray)return hsvColorArray[0]}private fun log(str: String) = Log.d(TAG, str)data class LightColorBean(val list: List<ColorTipBean>)data class ColorTipBean(@SerializedName("ColorTip")var colorTip: Int,)}
View Code

 

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

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

相关文章

uml图和数据流图

用例图 (Use Case Diagram) 定义:描述系统功能与外部用户(参与者)之间的交互关系 主要元素:参与者 (Actor):系统外部与系统交互的角色 用例 (Use Case):系统提供的功能单元 系统边界:定义系统范围 用途: 需求分…

复盘:如何用Coze+Kimi,搭建一个能自动分析财报的“金融助理”?

在金融投研领域,财报分析是了解企业价值的关键环节,但传统人工分析耗时耗力,一份详细的财报分析往往需要专业人士数小时甚至数天时间。现在,通过Coze和Kimi的强强联合,我们可以搭建一个自动化财报分析金融助理,实…

详细介绍:【算法竞赛学习笔记】基础算法篇:递归再探

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

折腾笔记:免费用上 Claude Code 的两个方案

Claude Code API 中转服务配置指南:88code 和 AnyRouter 使用教程 前言 Claude Code 是 Anthropic 推出的 AI 编程辅助工具,在代码生成、代码审查等场景中表现优异。然而,直接使用官方 API 存在一些限制:需要国际支…

2025 年最新金蝶云服务商代理机构权威推荐排行榜:聚焦铂金伙伴技术实力与万级客户口碑,上海金蝶云最新推荐优质公司

当前数字经济浪潮下,企业数字化转型进程不断加速,ERP 系统作为转型核心支撑,其服务商的选择直接决定转型成败。但金蝶云服务商市场乱象频发,资质混杂、服务能力悬殊,众多企业在选型时陷入困境:难以辨别服务商真实…

探索 Markdown 的奇妙世界

探索 Markdown 的奇妙世界欢迎来到 Markdown 的奇妙世界!无论你是写作爱好者、开发者、博主,还是想要简单记录点什么的人,Markdown 都能成为你新的好伙伴。它不仅让写作变得简单明了,还能轻松地将内容转化为漂亮的…

创建一个scale为0的矩阵

实现instanceMesh内某个单例暂时隐藏 const _zeroMatrix = new THREE.Matrix4().multiplyScalar(0);

可视化图解算法64:哈希表基础

哈希表(Hash table),也被称为散列表,是一种基于哈希函数的数据结构,它通过把关键值(Key value)映射到表中一个位置来访问记录,从而加快查找的速度。 当我们想使用哈希法来解决问题的时候,我们一般会选择如下2…

2025 防火/模压/瓦楞/大跨距/热镀锌/热浸锌/不锈钢/光伏/铝合金/锌铝镁/电缆桥架推荐榜:河北百著金属 5 星领跑,适配工业 / 建筑 / 通讯多场景线缆防护

随着工业生产、商业建筑、通讯网络对 “线缆规整 + 安全防护” 需求升级,电缆桥架的材质耐用性、场景适配性成为核心选择标准。结合防腐性能、承重能力、安装便捷度与用户反馈,2025 年电缆桥架推荐榜发布,河北百著金…

2025全球球形环氢硼聚变/“玄龙-50U”氢硼聚变厂家推荐榜单:探索清洁能源的未来方向

在全球能源转型与气候挑战的双重驱动下,曾被贴上 “永远 50 年” 标签的可控核聚变技术正迎来关键突破期。其中,氢硼聚变因无放射性废料、燃料易得、发电效率高等优势,成为最具商业化潜力的 “终极能源” 路线之一。…

SqlServer Arithmetic overflow error converting expression to data type int

现象 Microsoft.Data.SqlClient.SqlException (0x80131904): Arithmetic overflow error converting expression to data type int.at Microsoft.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateOb…

从零开始:如何用 C# 开发一款媲美 “AnyTxt” 的文件内容搜索工具

从零开始:如何用 C# 开发一款媲美 “AnyTxt” 的文件内容搜索工具说起文件内容搜索工具,那么不得不提到“AnyTxt”,号称本地知识库检索的终极答案。唯一的不足可能就是索引更新机制,不能实时监视文件更改从而更新索…

医疗公有云市场第一!

近日,国际数据公司IDC发布《中国医疗云IaaS+PaaS市场份额,2024:智能云时代》(Doc#CHC53772125,2025年9月)权威报告。报告显示,中国电信天翼云凭借在医疗云领域的深度布局与技术沉淀,以领先优势在2024年中国医疗…

11 继承--super和方法重写

11 继承--super和方法重写继承---super和方法重写 Super 子类中调用父类的方法/成员变量 私有的东西无法使用super调用 #调用父类的name属性: super.name#调用父类的方法 super.show()子类的无参构造中会隐含一个父类的…

2025手持光谱仪/光谱分析仪/便携式光谱仪、矿石/元素分析仪、合金/金属/不锈钢/铝合金、贵金属、三元催化、赛普斯、IF光谱仪推荐榜

手持式光谱仪作为现代工业检测与分析的重要工具,在合金成分分析、矿石勘探、土壤重金属检测等领域发挥着关键作用。随着技术的不断进步,手持式XRF光谱仪的性能和精度得到了显著提升,为各行业提供了更加便捷、高效的…

DC-1靶机通关

DC-1靶机 靶机地址:https://www.vulnhub.com/entry/dc-1,292/ 难度: 低 目标: 获得 root 权限 + 5个flag DC-1是VulnHub平台上的一个Linux渗透测试靶机,主要用于模拟Web应用安全场景,包含Drupal CMS漏洞利用、提权…

长视频理解与生成技术突破

本文介绍了在CVPR 2023会议上展示的四项关于长视频理解与生成的前沿研究,包括基于电影元数据的场景表示学习、选择性结构化状态空间模型、多模态模型动态推理和图像协调技术,这些技术显著提升了视频内容分析的效率和…

在 Android 11 上构建 WiFi 热点并发协助(同时开启 STA + AP 模式)

在 Android 11 上构建 WiFi 热点并发协助(同时开启 STA + AP 模式)2025-10-16 15:11 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto …

27 LCA模拟赛3T3 三等分的数组 题解

三等分的数组 题面 小 Y 有一个长度为 \(n\) 的数组,数组中的每个数都是一个 \(1 \sim m\) 之间的正整数。 小 Y 决定将这个数组分成若干个三元组:每个三元组要么由三个相同的数字组成,要么由三个连续的数字组成。换…

26 LCA模拟赛3T2 连边 题解

连边 题面 给定一张初始 \(n\) 个点,没有边的图。 给定 \(m\) 表示有 \(m\) 个时刻,第 \(i\) 个时刻会将 \(gcd(a,b) = m - i + 1\) 某些点连起来。 有 \(q\) 个询问,每次询问给定 \(x, y\),你需要回答 \(x, y\) 最…