iOS APP包分析工具 | 京东云技术团队

news2024/9/22 3:53:56

介绍

分享一款用于分析iOSipa包的脚本工具,使用此工具可以自动扫描发现可修复的包体积问题,同时可以生成包体积数据用于查看。这块工具我们团队内部已经使用很长一段时间,希望可以帮助到更多的开发同学更加效率的优化包体积问题。

工具下载地址

背景

APPAnalyze工具最早诞生主要是为了解决以下包体积管理的问题:

对于定位下沉市场的APP来讲,包体积是一个非常重要的性能指标,包体积过大会影响用户下载APP的意愿。但是在早期我们缺少一些手段帮助我们更高效的去进行包体积管理。

自动发现问题
  • 提升效率- 人工排查问题效率低,对于常见的问题尽可能自动扫描出来。并且对于组件化工程来讲,很多外部组件是通过Framework方式提供,没有仓库源码权限用于分析包体积问题。

  • 流程化- 形成自动化的质量流程,添加到CI流水线自动发现包体积问题。

数据指标量化
  • 包体积问题- 提供数据化平台查看每个组件的包体积待修复问题

  • 包体积大小- 提供数据化平台查看每个组件的包体积占比,包括总大小,单个文件二进制大小和每个资源大小。可以针对不同的APP版本进行组件化粒度的包体积数据对比,更方便查看每个版本的组件大小增量。

实现方式

我们选择了不依赖源码而是直接扫描二进制库的方式来实现这个能力,总体的执行流程一下:
执行流程

提示:基于组件化工程的扫描方式内部支持,只是暂时不对外开放。

使用指南

安装

无需安装。通过下载链接直接下载终端可执行命令文件APPAnalyzeCommand到本地即可使用。

APPAnalyzeCommand 下载地址

使用

$ /Users/Test/APPAnalyzeCommand --help
OPTIONS:
  --version <version>     当前版本 1.0.0
  --output <output>       输出文件目录。必传参数
  --config <config>       配置JSON文件地址。非必传参数
  --ipa <ipa>             ipa.app文件地址。必传参数
  -h, --help              Show help information.



执行

打开终端程序直接执行以下shell指令,即可生成ipa的包体积数据以及包体积待修复问题。

提示:不能直接使用AppStore的包,AppStore的包需要砸壳。建议尽量使用XCodeDebug的包。

/Users/Test/APPAnalyzeCommand --ipa ipas/JDAPP/JDAPP.app --output ipas/JDAPP



提示:如果提示permission denied没有权限,执行sudo chmod -R 777 /Users/a/Desktop/ipas/APPAnalyzeCommand即可。

生成产物

生成产物
指令执行完成以后,会在ouput参数指定的文件夹生成APPAnalyze文件夹。具体文件介绍如下:

包体积信息
  • app_size.html- 展示ipa每个framework的包体积数据,可直接用浏览器打开。

提示:按照主程序和动态库进行粒度划分

app_size.html

  • framework_size.html- 展示单个framework所有的包体积数据,二级页面不要直接打开

framework_size.html

提示:XCode生成Assets.car时会将一些小图片拼接成一张PackedAssetImage的大图片。

  • package_size.json-ipa包体积 JSON 数据
包体积待修复问题
  • app_issues.html- 展示ipa每个framework的包体积待修复问题数量,可直接用浏览器打开。

提示:按照主程序和动态库进行粒度划分
app_issues.html

  • framework_issues.html- 展示单个framework所有的待修复问题详细数据,二级页面不要单独打开

framework_issues.html

  • issues.json-ipa待修复包体积问题 JSON 数据

提示:json数据可用于搭建自己的数据平台,扩展更多的能力。例如查看不同APP版本以及支持多个APP版本对比等。

规则介绍

规则

包体积

未使用的类

定义了类没有被使用到,包含ObjC类和Swift类。

扫描规则

  • 没有查到到对应的ObjC类被引用

  • 没有被当做父类使用

  • 没有使用的字符串和类名一致

  • 没有被当做属性类型使用

  • 没有被创建或调用方法

  • 没有实现+load方法

可选的修复方式

  • 移除未使用的类

  • Swift类如果只是用了static方法考虑修改成Enum类型

  • 如果只是在类型转换时使用了也会检测出是未使用的类,例如(ABCClass *)object;。建议检查是否真的有没有到相关类后删除

  • 对于ObjC,如果只是作为方法参数类型使用也会被检测出是未使用的类。建议删除相关方法即可。

提示:删除类相对是一种安全的行为,因为删除后如果有被使用到会产生编译时错误。虽然有做字符串调用的扫描过滤,不过还是建议检查是否可能被Runtime动态创建调用

未使用的ObjC协议

定义了ObjC协议没有被类使用

扫描规则

  • 对应的协议没有被类引用

可选的修复方式

  • 移除未使用的协议
Bundle内多Scale图片

Bundle内同一张图片包含多个Scale会导致更大的包体积。

扫描规则

  • 同一个Bundle内存在同名但是scale不同的图片。例如a@2x.png/a@3x.png

可选的修复方式

  • 移除Scale更低的图片
大资源

文件大小超过一定大小的即为大资源,默认为20KB

扫描规则

  • 某个文件超过设置的大资源限额

可选的修复方式

  • 移除资源动态下发

  • 使用更小的数据格式,例如使用更小的图片格式

重复的资源文件

存在多个同样的重复文件。

扫描规则
  • 多个文件MD5一致即判定为重复文件。

可选的修复方式

  • 移除多余的文件
未使用的类Property属性

ObjC类中定义的属性没有被使用到。

扫描规则

  • 对应的属性没有被调用 set/get 方法,同时也没有被_的方式使用

  • 不是来自实现协议的属性

  • 不是来自Category的属性

  • 不存在字符串使用和属性名一致

可选的修复方式

  • 移除对应的属性

  • 如果是接口协议的属性,需要添加类实现此接口

注意事项

  • 可能存在部分动态使用的场景,需要进行一定的检查。例如一些继承NSObject的数据模型类,可能存在属性没有被直接使用到,但是可能会被传唤成JSON作为参数的情况。例如后台下发的数据模型
未使用的ImageSet/DataSet

包含的Imageset/DataSet并没有被使用到。

扫描规则

  • 未检测到和Imageset同样名字的字符串使用

可选的修复方式

  • 移除ImageSet/DataSet

注意事项

  • 某些Swift代码中使用的字符串不能被发现所以会被当做未使用。

  • 使用字符串拼接的名字作为imageset的名字。

  • 被合成到PackedAssetImage里的Imageset不能被扫描出来

未使用的ObjC方法

定义的ObjCCategory 方法并未被使用到。

扫描规则

  • 不存在和此方法一样的方法名使用

  • 不存在使用的字符串和方法名一致

  • 不是来自父类或Category的方法

  • 不是来自实现接口的方法

  • 不是属性 set/get 方法

可选的修复方式

  • 移除对应方法
未使用的分类方法

定义的ObjCCategory 方法并未被使用到。

扫描规则

  • 不存在和此方法一样的方法名使用

  • 不存在和方法名一致的字符串使用

  • 不是来自父类或Category的方法

  • 不是来自实现接口的方法

可选的修复方式

  • 移除未使用的方法

  • 如果是接口协议的方法,需要添加类实现此接口

未使用的资源文件

包含的文件资源并没有被使用到。这里的资源不包含Imageset/DataSet

扫描规则

  • 未检测到和文件名同样名字的字符串使用

可选的修复方式

  • 移除资源

注意事项

  • 某些Swift代码中使用的字符串不能被发现所以会被当做未使用

  • 使用字符串拼接的名字作为资源的名字

安全

动态反射调用ObjC类

存在类名和字符串一致,可能使用NSClassFromString()方法动态调用类。当字符串或类名变更时无法利用编译时检查发现问题,可能会导致功能异常。

扫描规则

  • 存在使用的字符串NSObject子类类名相同

可选的修复方式

  • 使用NSStringFromClass()获取类名字符串

  • 使用Framework外部的类应该使用方法封装,除了少部分功能不应该使用反射去调用

提示:包含继承NSObject的 swift 类。

ObjC属性内存申明错误

一些特殊的NSObject类型的属性内存类型申明错误,可能会导致功能异常或触发Crash

扫描规则

  • NSArray/NSSet/NSDictionary类型的属性使用strong申明

  • NSMutableArray/NSMutableSet/NSMutableDictionary类型的属性使用copy申明

可选的修复方式

  • 修改strong/copy申明
冲突的分类方法

ObjC同一个类的多个Category分类中存在多个相同的方法,由于运行时最终会加载方法可能是不确定的,可能会导致功能异常等未知的行为。

扫描规则

  • NSObject类的多个Category分类中存在多个相同的方法

修复方式

  • 移除多余的分类方法
重复的分类方法

ObjC原始类和类的Category分类中有相同的方法,分类中的方法会覆盖原始类的方法,可能会导致功能异常等未知的行为。

扫描规则

  • NSObject原始类和类的Category分类中有相同的方法

修复方式

  • 移除重复的分类方法
未实现的ObjC协议方法

类实现了某个ObjC协议,但是没有实现协议的非可选方法。可能会导致功能异常或触发Crash

扫描规则

  • 分类未实现NSObject协议的非可选方法

可选的修复方式

  • 对应的类实现缺失的非可选协议方法

  • 将对应的协议方法标识为optional可选方法

重复的ObjC类

多个动态库静态库之间存在同样的。不会导致编译失败,但是运行时只会使用其中一个类,可能会导致功能异常或触发Crash。同时会增加包体积

扫描规则

  • 多个动态库静态库之间存在同样的NSObject类符号

可能的修复方式

  • 移除重复的类

性能

使用动态库

使用动态库会增加启动耗时。

扫描规则

  • Macho为动态库

可选的修复方式

  • 使用静态库

  • 使用Mergeable Library

实现+load方法的类

APP启动后会执行所有+load方法,减少+load方法可以降低启动耗时。

扫描规则

  • 实现+load方法的NSObject

可选的修复方式

  • 移除+load方法

  • 使用+initialize替代

自定义配置

重要配置

systemFrameworkPaths

可以基于自身项目进行系统库目录的配置,解析工程时也会对系统库进行解析。配置系统库目录对于未使用方法的查找可以提供更多的信息避免误报。但是配置更多会导致执行的更慢,建议至少配置Foundation/UIKit

unusedObjCProperty-enable

unusedObjCProperty规则默认不开启。

  • 开启未使用属性检查以后,会扫描macho__TEXT段,会增加分析的耗时。
unusedClass-swiftEnable

unusedClass-swiftEnable默认不开启。

  • 开启Swift类检查以后,会扫描macho__TEXT段,会增加分析的耗时。

  • 未使用Swift类的项目建议不要开启,如果考虑执行性能的话Swift使用相对比较多的再开启。

提示:扫描macho__TEXT段需要使用XCodeRun编译出的包,不能直接使用用于上架APP Store构建出的包。主要是Debug会包含更多的信息用于扫描。

配置属性

/Users/Test/APPAnalyzeCommand -ipa /Users/Desktop/ipas/APPMobile/APPMobile.app -config /Users/Desktop/ipas/config.json --output /Users/Desktop/ipas/APPMobile



可基于自身项目需要,添加下列规则可配置参数。在使用APPAnalyzeCommand指令时添加--config配置文件地址。

{
    "systemFrameworkPaths": ["/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/System/Library/PrivateFrameworks/UIKitCore.framework/UIKitCore", "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation",
        "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/System/Library/Frameworks/Foundation.framework/Foundation"
    ], // 配置系统库。会极大增加未使用方法的误报
    "rules": {
        "dynamicCallObjCClass": { // 动态调`ObjC类
            "enable": false, // 是否启用
            "excludeClasslist": [ // 过滤类名
                "NSObject",
                "param"
            ]
        },
        "incorrectObjCPropertyDefine": { // 错误的 ObjC 属性定义
            "enable": false // 是否启动
        },
        "largeResource": { // 大资源
            "maxSize": 20480 // 配置大资源判定大小。默认 20480Byte=20KB
        },
        "unusedObjCProperty": { // 未使用的 ObjC 属性
          "enable": false, // 是否启用。默认不开启
          "excludeTypes": ["NSString", "NSArray", "NSDictionary", "NSNumber", "NSMutableArray", "NSMutableDictionary", "NSSet"] // 过滤掉部分类型的属性
        },
        "unusedClass": { // 未使用的类
            "swiftEnable": false, // 是否支持 Swift 类。默认不支持
            "excludeSuperClasslist": ["JDProtocolHandler", "JDProtocolScheme"],// 如果类继承了某些类就过滤
            "excludeProtocols": ["RCTBridgeModule"], // 如果类实现了某些协议就过滤
            "excludeClassRegex": ["^jd.*Module$", "^PodsDummy_", "^pg.*Module$", "^SF.*Module$"] // 过滤掉名字符合正则表达式的类
        },
        "unusedObjCMethod": { // 未使用的 ObjC 方法
            "excludeInstanceMethods": [""], // 过滤掉某些名字的对象方法
            "excludeClassMethods": [""], // 过滤掉某些名字的类方法
            "excludeInstanceMethodRegex": ["^jumpHandle_"], // 过滤掉名字符合正则表达式的对象方法
            "excludeClassMethodRegex": ["^routerHandle_"], // 过滤掉名字符合正则表达式的类方法
            "excludeProtocols": ["RCTBridgeModule"] // 如果类集成了某些协议就不再检查,例如 RN 方法
        },
        "loadObjCClass": { //  调用 ObjC + load 方法
            "excludeSuperClasslist": ["ProtocolHandler"], // 如果类继承了某些类就过滤
            "excludeProtocols": ["RCTBridgeModule"] // 如果类实现了某些协议就过滤,例如 RN 方法
        },
        "unusedImageset": { // 未使用 imageset
            "excludeNameRegex": [""] // 过滤掉名字符合正则表达式的imageset
        },
        "unusedResource": { // 未使用资源
            "excludeNameRegex": [""] // 过滤掉名字符合正则表达式的资源
        }
    }
}




组件化工程扫描

可以基于APPAnalyzeCore.framework定制实现自己的组件化工程扫描,或者添加基于自身组件化工程的检查规则。详情可以看Demo

基于组件化扫描方式有以下优势:

  • 细化数据粒度- 可以细化每个模块的包体积和包体积问题,更容易进行包体积优化。

  • 更多的检查- 例如检查不同组件同一个Bundle包含同名的文件,不同组件包含同一个category方法的的实现。

  • 检查结果更准确- 例如ObjC未使用方法的检查,只要存在一个和方法名同样的调用就表示方法有被使用到。但是整个ipa中可能存在很多一样的方法名但是只有一个方法有真正被调用到,如果细分到组件的粒度就可以发现更多问题。

提示:只有APP主工程无代码,全部通过子组件以framework的形式导入二进制库的方式的工程才适合这种模式。

其他

扫描质量如何

这套工具我们团队内部开发加逐步完善有一年的时间了。基于此工具修改了几十个组件的包体积问题,同时不断的修复误报问题。目前现有提供的这些规则检查误报率是很低的,只有极少数几个规则可能存在误报的可能性,总体扫描质量还是很高的。

和社区开源的工具有什么差异

我们在早期调研了社区的几个同类型的开源工具,主要存在以下几个问题:

  • 扩展性不够- 无法支持项目更好的扩展定制能力,例如添加扫描规则、支持不同类型扫描方式、生成更多的报告类型。

  • 功能不全- 只提供部分能力,例如只提供未使用资源或者未使用类

  • 无法生成包体积数据- 无法生成包体积完整的数据。

  • 检查质量不高- 扫描发现的错误数据多,或者有一些问题不能被发现。

开源计划

后续一定会开源。主要是希望调整一些内部结构再开源,开源后就不方便调整。顺便修复一些常见的问题。

开源带来的好处

开源带来的好处是,部分工程可以基于自身的业务需要,扩展定制自己的扫描工具。同时也可以将一些更好的想法实现添加进来。

  • 扩展解析方式- 目前只支持ipa模式扫描,很快会开放支持project组件化工程的扫描方式。基于组件化工程的扫描可以更加准确,但是不同的公司组件化工程的构建方式可能是不一样的,有需要可以在上层定制自身组件化工程的扫描解析。

  • 扩展扫描规则- 虽然现在已经添加了比较多的通用性的规则,同时提供了一定的灵活性配置能力。但是不同的项目可能需要定制一些其他的规则,这些规则没办法通过在现有规则上添加配置能力实现。

  • 扩展数据生成- 默认包里只包含两种数据生成,包体积数据还有包体积待修复问题数据。可以扩展更多的数据生成格式,例如我们自身的项目就有添加基于组件的依赖树格式。

后续规划

组件化工程支持

添加更多用于组件化工程的扫描

对于 Swift 更好的支持

对于Swift语言只要开启XCode编译优化以后就能在生成产物的时候支持无用代码的移除,包括未使用类型未使用方法的自动移除,但是依然有部分场景不会进行优化。所以这一块也是后续完善的重点:

  • 未使用属性- 编译器不会对于未使用属性进行移除,包括classstruct的属性。

  • 未使用方法- 对于class的方法,编译器并不会进行移除,即使没有申明[@objc](https://my.oschina.net/TnhqVdFXL8vnu)进行消息派发。

相关链接

  • Github地址

作者:京东零售 何骁

来源:京东云开发者社区 转载请注明来源

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

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

相关文章

HTB Codify WriteUp

Codify 2023年11月7日 20:59:48user nmap ➜ Codify nmap -A 10.10.11.239 Starting Nmap 7.80 ( https://nmap.org ) at 2023-11-07 21:00 CST Nmap scan report for bogon (10.10.11.239) Host is up (0.14s latency). Not shown: 997 closed ports PORT STATE SERVI…

An issue was found when checking AAR metadata

一、报错信息 An issue was found when checking AAR metadata:1. Dependency androidx.activity:activity:1.8.0 requires libraries and applications that depend on it to compile against version 34 or later of the Android APIs.:app is currently compiled against …

spark的算子

spark的算子 1.spark的单Value算子 Spark中的单Value算子是指对一个RDD中的每个元素进行操作&#xff0c;并返回一个新的RDD。下面详细介绍一些常用的单Value算子及其功能&#xff1a; map&#xff1a;逐条映射&#xff0c;将RDD中的每个元素通过指定的函数转换成另一个值&am…

009 OpenCV 二值化 threshold

一、环境 本文使用环境为&#xff1a; Windows10Python 3.9.17opencv-python 4.8.0.74 二、二值化算法 2.1、概述 在机器视觉应用中&#xff0c;OpenCV的二值化函数threshold具有不可忽视的作用。主要的功能是将一幅灰度图进行二值化处理&#xff0c;以此大幅降低图像的数…

app小程序定制的重点|软件定制开发|网站搭建

app小程序定制的重点|软件定制开发|网站搭建 App小程序定制开发是近年来快速发展的一项技术服务&#xff0c;随着移动互联网的普及和用户需求的不断升级&#xff0c;越来越多的企业和个人开始关注和需求定制化的小程序开发。那么&#xff0c;对于app小程序定制开发来说&#xf…

第十五届蓝桥杯(Web 应用开发)模拟赛 1 期-大学组(详细分析解答)

目录 1.动态的Tab栏 1.1 题目要求 1.2 题目分析 1.3 源代码 2.地球环游 2.1 题目要求 2.2 题目分析 2.3 源代码 3.迷惑的this 3.1 题目要求 3.2 题目分析 3.3 源代码 4.魔法失灵了 4.1 题目要求 4.2 题目分析 4.3 源代码 5.燃烧你的卡路里 5.1 题目要求 5.2…

U-boot(四):start_armboot

本文主要探讨210的uboot启动的第二阶段&#xff0c;主要函数为start_armboot。 uboot 一阶段初始化SoC内部部件(看门狗、时钟等),初始化DDR,重定位 二阶段初始化其余硬件(iNand、网卡芯片)以及命令、环境变量等 启动打印硬件信息,进入bootdelay,读秒完后执行bootc…

(2023码蹄杯)省赛(初赛)第二场真题(原题)(题解+AC代码)

题目1&#xff1a;MC0214捡麦子 码题集OJ-捡麦子 (matiji.net) 思路: 1.第n米在前n-1米的基础上多加一个n个麦子&#xff0c;那么直接从1开始枚举&#xff0c;累加答案即可 AC_Code:C #include<bits/stdc.h> using namespace std;int main( ) {int n; cin>>n;…

ES6 — ES14 新特性

一、ES6 新特性&#xff08;2015&#xff09; 1. let和const 在ES6中&#xff0c;新增了let和const关键字&#xff0c;其中 let 主要用来声明变量&#xff0c;而 const 通常用来声明常量。let、const相对于var关键字有以下特点&#xff1a; 特性varletconst变量提升✔️全局…

NX二次开发UF_CAM_update_list_object_customization 函数介绍

文章作者&#xff1a;里海 来源网站&#xff1a;https://blog.csdn.net/WangPaiFeiXingYuan UF_CAM_update_list_object_customization Defined in: uf_cam.h int UF_CAM_update_list_object_customization(tag_t * object_tags ) overview 概述 This function provids the…

Elasticsearch:ES|QL 函数及操作符

如果你对 ES|QL 还不是很熟悉的话&#xff0c;请阅读之前的文章 “Elasticsearch&#xff1a;ES|QL 查询语言简介​​​​​​​”。ES|QL 提供了一整套用于处理数据的函数和运算符。 功能分为以下几类&#xff1a; 目录 ES|QL 聚合函数 AVG COUNT COUNT_DISTINCT 计数为近…

web:[WUSTCTF2020]朴实无华

题目 点开页面显示如下 页面显示了一行报错&#xff1a;Cannot modify header information - headers already sent by (output started at /var/www/html/index.php:3) in /var/www/html/index.php on line 4 意思为不能修改报头信息-报头已经发送(输出开始于/var/www/html/i…

Ubuntu20.04 install pnpm

npm install -g pnpm referrence link: Installation | pnpmPrerequisiteshttps://pnpm.io/installation

嵌入式系统在工业自动化中的应用

嵌入式系统在工业自动化中的应用非常广泛&#xff0c;它们通过集成控制和实时响应能力&#xff0c;实现了生产线的自动化、智能化和高效化。以下将详细介绍嵌入式系统在工业自动化中的几个重要应用领域&#xff0c;并提供一些示例代码。 1. PLC&#xff08;可编程逻辑控制器&a…

Maven 简单配置阿里云镜像

配置步骤&#xff1a; 1、找到 maven 的安装目录&#xff0c;修改settings.xml 2、在文件中找到<mirrors>标签&#xff0c;然后再标签中添加阿里云配置即可 <mirror><id>aliyunmaven</id><mirrorOf>*</mirrorOf><name>阿里云公共…

FFmpeg常用命令讲解及实战二

文章目录 前言一、ffmpeg 常用命令1、ffmpeg 的封装转换2、ffmpeg 的编转码3、ffmpeg 的基本编转码原理 二、ffprobe 常用参数1、show_format2、show_frames3、show_streams4、print_format5、select_streams 三、ffplay 的常用命令1、ffplay 常用参数2、ffplay 高级参数3、ffp…

ARCore:在Android上构建令人惊叹的增强现实体验

ARCore&#xff1a;在Android上构建令人惊叹的增强现实体验 一、 AR 介绍1.1 AR技术简介1.2 AR技术原理1.3 AR技术应用领域 二、Google的增强现实平台ARCore2.1 ARCore简介2.2 ARCore API介绍2.3 ARCore API使用示例 三、总结 一、 AR 介绍 增强现实 Augmented Reality&#x…

python中一个文件(A.py)怎么调用另一个文件(B.py)中定义的类AA详解和示例

本文主要讲解python文件中怎么调用另外一个py文件中定义的类&#xff0c;将通过代码和示例解读&#xff0c;帮助大家理解和使用。 目录 代码B.pyA.py 调用过程 代码 B.py 如在文件B.py,定义了类别Bottleneck&#xff0c;其包含卷积层、正则化和激活函数层&#xff0c;主要对…

【OpenCV实现图像:可视化目标检测框】

文章目录 概要画框函数代码实现标签美化角点美化透明效果小结 概要 目标检测框的可视化在计算机视觉和机器学习领域中是一项重要的任务&#xff0c;有助于直观地理解和评估目标检测算法的性能。通过使用Python和相关的图像处理库&#xff0c;可以轻松实现目标检测框的可视化。…

图神经网络的数学原理总结

图深度学习(Graph Deep Learning) 多年来一直在加速发展。许多现实生活问题使GDL成为万能工具&#xff1a;在社交媒体、药物发现、芯片植入、预测、生物信息学等方面都显示出了很大的前景。 本文将流行的图神经网络及其数学细微差别的进行详细的梳理和解释&#xff0c;图深度学…