Android_Kotlin

txt
`class FirstActivity : AppCompatActivity() {`
`override fun onCreate(savedInstanceState: Bundle?) {`
`super.onCreate(savedInstanceState)`
`}`
`}`

这段代码是使用 Kotlin 语言编写的 Android 应用程序中的一个活动(Activity)类。让我逐步解释其中的内容:

  1. class FirstActivity : AppCompatActivity():这是一个类的声明,类名为 FirstActivity,并且继承自 AppCompatActivity 类。AppCompatActivity 是 Android 开发中常用的一个基类,用于支持应用程序在较旧的 Android 版本上提供向后兼容性。
  2. override fun onCreate(savedInstanceState: Bundle?):这是 FirstActivity 类中的一个方法 onCreate() 的重写。在 Android 中,onCreate() 方法是活动生命周期的一部分,在活动第一次创建时被调用。savedInstanceState 参数是一个 Bundle 对象,其中包含了之前保存的活动状态信息,可以用于在活动重新创建时恢复状态。
  3. super.onCreate(savedInstanceState):这是调用父类 AppCompatActivity 中的 onCreate() 方法,确保父类中的初始化工作得以执行。

因此,这段代码定义了一个名为 FirstActivity 的活动类,当该活动第一次创建时,会调用父类的 onCreate() 方法进行初始化。

在声明 savedInstanceState 参数时,如果在类型后面添加了 ?,则表示该参数可以接受 null 值。

这样做的目的是为了允许 savedInstanceState 参数在某些情况下为 null,例如当活动或片段首次创建时,savedInstanceState 可能为 null,因为此时还没有保存任何状态信息。

在 Kotlin 中,如果没有使用 ?,则表示该参数不接受 null 值,如果在实际使用中传递了 null 值,编译器将会报错。而使用了 ? 后,表示该参数可以接受 null 值,编译器将不会报错。

因此,在 override fun onCreate(savedInstanceState: Bundle?) 中,Bundle? 表示 savedInstanceState 参数可以接受 null 值,即在某些情况下,savedInstanceState 可能为 null。

txt
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/button1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Button 1"
/>
</LinearLayout>

这段代码是一个简单的 Android 布局文件,使用 XML 格式描述了一个线性布局(LinearLayout)以及一个按钮(Button)的布局和属性。

让我解释其中的一些关键部分:

  • <LinearLayout>:这是一个布局容器,用于在垂直方向排列其子视图(例如按钮)。xmlns:android="http://schemas.android.com/apk/res/android" 是 XML 命名空间声明,它使得可以在 XML 文件中使用 Android 提供的属性和元素。
  • android:orientation="vertical":这个属性指定了线性布局的方向,即垂直方向。这意味着其中的子视图(此处为按钮)将会按照垂直方向排列。
  • android:layout_width="match_parent"android:layout_height="match_parent":这两个属性指定了布局的宽度和高度。match_parent 表示该布局将会填充其父容器的宽度或高度,以占据尽可能多的空间。
  • <Button>:这是一个按钮视图,在布局中用于响应用户的点击事件。
  • android:id="@+id/button1":这个属性为按钮指定了一个唯一的标识符,可以在 Java 代码中使用这个标识符来查找和操作这个按钮。
  • wrap_content 属性可以使得布局更加灵活,可以根据内容的大小动态调整视图的尺寸,而不是固定为特定的尺寸。
  • android:text="Button 1":这个属性为按钮设置了显示的文本内容为 “Button 1”。

因此,这段代码描述了一个垂直排列的线性布局,其中包含一个按钮,按钮显示文本为 “Button 1”。按钮的宽度会填充父容器的宽度,而高度则根据按钮文本的大小动态调整。

txt
class FirstActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.first_layout)
}
}

首先调用了 super.onCreate(savedInstanceState),以确保调用了父类的 onCreate() 方法,以便执行必要的初始化操作。

接着调用了 setContentView(R.layout.first_layout) 方法,这个方法用于设置该活动所使用的布局文件。在这里,first_layout 是指定的布局资源文件的名称,这个布局文件定义了活动的界面布局结构。

因此,这段代码的作用是在 FirstActivity 中设置了一个布局文件 first_layout 作为活动的界面布局,并在活动创建时加载该布局。

R.layout 是一个自动生成的资源标识符类,它包含了项目中所有布局文件的引用。在 Android 开发中,资源文件(如布局文件、字符串、图像等)都需要通过资源标识符来访问和引用。

当你在项目中创建布局文件时,每个布局文件都会被编译成一个资源标识符,以便在代码中进行引用。这些资源标识符都会被统一放置在 R 类的内部静态类中,而 R.layout 则是其中用于引用布局文件的子类之一。

Intent—>用于通信的消息对象

在 Android 中,Intent 是一种用于在不同组件之间进行通信的对象。它可以用于启动活动(Activity)、启动服务(Service)、发送广播(Broadcast)以及执行其他各种操作。Intent 提供了一种在不同组件之间传递数据和执行操作的机制。

Intent 本质上是一个消息对象,用于指示想要执行的操作。它可以包含以下信息:

  1. 操作(Action):指示要执行的操作,如启动活动、启动服务、发送广播等。常见的操作包括 android.intent.action.VIEW(查看操作)、android.intent.action.SEND(发送操作)、android.intent.action.MAIN(主操作)等。
  2. 数据(Data):用于指定操作的数据,可以是 URI、文件路径、文本等。例如,如果要查看网页,可以将网页的 URL 作为数据传递给 Intent。
  3. 类别(Category):用于指定操作的类别,如 android.intent.category.LAUNCHER(启动器类别)、android.intent.category.BROWSABLE(可浏览类别)等。
  4. 附加信息(Extras):用于传递额外的数据给目标组件。Extras 是键值对的形式,可以包含各种数据类型,如字符串、整数、布尔值等。

Intent 可以分为两种类型:

  • 显式 Intent:明确定义了目标组件的类名,用于启动特定的组件。
  • 隐式 Intent:没有明确指定目标组件,而是根据 Intent 的操作、数据等信息由系统来匹配合适的组件。

通过使用 Intent,Android 应用程序可以实现各种功能,例如启动新的活动、执行后台任务、发送广播等,从而实现各种复杂的交互和功能。

Kotlin直接可以:

txt
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.first_layout)
button1.setOnClickListener {
Toast.makeText(this, "You clicked Button 1", Toast.LENGTH_SHORT).show()
}
}

在 Kotlin 中,函数声明的语法是:

txt
fun 函数名(参数列表): 返回值类型 {
    // 函数体
}

其中,返回值类型在函数名和参数列表之后,使用冒号 : 来标识。在这个语法中,返回值类型是必须的,但在某些情况下,如果函数没有返回值,可以将返回值类型指定为 Unit,或者省略返回值类型(在这种情况下,编译器会自动推断返回值类型为 Unit)。例如:

kotlin
kotlin
fun greet(name: String): Unit {
    println("Hello, $name!")
}

// 或者省略返回值类型,编译器会自动推断为 Unit
fun greet(name: String) {
    println("Hello, $name!")
}
txt
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.main, menu)
return true
}

menuInflater 是 Android 开发中的一个类,用于从 XML 文件中创建菜单对象。在 Android 中,通常使用 XML 文件定义应用程序中的菜单,然后通过 MenuInflater 类将这些 XML 文件中定义的菜单加载到应用程序中的菜单对象中,以供在用户界面中显示和操作。

具体来说,menuInflater.inflate() 方法用于将一个 XML 文件中定义的菜单资源加载到一个 Menu 对象中,这样就可以在应用程序的用户界面中显示这个菜单。

在 Android 应用程序中,Activity 和 Fragment 是两种重要的组件,用于构建用户界面和处理用户交互。它们都可以包含用户界面的布局,并且可以响应用户的输入事件(如点击、滑动等)。

下面是关于 Activity 和 Fragment 的简要介绍:

Activity(活动)

  1. 定义:Activity 是 Android 应用中的一个基本组件,代表一个单独的用户界面屏幕,通常是一个窗口、一个对话框或全屏显示的窗口。
  2. 作用:Activity 主要负责管理用户与应用程序之间的交互,包括接收用户输入、处理用户操作,并在屏幕上显示相应的界面。
  3. 生命周期:Activity 具有丰富的生命周期方法,如 onCreate()onStart()onResume()onPause()onStop()onDestroy() 等,开发者可以根据需要重写这些方法来执行相应的操作。
  4. 布局:Activity 可以通过设置布局文件(XML 文件)来定义用户界面的外观和行为,也可以通过代码动态地创建和管理用户界面。

Fragment(片段)

  1. 定义:Fragment 是 Android 应用中的另一个基本组件,代表了一个可复用的用户界面模块,可以在一个 Activity 中嵌套多个 Fragment。
  2. 作用:Fragment 主要用于构建灵活的用户界面,允许开发者将应用程序的功能拆分成可重用的模块,并在不同的屏幕尺寸和设备方向下进行适配。
  3. 生命周期:Fragment 也有自己的生命周期方法,与 Activity 的生命周期方法类似,包括 onCreate()onStart()onResume()onPause()onStop()onDestroy() 等。
  4. 布局:Fragment 可以拥有自己的布局文件(XML 文件),也可以在宿主 Activity 中动态添加到布局中,允许开发者在运行时动态地添加、替换和移除 Fragment。

总的来说,Activity 通常代表一个完整的屏幕,而 Fragment 则是 Activity 中一个可重用的组成部分,可以在一个 Activity 中组合多个 Fragment 来构建复杂的用户界面。在实际开发中,Activity 和 Fragment 经常一起使用,以实现灵活和高效的用户界面设计。

在 Kotlin 中,?. 是安全调用运算符,用于在对象为非空时调用其方法或访问其属性。如果对象为 null,则安全调用运算符会短路并返回 null,而不会抛出空指针异常。

在你提供的代码中,data?.getStringExtra("data_return") 的意思是,如果 data 不为 null,则调用 getStringExtra("data_return") 方法来获取名为 “data_return” 的额外数据,否则返回 null。这种写法可以避免在 data 为 null 时引发空指针异常。

registerForActivityResult(...):这是一个用于注册 Activity Result 的函数。它接受一个 ActivityResultContract 对象作为参数,并返回一个 ActivityResultLauncher 对象。ActivityResultContract 是一个接口,用于定义活动启动和结果处理之间的合同。

Activity类中定义了7个回调方法,覆盖了Activity生命周期的每一个环节:

  • onCreate() 在Activity第一次被创建时调用

  • onStart() 由不可见到可见时调用

  • onResume()。这个方法在Activity准备好和用户进行交互的时候调用。此时的Activity一

    定位于返回栈的栈顶,并且处于运行状态。

  • onPause()。这个方法在系统准备去启动或者恢复另一个Activity的时候调用。我们通常

    会在这个方法中将一些消耗CPU的资源释放掉,以及保存一些关键数据,但这个方法的执

    行速度一定要快,不然会影响到新的栈顶Activity的使用。

  • onStop()。这个方法在Activity完全不可见的时候调用。它和onPause()方法的主要区

    别在于,如果启动的新Activity是一个对话框式的Activity,那么onPause()方法会得到执行,而onStop()方法并不会执行。

  • onDestroy()。这个方法在Activity被销毁之前调用,之后Activity的状态将变为销毁状态。

  • onRestart()。这个方法在Activity由停止状态变为运行状态之前调用,也就是Activity被重新启动了。

onPause() 方法是 Android Activity 生命周期中的一个回调方法,用于指示当前 Activity 正在失去焦点并即将暂停其可见性。当某些事件发生时,系统会调用 onPause() 方法,这些事件包括:

  1. 启动另一个 Activity:当用户启动另一个 Activity 并且当前 Activity 失去焦点时,系统会调用 onPause() 方法。例如,当用户点击应用中的按钮,打开新的 Activity 时,当前 Activity 将暂停。
  2. 打开对话框或弹出窗口:如果当前 Activity 打开了对话框、弹出了一个窗口或者其他部分覆盖了当前 Activity 但不完全遮挡,系统也会调用 onPause() 方法。
  3. 接收到来电或其他中断:当用户接收到来电、收到短信或者其他中断事件时,当前 Activity 也会暂停,系统会调用 onPause() 方法。
  4. 用户按下 Home 键或切换到最近任务列表:当用户按下 Home 键返回桌面或切换到最近任务列表时,当前 Activity 也会暂停,系统会调用 onPause() 方法。

总之,onPause() 方法的调用情况涵盖了当前 Activity 失去焦点并即将暂停可见性的各种情况。

onStart() 是 Android 活动生命周期中的一个方法,用于指示活动即将变为可见状态。当活动首次启动或从停止状态恢复到活动栈时,系统会调用 onStart() 方法。

具体情况下,onStart() 方法会在以下几种情况下被调用:

  1. 当活动首次启动:当用户启动应用程序并打开了包含该活动的界面时,系统会调用活动的 onStart() 方法。此时,活动将从不可见状态转变为可见状态。
  2. 当活动从暂停状态恢复:如果一个活动从 onPause() 状态恢复到前台状态,系统会先调用 onStart() 方法,然后调用 onResume() 方法。这种情况通常发生在用户按下返回按钮、活动恢复到前台、或者其他活动被移除而当前活动重新进入前台的情况下。

onStart() 方法中,通常执行一些与界面相关的初始化操作,比如恢复 UI 状态、注册广播接收器或者启动一些后台任务。需要注意的是,尽管活动已经变为可见状态,但此时活动并未处于用户的焦点下,用户可能无法与其进行交互。

onResume() 是 Android 活动生命周期中的一个方法,用于指示活动即将成为用户焦点并开始与用户进行交互。当活动从不可见状态变为可见状态,并且用户可以开始与其进行交互时,系统会调用 onResume() 方法。

具体情况下,onResume() 方法会在以下几种情况下被调用:

  1. 当活动首次启动:当用户首次启动应用程序并打开了包含该活动的界面时,系统会先调用 onStart() 方法,然后调用 onResume() 方法。此时,活动将从不可见状态转变为可见状态,并且用户可以开始与其进行交互。
  2. 当活动从暂停状态恢复:如果一个活动从 onPause() 状态恢复到前台状态,系统会先调用 onStart() 方法,然后调用 onResume() 方法。这种情况通常发生在用户按下返回按钮、活动恢复到前台、或者其他活动被移除而当前活动重新进入前台的情况下。
  3. 当活动从停止状态恢复:如果一个活动从 onStop() 状态恢复到前台状态,系统会依次调用 onRestart()onStart()onResume() 方法。这种情况通常发生在用户按下 Home 键后再次打开应用程序的情况下。

onResume() 方法中,通常执行一些与活动生命周期相关的操作,比如恢复用户的输入状态、启动动画效果或者连接到一些外部服务。需要注意的是,当活动处于 onResume() 状态时,它已经成为了用户焦点下的活动,并且用户可以直接与其进行交互。

image-20240422135757284

当将视图或布局的尺寸设置为 “wrap_content” 时,系统会根据其内容自动调整视图或布局的尺寸,以便刚好容纳其内

在 Android 的清单文件(AndroidManifest.xml)中声明活动(Activity)时,可以使用两种方式:

  1. <activity>...</activity>:这是一种传统的 XML 标签方式,用于定义活动的属性和行为。在 <activity> 标签中,可以指定活动的各种属性,例如名称、图标、主题等,并且可以包含其他标签和属性以提供更详细的配置。通常情况下,你可以在 <activity> 标签内部设置更多的属性,包括活动的名称、图标、主题等,以及与活动相关的其他设置。
  2. <activity/>:这是一种自闭合的 XML 标签方式,用于简单地声明一个活动而不指定任何属性或配置。这种方式适用于简单的活动声明,当你不需要指定任何属性或配置时,可以使用这种方式。例如,如果你的活动只需要基本的声明,而不需要指定任何其他属性或配置,你可以使用 <activity/> 标签。

因此,你应该根据活动的具体需求和配置选择适当的方式。如果需要指定活动的各种属性和配置,可以使用 <activity>...</activity> 标签;如果活动只需要基本的声明而不需要指定任何其他属性或配置,可以使用 <activity/> 标签。

@style/Theme.AppCompat.Dialog 是指在 Android 应用程序中使用的一个预定义的对话框主题样式。这个样式通常用于创建对话框,即弹出式窗口,以在应用程序中显示临时信息、接受用户输入或执行其他操作。

这个主题样式基于 AppCompat 库提供的默认对话框主题进行定义,并且与 AppCompat 库中其他主题一样,它提供了跨不同 Android 版本的一致外观和行为。这样,你的应用程序就可以在不同版本的 Android 上保持一致的外观和用户体验。

android:exported="false" 是 Android 清单文件中 <activity> 元素的一个属性,用于指定该活动是否能够被其他应用程序组件或者系统组件访问。具体含义如下:

  • 如果 android:exported="false",则表示该活动不会被其他应用程序或系统组件调用。这意味着该活动只能被声明它的应用程序内部的组件所访问,其他应用程序或系统组件无法直接启动或与其交互。
  • 如果 android:exported="true",则表示该活动可以被其他应用程序或系统组件调用。这意味着其他应用程序可以使用显式或隐式意图启动该活动,并且与其进行交互。

在你的示例中,android:exported="false" 意味着 DialogActivity 这个活动不会被其他应用程序或系统组件访问。它只能被声明它的应用程序内部的组件所访问,其他应用程序无法直接启动或与其交互。这通常用于内部使用的活动,例如只在应用程序内部使用的对话框或者配置界面。

在 Android 开发中,Intent(意图)是用于在不同组件之间传递数据或执行操作的对象。它是一种在 Android 应用程序中实现组件之间通信的重要机制。

Intent 主要有两种类型:显式 Intent 和隐式 Intent。

  1. 显式 Intent:用于启动应用程序内部的组件,例如启动另一个活动(Activity)、启动服务(Service)等。显式 Intent 通过指定目标组件的类名来明确指示要执行的操作。

    示例:

txt
Intent intent = new Intent(this, AnotherActivity.class);
startActivity(intent);

隐式 Intent:用于启动应用程序内或其他应用程序中具有特定功能的组件,而不需要指定目标组件的类名。隐式 Intent 根据指定的动作(Action)、数据(Data)等信息来寻找合适的组件执行操作。

示例:

  1. txt
    Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://www.example.com"));
    startActivity(intent);

Intent 的主要作用包括但不限于:

  • 启动活动、服务或广播接收器等组件。
  • 在组件之间传递数据,例如在不同活动之间传递参数。
  • 执行一些系统级别的操作,例如拨打电话、发送短信、打开网页等。

总之,Intent 是 Android 应用程序中用于实现组件之间通信和执行操作的重要机制。

在 Android 中,Bundle 是一个用来存储键值对数据的容器类。它通常被用于在不同的组件(如活动、片段)之间传递数据,或者在组件销毁和重新创建时保存和恢复数据的状态。

onCreate() 方法中,Bundle 参数 savedInstanceState 表示上一个实例状态的数据。当活动被销毁并重新创建时(例如,由于设备旋转或内存紧张),Android 系统会调用 onSaveInstanceState() 方法来保存当前的状态数据,并将其存储在 Bundle 中。然后,在活动重新创建时,系统会将之前保存的状态数据传递给 onCreate() 方法的 savedInstanceState 参数。

txt
Log.d("FirstActivity", this.toString())

this.toString() 是调用当前对象的 toString() 方法。在 Java 中,几乎所有的对象都继承自 Object 类,而 Object 类中有一个 toString() 方法,用于返回对象的字符串表示形式

当你调用 this.toString() 时,它会返回当前对象的字符串表示形式

Activity的启动模式:

  • standard
  • singleTop 单栈顶
  • singleTask 单任务
  • singleInstance 单实例

在 Kotlin 中,object 关键字用于定义单例对象。单例对象是指在程序运行期间只有一个实例存在的对象。在给定的作用域内,单例对象只能有一个实例,因此它们非常适合用于管理全局状态或提供全局访问点。

关闭所有活动并不等同于关闭应用程序的进程。在 Android 应用程序中,当你调用 finish() 方法结束一个活动时,这个活动会被销毁,但应用程序的进程仍然在运行。即使所有活动都被销毁,应用程序的进程仍然存在于系统中。

为了完全退出应用程序,有时需要调用 System.exit(0) 或者 Process.killProcess(Process.myPid()) 这样的方法来结束应用程序的进程。这样做可以确保应用程序的所有组件都被终止,包括活动、服务、广播接收器等,从而实现应用程序的完全退出。

然而,这种做法通常被视为不推荐的,因为它可能会导致用户体验上的问题,以及系统资源的浪费。通常情况下,Android 系统会自动管理应用程序的进程,并在必要时终止它们,而不需要手动干预。因此,大多数情况下,关闭所有活动即可满足应用程序退出的需求,而无需手动杀死进程。

在 Kotlin 中,companion object(伴生对象)具有以下作用:

  1. 静态成员访问:伴生对象中的成员可以直接通过类名访问,就像 Java 中的静态成员一样。这使得可以在不创建类的实例的情况下访问这些成员。
  2. 工厂方法:可以在伴生对象中定义工厂方法,用于创建类的实例。这种方法通常用于隐藏类的构造函数,提供一种更灵活的方式来创建实例。
  3. 共享代码:伴生对象可以包含在类的所有实例之间共享的代码或常量。这些代码或常量对于类的所有实例都是相同的,可以方便地通过伴生对象访问。
  4. 扩展方法:在伴生对象中还可以定义扩展方法,这些方法可以为类添加额外的功能,而无需继承或修改类的源代码。

总的来说,伴生对象提供了一种在 Kotlin 中实现类级别功能的方式,它可以用于静态成员访问、工厂方法、共享代码和扩展方法等场景。

StringBuilder是Java中的一个类,用于处理字符串。它允许你在不创建新的String对象的情况下进行字符串的修改和操作,这样可以提高性能并节省内存。

当你需要对字符串进行频繁的修改时,使用StringBuilder通常比直接使用String更高效。这是因为String是不可变的,每次对String进行修改都会创建一个新的String对象,而StringBuilder允许你在同一个对象上执行多次修改操作。

你可以使用StringBuilder的append()方法来添加字符串,使用delete()方法来删除字符串,使用insert()方法来在指定位置插入字符串,使用replace()方法来替换字符串等等。最后,你可以使用toString()方法将StringBuilder对象转换为String对象,以便进行进一步的操作或输出。

val list = listOf("Apple", "Banana", "Orange", "Pear", "Grape") val builder = StringBuilder() builder.append("Start eating fruits.\n") for (fruit in list) { builder.append(fruit).append("\n") } builder.append("Ate all fruits.") val result = builder.toString() println(result) 为什么最后要调用builder.toString(),不能直接打印吗

在上面的代码中,builder是一个StringBuilder对象,而println函数通常接受String类型的参数来进行输出。而builder对象是一个StringBuilder类型的对象,不是String类型的对象,因此无法直接传递给println函数。

调用builder.toString()方法将StringBuilder对象转换为String类型的对象,这样就可以将其作为参数传递给println函数,从而实现输出。toString()方法会返回StringBuilder对象中包含的所有字符序列作为一个字符串。

因此,为了能够正确地输出builder对象中的内容,需要先调用toString()方法将其转换为String类型的对象,然后再传递给println函数进行打印。

with 是 Kotlin 的一个标准库函数,它提供了一种简洁的方式来执行针对特定对象的一系列操作,并返回最后一个表达式的结果。

AlertDialog.Builder(this).apply { setTitle("This is Dialog") setMessage("Something important.") setCancelable(false) setPositiveButton("OK") { dialog, which -> } setNegativeButton("Cancel") { dialog, which -> } show() 是什么意思

这段代码是使用 Kotlin 的标准库函数 apply 来构建一个 AlertDialog 对话框,并设置其标题、消息、按钮等属性。下面是代码的解释:

  1. AlertDialog.Builder(this):创建了一个 AlertDialog.Builder 的实例,这个实例用于构建一个对话框。
  2. apply { ... }apply 是一个 Kotlin 标准库函数,它接收一个 lambda 表达式作为参数,并在 lambda 表达式的作用域内执行一系列操作。在这个例子中,apply 函数被调用后,会将调用者对象(即 AlertDialog.Builder 的实例)作为参数传递给 lambda 表达式,并在 lambda 表达式内部执行一系列设置操作。
  3. setTitle("This is Dialog"):在 lambda 表达式中调用 setTitle 方法,设置对话框的标题为 “This is Dialog”。
  4. setMessage("Something important."):在 lambda 表达式中调用 setMessage 方法,设置对话框的消息内容为 “Something important.”。
  5. setCancelable(false):在 lambda 表达式中调用 setCancelable 方法,设置对话框为不可取消状态,即用户点击对话框外部或返回键时不会关闭对话框。
  6. setPositiveButton("OK") { dialog, which -> ... }:在 lambda 表达式中调用 setPositiveButton 方法,设置对话框的确定按钮文本为 “OK”,并设置点击事件处理器。在这里,{ dialog, which -> ... } 是一个 lambda 表达式,表示当用户点击确定按钮时执行的操作。在本例中,lambda 表达式为空,即不执行任何操作。
  7. setNegativeButton("Cancel") { dialog, which -> ... }:在 lambda 表达式中调用 setNegativeButton 方法,设置对话框的取消按钮文本为 “Cancel”,并设置点击事件处理器。同样,{ dialog, which -> ... } 是一个 lambda 表达式,表示当用户点击取消按钮时执行的操作。在本例中,lambda 表达式为空,即不执行任何操作。
  8. show():在所有设置完成后,调用 show 方法显示对话框。

因此,这段代码的作用是创建一个带有标题、消息、确定按钮和取消按钮的对话框,并将其显示在界面上。

三种基本布局:

  • LinearLayout垂直排布
  • RelativeLayout相对布局
  • FrameLayout帧布局

image-20240423231325479

override fun getView(position: Int, convertView: View?, parent: ViewGroup): View { val view = LayoutInflater.from(context).inflate(resourceId, parent, false) val fruitImage: ImageView = view.findViewById(R.id.fruitImage) val fruitName: TextView = view.findViewById(R.id.fruitName) val fruit = getItem(position) // 获取当前项的Fruit实例 if (fruit != null) { fruitImage.setImageResource(fruit.imageId) fruitName.text = fruit.name } return view }

其中:val view = LayoutInflater.from(context).inflate(resourceId, parent, false)

作用是从 XML 布局文件中创建一个视图对象,并将其添加到指定的父视图中。

解释每个参数的含义:

  • context: 表示当前的上下文环境,通常是一个 Activity 或 Fragment 的实例。
  • resourceId: 表示要加载的布局文件的资源 ID,即 XML 文件的唯一标识符。
  • parent: 表示要将创建的视图添加到的父视图,通常是一个 ViewGroup,比如一个 LinearLayout 或者一个 RecyclerView。
  • false: 表示在加载布局文件时,不将其添加到父视图中。这个参数设置为 false 表示我们会手动将视图添加到父视图中,而不是在加载时自动添加。

接口在编程中有多种作用,包括但不限于以下几个方面:

  1. 定义约束和契约:接口定义了一组方法或属性的规范,实现该接口的类必须提供这些方法或属性的具体实现。这种约束和契约使得代码更加清晰,使得不同的类可以共享相同的行为规范。
  2. 实现多态:通过接口,可以实现多态,即在不同的类中使用相同的方法名,但实际调用的是各自类的具体实现。这样可以提高代码的灵活性和可扩展性。
  3. 代码重用:接口可以用于定义通用的行为规范,使得多个类可以共享相同的接口定义,从而实现代码的重用。当多个类具有相似的行为或功能时,可以通过接口来统一定义这些行为或功能,避免重复编写代码。
  4. 降低耦合性:通过接口,类与类之间的耦合度可以降低,因为类之间通过接口进行交互,而不是直接依赖于具体的实现。这样,当一个类的实现发生变化时,只需要修改实现该接口的类,而不需要修改其他使用该类的代码。
  5. 接口委托:接口支持委托,一个接口可以通过另一个对象来实现其方法,这种方式称为接口委托。这种机制可以进一步提高代码的灵活性和可复用性。

总的来说,接口是一种重要的编程工具,可以帮助程序员设计出更加灵活、可扩展和易于维护的代码结构。

interface接口

sealed class密封类

image-20240429211327595

companion object 是 Kotlin 中的一个关键字,它用于创建一个伴随对象。伴随对象是类中的一个单例对象,可以通过类名直接访问其中的属性和方法

news_content_frag.xml——–>NewsContentFragment类———–>NewsContentActivity

news_item.xml——–>news_title_frag.xml———>NewsTitleFragment类———->

layout/activity_main.xml——->单页模式;

NewsTitleFragment类————>

​ layout-sw600dp/activity_main.xml——–>双页模式;

NewsContentFragment类——->

在NewsTitleFragment类中通过RecyclerView将新闻列表展示出来

在 Kotlin 中,open 关键字用于声明一个类、方法或属性是可以被继承或覆盖的。具体来说:

  • 类(Class):在类声明前加上 open 关键字,表示这个类是可以被其他类继承的。如果不加 open 关键字,则默认情况下类是 final 的,不能被继承。
txt
kotlin
open class BaseActivity : AppCompatActivity() {
    // 可以被继承的类
}
  • 方法(Method):在方法声明前加上 open 关键字,表示这个方法是可以被子类覆盖(重写)的。如果不加 open 关键字,则默认情况下方法是 final 的,不能被子类覆盖。
txt
kotlin
open fun someMethod() {
    // 可以被子类重写的方法
}
  • 属性(Property):在属性声明前加上 open 关键字,表示这个属性是可以被子类覆盖的。如果不加 open 关键字,则默认情况下属性是 final 的,不能被子类覆盖。
txt
kotlin
open val someProperty: Int = 0

使用 open 关键字可以让类的设计更加灵活,允许其他类继承并重写其中的方法,或者覆盖属性的行为。

val square: (Int) -> Int = { x: Int -> x * x }

square是(Int) -> Int函数类型的变量,表示接受一个 Int 类型的参数,并返回一个 Int 类型的结果。

Lambda 表达式 { x: Int -> x * x } 被赋给了这个变量

fun save(inputText: String) {
try {
val output = openFileOutput("data", Context.MODE_PRIVATE)
val writer = BufferedWriter(OutputStreamWriter(output))
writer.use {
it.write(inputText)
}
} catch (e: IOException) {
e.printStackTrace()
}
}

这段代码定义了一个名为 save 的函数,它接受一个 inputText 参数,类型为 String。函数的作用是将输入的文本内容保存到文件中。让我解释一下代码的逻辑:

  1. openFileOutput("data", Context.MODE_PRIVATE): 这行代码打开一个名为 “data” 的文件,并返回一个 FileOutputStream 对象。这个文件将会存储在应用的内部存储空间中,因为使用了 Context.MODE_PRIVATE 参数,表示只有当前应用可以访问这个文件,并且会覆盖掉同名的文件(如果存在)。
  2. val writer = BufferedWriter(OutputStreamWriter(output)): 这行代码创建了一个 BufferedWriter 对象,并将其包装在一个 OutputStreamWriter 中,以便将文本写入到 output 中。
  3. writer.use { it.write(inputText) }: 这行代码使用 Kotlin 的 use 函数,确保在使用结束后正确关闭 writer,以释放资源。在 use 函数的 lambda 表达式中,调用了 write 方法,将 inputText 写入到文件中。
  4. catch (e: IOException) { e.printStackTrace() }: 这是一个异常处理块,如果在保存文件时发生了 IOException 异常,程序将会打印异常的堆栈信息。

将委托功能分为了两种:类委托和委托属性

Inference_Framework

PNNX
PNNX项目 PyTorch Neural Network eXchange(PNNX)是PyTorch模型互操作性的开放标准。PNNX为PyTorch提供了一种开源的模型格式,它定义了与Pytorch相匹配的数据流图和运算图,我们的框架在PNNX之上封装了一层更加易用和简单的计算图格式。pytorch训练好一个模型之后,然后模型需要转换到pnnx格式,然后pnnx格式我们再去读取,形成计算图.

pytorch到我们计算图?

PNNX帮我做了很多的图优化、算子融合的工作,所以底层的用它PNNX的话,我们可以吸收图优化的结果,后面推理更快.

但是不直接在项目中用PNNX,因为别人的工作和自己推理框架开发思路总是有不同的。所以在这上面封装,又快速又好用方便,符合自己的使用习惯。

我们只是去读取PNNX产物,然后构建自己一种易用的计算图结构。

产物:resnet18.pnnx.param PNNX graph definition 结构定义

resnet18.pnnx.bin PNNX model weight 权重

PNNX的格式定义:

PNNX由操作数operand(运算数)和operator(运算符号),PNNX::Graph用来管理和操作这两者。

操作数(operand),也可以通过操作数来方向访问到这个数字的产生者和使用者Customer

Operand有以下几个部分组成:

Producer: 类型是operator, 表示产生了这个操作数的运算符(operator). 也就是说这个操作数(operand)是Producer的输出. Producer这个操作符号产生了当前的Operand
Customer:类型是operator, 表示需要这个操作数下一个操作的的运算符(operator),也就是说这个操作数(operand)作为Customer的输入存在.

Name: 类型是std::string, 表示这个操作数的名称.Values
Shape: 类型是std::vector , 用来表示操作数的大小,

this:指针,指向当前对象的地址。在类的成员函数中,this关键字指向当前对象。

->:成员访问运算符,用来访问类的成员变量或成员函数。

在 C++11 中,使用 new 创建动态分配的对象并不安全,因为需要手动管理资源的释放,容易出现内存泄漏或者忘记释放资源导致的内存泄漏。为了更加安全和方便地管理动态分配的对象,C++11 引入了智能指针,其中 std::unique_ptr 是一种独占所有权的智能指针,它负责在对象不再需要时释放所占用的内存。

图(graph) 节点(vertex) 边(edge)

电路Learning

Screenshot_20240413_081729_com.able.wisdomtree_ed

IMG_20240413_100936

IMG_20240413_100941

一阶电路三要素法:
https://zhuanlan.zhihu.com/p/367671862

续流二极管的作用:当输入电压由变+VCC为0V时,三极管由饱和变为截止,这样继电器电感线圈中的电流突然失去了流通通路,若无续流二极管D将在线圈两端产生较大的反向电动势,极性为下正上负,电压值可达一百多伏,这个电压加上电源电压作用在三极管的集电极上足以损坏三极管。故续流二极管D的作用是将这个反向电动势通过图中箭头所指方向放电,使三极管集电极对地的电压最高不超过+VCC +0.7V。

image-20240415081034319

桥式全波整流电路

img

img

img

image-20240527141313565

image-20240527141401386

衰减电阻网络需要搭配上电容来进行补偿是什么意思

在电子电路中,衰减电阻网络通常是指由电阻组成的网络,用于降低信号的电压或电流。而提到衰减电阻网络需要搭配电容来进行补偿,这通常是指在某些电路设计中,为了改善电路的性能,需要在不改变电路基本功能的前提下,通过添加电容元件来修正或改善电路的某些特性。
补偿电容的作用可能包括:

  1. 改善频率响应:在某些电路中,电阻网络可能会引入一定的相位偏移,导致电路在高频工作时性能变差。添加电容可以补偿这种相位偏移,从而改善电路的带宽和频率响应。
  2. 减少噪声:电容可以起到滤波的作用,减少电路中的噪声成分,使输出信号更干净。
  3. 改善稳定性:在某些电路中,电容可以用来改善系统的稳定性,例如在反馈电路中,适当的电容值可以帮助电路更快地稳定在工作点。
  4. 消除振荡:如果电路中存在不需要的振荡,适当的电容值可以用来消除这些振荡。
  5. 定时作用:在某些振荡电路中,电容与电阻配合使用,可以决定振荡频率。
    补偿电容的值和位置需要根据具体的电路设计和所需的性能来确定。通常,电路设计者会根据电路的频率特性、相位特性以及所需的带宽等因素来选择合适的电容类型和值。

为什么添加电容可以补偿这种相位偏移

在电路中,电阻和电容都会引入相位偏移。电阻器的相位偏移通常与频率成正比,而电容器则与频率成反比.为了补偿这种相位偏移,电路设计者会在电路中添加电容器,以便在高频应用中提供额外的相位移动,从而抵消电阻引起的相位偏移。通过这种方式,电路可以在整个频率范围内保持稳定的相位响应,从而提高电路的整体性能。

pcl

``c make -DCMAKE_BUILD_TYPE=None `
-DCMAKE_INSTALL_PREFIX=/home/zgh/pcl_1.9.1_compile \
-DBUILD_GPU=ON \
-DBUILD_apps=ON \
-DBUILD_examples=ON

-DCUDA_TOOLKIT_ROOT_DIR=/usr/local/cuda-12.2 \

-DCUDA_ARCH_BIN=8.6 \

-DCUDA_ARCH_PTX=8.6 ..

cmake
  if(NOT ${CUDA_VERSION_STRING} VERSION_LESS "10.0")
    set(__cuda_arch_bin "3.0 3.5 5.0 5.2 5.3 6.0 6.1 7.0 7.2 7.5")
  elseif(NOT ${CUDA_VERSION_STRING} VERSION_LESS "9.1")
    set(__cuda_arch_bin "3.0 3.5 5.0 5.2 5.3 6.0 6.1 7.0 7.2")
  elseif(NOT ${CUDA_VERSION_STRING} VERSION_LESS "9.0")
    set(__cuda_arch_bin "3.0 3.5 5.0 5.2 5.3 6.0 6.1 7.0")  
  elseif(NOT ${CUDA_VERSION_STRING} VERSION_LESS "8.0")
    set(__cuda_arch_bin "2.0 2.1(2.0) 3.0 3.5 5.0 5.2 5.3 6.0 6.1")
  elseif(NOT ${CUDA_VERSION_STRING} VERSION_LESS "6.5")
    set(__cuda_arch_bin "2.0 2.1(2.0) 3.0 3.5 5.0 5.2")
  elseif(NOT ${CUDA_VERSION_STRING} VERSION_LESS "6.0")
    set(__cuda_arch_bin "2.0 2.1(2.0) 3.0 3.5 5.0")
  elseif(NOT ${CUDA_VERSION_STRING} VERSION_LESS "5.0")
    set(__cuda_arch_bin "2.0 2.1(2.0) 3.0 3.5")
  elseif(${CUDA_VERSION_STRING} VERSION_GREATER "4.1")
    set(__cuda_arch_bin "2.0 2.1(2.0) 3.0")
  else()
    set(__cuda_arch_bin "2.0 2.1(2.0)")
  endif()

NXHAY2OW76-eyJsaWNlbnNlSWQiOiJOWEhBWTJPVzc2IiwibGljZW5zZWVOYW1lIjoiSHVuYW4gSW5zdGl0dXRlIG9mIFNjaWVuY2UgYW5kIFRlY2hub2xvZ3kiLCJsaWNlbnNlZVR5cGUiOiJDTEFTU1JPT00iLCJhc3NpZ25lZU5hbWUiOiJ0bXUgaXRtYW5hZ2VyIiwiYXNzaWduZWVFbWFpbCI6InRtdWl0bWFuYWdlckBvdXRsb29rLmNvbSIsImxpY2Vuc2VSZXN0cmljdGlvbiI6IkZvciBlZHVjYXRpb25hbCB1c2Ugb25seSIsImNoZWNrQ29uY3VycmVudFVzZSI6ZmFsc2UsInByb2R1Y3RzIjpbeyJjb2RlIjoiR08iLCJwYWlkVXBUbyI6IjIwMjQtMDItMDkiLCJleHRlbmRlZCI6ZmFsc2V9LHsiY29kZSI6IlJTMCIsInBhaWRVcFRvIjoiMjAyNC0wMi0wOSIsImV4dGVuZGVkIjpmYWxzZX0seyJjb2RlIjoiRE0iLCJwYWlkVXBUbyI6IjIwMjQtMDItMDkiLCJleHRlbmRlZCI6ZmFsc2V9LHsiY29kZSI6IkNMIiwicGFpZFVwVG8iOiIyMDI0LTAyLTA5IiwiZXh0ZW5kZWQiOmZhbHNlfSx7ImNvZGUiOiJBQyIsInBhaWRVcFRvIjoiMjAyNC0wMi0wOSIsImV4dGVuZGVkIjpmYWxzZX0seyJjb2RlIjoiUlNVIiwicGFpZFVwVG8iOiIyMDI0LTAyLTA5IiwiZXh0ZW5kZWQiOmZhbHNlfSx7ImNvZGUiOiJSU0MiLCJwYWlkVXBUbyI6IjIwMjQtMDItMDkiLCJleHRlbmRlZCI6dHJ1ZX0seyJjb2RlIjoiUEMiLCJwYWlkVXBUbyI6IjIwMjQtMDItMDkiLCJleHRlbmRlZCI6ZmFsc2V9LHsiY29kZSI6IkRTIiwicGFpZFVwVG8iOiIyMDI0LTAyLTA5IiwiZXh0ZW5kZWQiOmZhbHNlfSx7ImNvZGUiOiJSRCIsInBhaWRVcFRvIjoiMjAyNC0wMi0wOSIsImV4dGVuZGVkIjpmYWxzZX0seyJjb2RlIjoiUkMiLCJwYWlkVXBUbyI6IjIwMjQtMDItMDkiLCJleHRlbmRlZCI6ZmFsc2V9LHsiY29kZSI6IlJTRiIsInBhaWRVcFRvIjoiMjAyNC0wMi0wOSIsImV4dGVuZGVkIjp0cnVlfSx7ImNvZGUiOiJSTSIsInBhaWRVcFRvIjoiMjAyNC0wMi0wOSIsImV4dGVuZGVkIjpmYWxzZX0seyJjb2RlIjoiSUkiLCJwYWlkVXBUbyI6IjIwMjQtMDItMDkiLCJleHRlbmRlZCI6ZmFsc2V9LHsiY29kZSI6IkRQTiIsInBhaWRVcFRvIjoiMjAyNC0wMi0wOSIsImV4dGVuZGVkIjpmYWxzZX0seyJjb2RlIjoiREIiLCJwYWlkVXBUbyI6IjIwMjQtMDItMDkiLCJleHRlbmRlZCI6ZmFsc2V9LHsiY29kZSI6IkRDIiwicGFpZFVwVG8iOiIyMDI0LTAyLTA5IiwiZXh0ZW5kZWQiOmZhbHNlfSx7ImNvZGUiOiJQUyIsInBhaWRVcFRvIjoiMjAyNC0wMi0wOSIsImV4dGVuZGVkIjpmYWxzZX0seyJjb2RlIjoiUlNWIiwicGFpZFVwVG8iOiIyMDI0LTAyLTA5IiwiZXh0ZW5kZWQiOnRydWV9LHsiY29kZSI6IldTIiwicGFpZFVwVG8iOiIyMDI0LTAyLTA5IiwiZXh0ZW5kZWQiOmZhbHNlfSx7ImNvZGUiOiJQU0kiLCJwYWlkVXBUbyI6IjIwMjQtMDItMDkiLCJleHRlbmRlZCI6dHJ1ZX0seyJjb2RlIjoiUENXTVAiLCJwYWlkVXBUbyI6IjIwMjQtMDItMDkiLCJleHRlbmRlZCI6dHJ1ZX0seyJjb2RlIjoiUlMiLCJwYWlkVXBUbyI6IjIwMjQtMDItMDkiLCJleHRlbmRlZCI6dHJ1ZX0seyJjb2RlIjoiRFAiLCJwYWlkVXBUbyI6IjIwMjQtMDItMDkiLCJleHRlbmRlZCI6dHJ1ZX0seyJjb2RlIjoiUERCIiwicGFpZFVwVG8iOiIyMDI0LTAyLTA5IiwiZXh0ZW5kZWQiOnRydWV9XSwibWV0YWRhdGEiOiIwMTIwMjMxMTA5TFBBQTAwOTAwNyIsImhhc2giOiI0MjU0OTY3OS8xMzU2NTA1OTotNDU5NTIyNTciLCJncmFjZVBlcmlvZERheXMiOjcsImF1dG9Qcm9sb25nYXRlZCI6ZmFsc2UsImlzQXV0b1Byb2xvbmdhdGVkIjpmYWxzZSwidHJpYWwiOmZhbHNlLCJhaUFsbG93ZWQiOnRydWV9-t3Mcnh+cc/DF5z54xXxQ1wh2DTHULDDp0xl9P1s3jRugff7MKaHhYu8MFuKB8smfDaUysLfs94WjunQJeCc4L/gMi024G9o/O2yBx4/Ho9yU7SeYOvnuMqPwwpczR/U2JcIZAhH9YPdOo5E7CEtPEW5cq774wN7MrXnHK+LPN6uE4asZ/Qk3g3TyqpD3R7ubTmtkAx8JF6iWrezyLNngezgq3NkSE+3LZFuOLep6EKsOJeuaPCKD1uSFJZK7yzUkcLq+H/AZDOPZ+Gk9ZTl+P8TlRw3DIA1WDMORmycx5Q4mG+y2cNJoj9r0gfZPiw8OcmcQI8icyF2yTLnWOopRUg==-MIIETDCCAjSgAwIBAgIBDzANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDDA1KZXRQcm9maWxlIENBMB4XDTIyMTAxMDE2MDU0NFoXDTI0MTAxMTE2MDU0NFowHzEdMBsGA1UEAwwUcHJvZDJ5LWZyb20tMjAyMjEwMTAwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC/W3uCpU5M2y48rUR/3fFR6y4xj1nOm3rIuGp2brELVGzdgK2BezjnDXpAxVDw5657hBkAUMoyByiDs2MgmVi9IcqdAwpk988/Daaajq9xuU1of59jH9eQ9c3BmsEtdA4boN3VpenYKATwmpKYkJKVc07ZKoXL6kSyZuF7Jq7HoQZcclChbF75QJPGbri3cw9vDk/e46kuzfwpGftvl6+vKibpInO6Dv0ocwImDbOutyZC7E+BwpEm1TJZW4XovMBegHhWC04cJvpH1u98xoR94ichw0jKhdppywARe43rGU96163RckIuFmFDQKZV9SMUrwpQFu4Z2D5yTNqnlLRfAgMBAAGjgZkwgZYwCQYDVR0TBAIwADAdBgNVHQ4EFgQU5FZqQ4gnVc+inIeZF+o3ID+VhcEwSAYDVR0jBEEwP4AUo562SGdCEjZBvW3gubSgUouX8bOhHKQaMBgxFjAUBgNVBAMMDUpldFByb2ZpbGUgQ0GCCQDSbLGDsoN54TATBgNVHSUEDDAKBggrBgEFBQcDATALBgNVHQ8EBAMCBaAwDQYJKoZIhvcNAQELBQADggIBANLG1anEKid4W87vQkqWaQTkRtFKJ2GFtBeMhvLhIyM6Cg3FdQnMZr0qr9mlV0w289pf/+M14J7S7SgsfwxMJvFbw9gZlwHvhBl24N349GuthshGO9P9eKmNPgyTJzTtw6FedXrrHV99nC7spaY84e+DqfHGYOzMJDrg8xHDYLLHk5Q2z5TlrztXMbtLhjPKrc2+ZajFFshgE5eowfkutSYxeX8uA5czFNT1ZxmDwX1KIelbqhh6XkMQFJui8v8Eo396/sN3RAQSfvBd7Syhch2vlaMP4FAB11AlMKO2x/1hoKiHBU3oU3OKRTfoUTfy1uH3T+t03k1Qkr0dqgHLxiv6QU5WrarR9tx/dapqbsSmrYapmJ7S5+ghc4FTWxXJB1cjJRh3X+gwJIHjOVW+5ZVqXTG2s2Jwi2daDt6XYeigxgL2SlQpeL5kvXNCcuSJurJVcRZFYUkzVv85XfDauqGxYqaehPcK2TzmcXOUWPfxQxLJd2TrqSiO+mseqqkNTb3ZDiYS/ZqdQoGYIUwJqXo+EDgqlmuWUhkWwCkyo4rtTZeAj+nP00v3n8JmXtO30Fip+lxpfsVR3tO1hk4Vi2kmVjXyRkW2G7D7WAVt+91ahFoSeRWlKyb4KcvGvwUaa43fWLem2hyI4di2pZdr3fcYJ3xvL5ejL3m14bKsfoOv

pcl::PointCloudpcl::PCLPointCloud2 是 PCL 中两种不同的点云数据结构,它们之间的主要区别在于数据的组织形式和灵活性:

  1. pcl::PointCloud
    • pcl::PointCloud 是 PCL 中用于表示点云的模板类。
    • 它是一种比较高级的数据结构,已经预定义了点云中每个点的字段(如坐标、法向量等)以及数据类型(如PointXYZ、Normal等)。
    • 使用 pcl::PointCloud 可以更方便地访问和处理点云数据,因为它提供了成员函数来操作点云中的点,如添加、删除、修改等操作。
  2. pcl::PCLPointCloud2
    • pcl::PCLPointCloud2 是 PCL 中用于表示点云的更底层、更通用的数据结构。
    • 它是一种更灵活的数据结构,可以容纳任意类型和数量的字段,适合表示各种形式的点云数据。
    • 使用 pcl::PCLPointCloud2 需要通过字段的偏移量和数据类型来手动解析和访问点云数据,相对复杂一些。

总的来说,pcl::PointCloud 更适合处理已知结构和类型的点云数据,而 pcl::PCLPointCloud2 则更适合处理未知结构或需要更大灵活性的点云数据。在实际应用中,根据具体需求选择合适的数据结构进行点云数据的处理和操作。

std::cerr 通常用于输出程序运行时的错误信息、警告信息等

Embedded

为什么原理图里的stm32f4的VCAP1引脚要接一个4.7微法的电容,再接地呢

2023/12/25 08:23:32

STM32F4芯片的VCAP1引脚是芯片内部电容的引出端,用于连接外部电容以提供给芯片内部振荡电路使用。在使用高速外设时,由于这些外设需要非常稳定的电源供应,因此需要在VCAP1引脚与地之间连接一个电容来提高芯片的稳定性。

具体来说,连接4.7微法的电容可以起到平滑电压、提高电源噪声抑制能力等作用,从而提高芯片的工作稳定性和可靠性。此外,需要注意电容的选型要符合芯片手册的要求,不能超出规定的范围。

2023/12/25 08:26:15
芯片内部还有电容吗

2023/12/25 08:26:20

是的,芯片内部通常会包含一些电容。这些内部电容主要用于稳定芯片的电源供应和进行滤波。它们的作用包括:

txt
电源滤波:在芯片内部集成了一些小型电容器,用于过滤电源中的噪声和干扰,确保芯片正常运行所需的电源干净和稳定。

芯片电源稳定:芯片内部可能还包含一些供电相关的电容,用于提供瞬态响应和电源稳定性,以确保芯片在各种工作条件下都能正常工作。

这些内部电容一般由芯片制造商在设计阶段根据具体需求添加,并在芯片手册或参考设计中进行了详细说明。在使用芯片时,我们不需要特别处理这些内部电容,只需按照芯片手册的要求合理连接外部电容即可。

2023/12/25 08:26:41
那为什么还要连接外部电容

2023/12/25 08:26:48

连接外部电容主要是为了进一步提高芯片的电源稳定性和抑制电磁干扰。虽然芯片内部已经包含了一些电容,但这些电容的容值较小且位置相对固定,可能无法满足某些特殊应用或高要求的电源稳定性。

通过在VCAP1引脚与地之间连接外部电容,可以实现以下效果:

txt
改善电源噪声抑制能力:外部电容可以提供更大的容值,能够更好地滤除电源中的高频噪声和纹波,从而提供更稳定的电源供应。

提供额外的瞬态响应:外部电容能够快速响应芯片工作状态的变化,提供更好的瞬态响应能力,尤其在高速外设工作时,可以提供更稳定的电源给这些外设。

抑制电磁干扰:外部电容能够帮助减少电源线上的电磁辐射和接收到的外界干扰信号,提高系统的抗干扰能力,保证芯片的正常运行。

需要注意的是,具体的外部电容选型和连接方式应根据芯片厂商提供的参考设计或芯片手册的建议进行,以确保电路的稳定性和可靠性。

img

image-20231228133639969

image-20231228133811569配置通道 具有检测正反插…..等

image-20231228134014238

边带使用实现…..

image-20231228134605423

image-20231228134230069

image-20231228134310310

image-20231228142350256

image-20231228142627629

image-20231228142731948OSC32IN引脚,用于连接外部低速晶体振荡器(32.768 kHz)。这种振荡器通常用于实时时钟(RTC)的时基。

OSC_IN引脚,用于连接外部高速晶体振荡器(通常在4 MHz到26 MHz之间)。这种振荡器通常用于系统时钟(SYSCLK)的时基。

VBAT代表电池供电引脚(Voltage Battery)。VBAT引脚用于连接外部备用电池,通常是一个小型电池,以提供芯片的备份电源。

VCAP1是指STM32系列芯片上的一个电容滤波器引脚,用于为芯片内部提供稳定的电源环境
,用于去除芯片电源中的高频噪声和波动。

image-20240102113359669

image-20240102144257554在电路设计中,加入0欧电阻(也称为短接电阻)有以下几个常见的目的:

  1. 电路连接:0欧电阻可以作为电路的连接点,将不同信号线或电源线连接在一起。它可以提供良好的电气连接,并保持信号或电流的连续性。
  2. 信号分配:在复杂的电路板上,使用0欧电阻可以方便地将信号线分配到不同的位置。通过添加或移除0欧电阻,可以改变信号路径,以满足电路的布局要求。
  3. 调试和测试:在调试和测试电路时,加入0欧电阻可以方便地连接测试仪器或测量点。它可以用作测试点或测量点的连接线,以便在需要时轻松接入测试设备。
  4. 阻抗匹配:在高频电路设计中,0欧电阻可以用于阻抗匹配。通过选择适当的阻值,可以使电路中的阻抗更好地匹配,以最大限度地传输信号或功率。

需要注意的是,加入0欧电阻并不会引入电阻本身的阻尼效应。它的主要作用是提供连接和分配功能,而不会对电路的整体电性能产生实质性的影响。

image-20240103170615099

TPS3823-33DBVR的MR引脚是干什么的

1/3/2024, 5:11:40 PM

TPS3823-33DBVR是一款超低功耗、微型化的复位监测器。MR引脚是器件的主复位引脚,用于手动地对器件进行复位操作。

当MR引脚被拉低时,TPS3823-33DBVR会立即进行复位操作,并将RST引脚拉低,使被监测的系统或芯片得到重新启动。此外,当MR引脚保持低电平时,TPS3823-33DBVR将始终保持在复位状态,直到MR引脚上升到高电平。

需要注意的是,MR引脚应该在正常工作时保持高电平,并通过一个合适的电阻接到正电源。当需要手动复位时,可以通过连接一个按钮或开关来将MR引脚拉低,从而触发复位操作。

总之,TPS3823-33DBVR的MR引脚是用于手动复位操作的引脚,当MR引脚被拉低时,TPS3823-33DBVR会进行复位操作,从而实现对被监测系统或芯片的重新启动。

1/3/2024, 5:12:51 PM

TPS3823-33DBVR的WDI引脚是干什么的

1/3/2024, 5:13:13 PM

TPS3823-33DBVR的WDI引脚是用于喂狗定时器(Watchdog Timer)的输入引脚。

喂狗定时器是一种用于监控系统运行状态的计时器。它需要周期性地接收一个喂狗脉冲来防止系统出现故障或死锁。如果在一定的时间内没有接收到喂狗脉冲,喂狗定时器会触发复位操作,使被监控的系统重新启动。

在TPS3823-33DBVR中,WDI引脚用于接收外部喂狗脉冲。当WDI引脚接收到一个高电平脉冲时,喂狗定时器会被重置,系统继续正常运行。如果在一定时间内未接收到喂狗脉冲,喂狗定时器将超时,并触发复位操作。

通过连接一个外部的喂狗脉冲源(例如微处理器的GPIO引脚),可以周期性地向TPS3823-33DBVR的WDI引脚提供喂狗脉冲。这样可以确保系统持续运行,并在出现故障或死锁时进行自动复位,提高系统的可靠性和稳定性。

总之,TPS3823-33DBVR的WDI引脚用于接收外部喂狗脉冲,用于喂狗定时器的重置操作,以确保系统正常运行并防止故障或死锁。

MPU6050
https://blog.csdn.net/qq_52251819/article/details/134957492

image-20240103191542473

AHT21

image-20240103193207567

Vdd_IO和Vdd是两个不同的电源引脚,常见于集成电路或芯片中。

  1. Vdd(也称为Vcc)是供电引脚,用于提供主要的电源电压给芯片或集成电路的内部电路。它通常连接到正电源(例如+3.3V或+5V),以供应芯片内部的数字和模拟电路。
  2. Vdd_IO(也称为Vcc_IO或VddIO)是IO供电引脚,用于提供给输入输出(IO)电路的电源电压。它通常连接到较低的电压(例如+1.8V或+3.3V),用于驱动芯片的输入和输出引脚。

区别:

  • 功能:Vdd提供整个芯片的电源,包括内部逻辑、处理器核心等。Vdd_IO则专门提供给IO电路使用。
  • 电压级别:Vdd通常连接到较高的电压,而Vdd_IO连接到较低的电压。这是为了在现代集成电路中实现低功耗设计和电压兼容性。

在 STM32 HAL 库中,xx_MspInit() 和 xx_Init() 函数是针对特定外设的初始化函数。

  1. xx_MspInit() 函数:该函数是外设的底层初始化函数,用于配置外设的时钟、引脚、中断等底层硬件资源。”xx” 是指特定外设的前缀,例如 GPIO、USART、SPI 等。xx_MspInit() 通常在应用程序初始化之前调用,主要目的是配置外设所需的底层硬件资源。
  2. xx_Init() 函数:该函数是外设的高层初始化函数,用于配置外设的工作模式、时钟频率、中断优先级等高层参数。它会调用底层的 xx_MspInit() 函数来初始化底层硬件资源,并进行一些高层配置。xx_Init() 通常在应用程序初始化阶段调用,用于配置外设的工作模式和参数。

HAL_ADC_ConfigChannel()是ADC常规通道配置,一次配置一个通道

HAL_ADC_PollForConversion()是轮询方式等待ADC常规通道转换完成

HAL_ADC_GetValue()读取常规通道转换结果寄存器的数据

HAL_ADC_Start()以软件方式启动ADC常规转换的通道,然后调用HAL_ADC_PollForConversion()来查询转换是否完成,如果转换完成,使用HAL_ADC_GetValue()读出常规结果寄存器的32位数据

stm32是32位的,所以指针总是32位的

image-20240322130525454

![(../images/image-20240322125751723.png)image-20240322130023148

image-20240322130246888

image-20240322130635769image-20240322195132792

工作模式:

image-20240322195540298

低功耗模式:

image-20240322195836292

image-20240322200333679image-20240323090001811

stm32的SPI的Clock Phase(CPHA)设置为2 Edge是什么意思

2024/3/23 14:29:32

在 STM32 微控制器的 SPI(Serial Peripheral Interface)模块中,Clock Phase(时钟相位,通常用 CPHA 表示)参数用于定义数据采样的时机。当设置为 2 Edge 时,表示数据采样会在时钟的第二个边缘上进行。

在 SPI 通信中,数据传输的时机是由时钟信号决定的。CPHA 参数定义了数据采样的时机相对于时钟信号的边缘。具体来说,CPHA 可以设置为 0 或 1,分别表示:

  • CPHA = 0:数据在时钟信号的第一个边缘上进行采样。也就是说,在时钟信号的上升沿或下降沿(取决于时钟极性)开始时采样数据。
  • CPHA = 1:数据在时钟信号的第二个边缘上进行采样。也就是说,在时钟信号的另一个沿(与上升沿或下降沿相反的沿)上采样数据。

因此,当将 SPI 的 CPHA 参数设置为 2 Edge 时,表示数据采样会在时钟的第二个边缘上进行,这种设置通常用于特定的 SPI 设备或者通信协议要求,确保数据的正确采样和传输。在实际应用中,需要根据外设设备的要求和通信协议的规范来选择合适的 CPHA 设置,以确保 SPI 数据传输的准确性和稳定性。

image-20240324102428755image-20240324102801798

image-20240324103200416image-20240324103611561image-20240324103705403

不使用预装载,设置的新ARR的值立即生效

使用,会在下一个UEV事件生效

PWM波

image-20240324105850607

image-20240324110915173image-20240324115944131

c
HAL_TIM_IC_CaptureCallback(htim);
HAL_TIM_OC_DelayElapsedCallback(htim);
HAL_TIM_PWM_PulseFinishedCallback(htim);
HAL_TIM_PeriodElapsedCallback(htim);
HAL_TIM_TriggerCallback(htim);
HAL_TIMEx_CommutCallback(htim);

image-20240324143451922image-20240324160106485

image-20240328093523112

mpu_prototypes.h

mpu_wrappers.h内存保护单元 ,内存保护单元(memory protection unit),简称:MPU,使用MPU可以设置不同存储区域的存储访问特性(如只支持特权访问或全访问)和存储器属性(如可缓存、可共享),从而提高嵌入式系统的健壮性,使系统更加安全。优先执行mpu_prototypes.h,mpu_wrappers.h里的函数

image-20240410131546745

image-20240410131717234

image-20240410141116783

image-20240410142357998

MPU:内存保护单元

FPU:浮点数单元

钩子函数类似于回调函数

image-20240410171152068

image-20240410171607710

image-20240410171723221

image-20240410172152947

image-20240411090500199

image-20240411090745706

freertos中任何时候都要有一个任务占用CPU,所以就有了空闲任务

systick只有定时中断功能,1ms中断一次

systick定时器不仅可以产生滴答信号,还可以产生任务切换申请

image-20240411092035829

image-20240411092600517

所以:Freertos的任务优先级总是低于系统中断的优先级

image-20240414171100213

image-20240414172301612

xTaskCreate()创建一个任务,以动态方式来分配内存

xTaskCreateStatic()

vTaskDelete()可以删除当前任务或者另一个任务

vTaskSuspend()可以挂起当前任务或者另一个任务

vTaskResume()恢复另一个挂起的任务的运行

调度器管理的函数:
vTaskStartScheduler()开启任务调度器

vTaskSuspendAll()挂起任务调度器,但是不禁用中断,调度器被挂起后,不再进行上下文切换

vTaskResumeAll()恢复调度器的执行,但是不会恢复vTaskSuspend()单独挂起的任务

延时和调度的函数:

中央对齐模式下:

txt
RCR = 0,更新事件没有延迟;
RCR = 1,更新事件延后了半个PWM周期;
RCR = 2, 更新事件延后了一个PWM周期;
RCR = 3,更新事件延后了 3 2 \cfrac{3}{2} 23个PWM周期;

yolov5

image-20231216210026711

image-20231216210245075

IOU —-交并比

image-20231216210441830

Lou为1意味着预测边界框和地面真实边界框完全重叠。
您可以为LOU设置阈值,以确定对象检测是否有效。
假设您将LOU设置为0.5,在这种情况下。
·如果LOU≥为0.5,则将目标检测归类为真阳性(TP)。
如果LOU<0.5,则为错误检测,并将其归类为假阳性(FP)。
当图像中存在地面真实且模型未能检测到目标时,分类。
作为假阴性(FN)。
真负片(TN):TN是我们没有预测到物体的图像的每一部分。
度量对于目标检测没有用处,因此我们忽略TN。

image-20231216210636311

AP,MAP

image-20231216210923498

image-20231216211711468

image-20231216211921852

image-20231216204704657

image-20231216204353728

网络架构和组件

单阶段检测器:

image-20231216205751067

yolov5:(没有划出专门的颈部Neck)

image-20231216212300844

git clone https://github.moeyy.xyz/https://github.com/ultralytics/yolov5.git

image-20231217123703969

  1. nc: 80:这个参数表示模型分类数量(number of classes),默认为 80,对应着 COCO 数据集。
  2. depth_multiple: 0.33:这个参数表示模型深度相对于基础版本的倍数。在 YOLOv5 中,有 S、M、L 和 X 四个版本,其中 S 为基础版本,即 depth_multiple: 1.0,而 M、L 和 X 版本为在此基础上分别加深了一定的层数。而 depth_multiple: 0.33 表示在 S 版本的基础上,深度缩小了 3 倍,即变成了 depth_multiple: 0.33 × 3 = 0.99。
  3. width_multiple: 0.50:这个参数表示模型通道宽度相对于基础版本的倍数。与 depth_multiple 类似,S 版本的 width_multiple 是 1.0,而 M、L 和 X 版本则在此基础上分别扩大了一定的倍数。
  4. anchors:这是一个锚点数组,用于定义不同尺度下的 anchor boxes。YOLOv5 中使用了三个不同的尺度,每个尺度使用三个不同的 anchor boxes。这些锚点大小是相对于输入图像的,因此不同尺度下的大小会有所差别。
  5. backbone:这一部分定义了模型的骨干网络(backbone),包括卷积层、批归一化层和激活函数等。YOLOv5 使用了 CSPDarknet53 这个网络作为基础骨干网络,并在此基础上进行改进。具体而言,YOLOv5 增加了空间注意力机制和SPP模块,以增强特征表达能力。
  6. head:这一部分定义了模型的检测头(detection head),包括检测网络和分类网络。YOLOv5 中的检测网络采用了YOLOv3中的FPN结构,并在此基础上加入了PANet模块和SAM模块,以提高检测性能。

序列数据的不同采样方法(随机采样和顺序分区)会导致隐状态初始化的差异,原因如下:

  1. 随机采样: 在随机采样中,我们从序列数据中随机选择一个序列作为训练样本。这意味着每次训练时,我们都使用不同的序列作为输入。由于每个序列可能具有不同的上下文和语义信息,模型在每次训练时都需要重新适应不同的序列特征。因此,随机采样会导致隐状态的初始化与之前的训练批次存在一定差异。
  2. 顺序分区: 在顺序分区中,我们按顺序依次读取序列数据进行训练。这意味着模型在每个训练批次中都会接收到相邻的序列数据。由于相邻的序列通常具有相似的上下文和语义信息,模型可以利用之前批次的隐藏状态来帮助理解当前批次的序列。因此,顺序分区会导致隐状态的初始化与之前的训练批次存在一定的相关性。

不同的隐状态初始化差异可能会对模型的训练和预测产生影响。随机采样可以增加数据的多样性,帮助模型更好地适应不同的序列特征。然而,随机采样可能也会引入一些噪声,导致训练过程更加不稳定。顺序分区可以利用相邻序列之间的相关性,帮助模型更好地捕捉到序列的上下文信息。然而,顺序分区可能会限制模型对不同序列特征的适应能力。

困惑度(perplexity)是自然语言处理中常用的一个评价指标,主要用于衡量语言模型的预测性能。困惑度越低,表示模型的预测能力越好。

在自然语言处理中,我们通常使用语言模型来计算文本序列的概率。给定一个文本序列 $W=w_1,w_2,…,w_n$,其概率可以表示为:

$$
P(W)=P(w_1)\times P(w_2|w_1) \times … \times P(w_n|w_1,w_2,…,w_{n-1})
$$

其中,$P(w_i|w_1,w_2,…,w_{i-1})$ 表示在已知前面 $i-1$ 个词的情况下,第 $i$ 个词的概率。语言模型的目标就是学习这种条件概率分布。在模型训练过程中,我们通常会使用最大似然估计法来估计模型参数。

困惑度是一个数值指标,表示用当前语言模型对一个测试集进行预测时所得到的困惑程度。具体而言,如果测试集包含 $N$ 个词,我们可以计算出每个词的概率 $P(w_i)$,然后将这些概率求倒数并取对数,即:

$$
\log \frac{1}{P(w_1)}+\log \frac{1}{P(w_2|w_1)}+…+\log \frac{1}{P(w_N|w_1,w_2,…,w_{N-1})}
$$

然后,我们可以将上述结果除以测试集中的词数 $N$,得到平均困惑度。具体而言,平均困惑度的计算公式如下:

$$
\text{Perplexity}=exp\left(-\frac{1}{N}\sum_{i=1}^{N}\log P(w_i)\right)
$$

例如,如果我们有一个包含100个句子的测试集,其中总共包含1000个词,我们可以使用语言模型来预测每个词的概率,并计算出平均困惑度。假设我们的模型预测准确率较高,平均每个词的概率为0.9,则平均困惑度为:

$$
exp\left(-\frac{1}{1000}\sum_{i=1}^{1000}\log 0.9\right) \approx 2.15
$$

这表示我们的模型对测试集中的文本序列进行预测时,每个词的平均困惑度为2.15。如果我们使用一个更好的语言模型,其困惑度可能会更低。

用困惑度来评价模型确保了不同长度的序列具有可比性

路径聚合网络模块

image-20231219133825543

Focus处理模块

image-20231219133907407

空间金字塔池化模块

image-20231219134700073

跨阶段局部网络模块

image-20231219134949252

image-20231219135635494

IoU、GIoU、DIoU、CIoU损失函数

IoU、GIoU、DIoU、CIoU损失函数

目标检测任务的损失函数由Classificition Loss和Bounding Box Regeression Loss两部分构成。目标检测任务中近几年来Bounding Box Regression Loss Function的演进过程,其演进路线是

img

一、IOU(Intersection over Union)

1. 特性(优点)

IoU就是我们所说的交并比,是目标检测中最常用的指标,在anchor-based的方法。作用不仅用来确定正样本和负样本,还可以用来评价输出框(predict box)和ground-truth的距离。

img

\1. 可以说它可以反映预测检测框与真实检测框的检测效果。

\2. 还有一个很好的特性就是尺度不变性,也就是对尺度不敏感(scale invariant), 在regression任务中,判断predict box和gt的距离最直接的指标就是IoU。**(**满足非负性;同一性;对称性;三角不等性)

img

2. 作为损失函数会出现的问题(缺点)

\1. 如果两个框没有相交,根据定义,IoU=0,不能反映两者的距离大小(重合度)。同时因为loss=0,没有梯度回传,无法进行学习训练。

\2. IoU无法精确的反映两者的重合度大小。如下图所示,三种情况IoU都相等,但看得出来他们的重合度是不一样的,左边的图回归的效果最好,右边的最差。

img

二、GIOU(Generalized Intersection over Union)

1****、来源

在CVPR2019中,论文

《Generalized Intersection over Union: A Metric and A Loss for Bounding Box Regression》
https:arxiv.org/abs/1902.09630

提出了GIoU的思想。由于IoU是比值的概念,对目标物体的scale是不敏感的。然而检测任务中的BBox的回归损失(MSE loss, l1-smooth loss等)优化和IoU优化不是完全等价的,而且 Ln 范数对物体的scale也比较敏感,IoU无法直接优化没有重叠的部分。

img

这篇论文提出可以直接把IoU设为回归的loss。

img

上面公式的意思是:先计算两个框的最小闭包区域面积_ _(通俗理解:同时包含了预测框和真实框的最小框的面积),再计算出IoU,再计算闭包区域中不属于两个框的区域占闭包区域的比重,最后用IoU减去这个比重得到GIoU。

附:https://github.com/generalized-iou/g-darknet

2****、 特性[1]

与IoU相似,GIoU也是一种距离度量,作为损失函数的话, ,满足损失函数的基本要求

GIoU对scale不敏感

GIoU是IoU的下界,在两个框无线重合的情况下,IoU=GIoU

IoU取值[0,1],但GIoU有对称区间,取值范围[-1,1]。在两者重合的时候取最大值1,在两者无交集且无限远的时候取最小值-1,因此GIoU是一个非常好的距离度量指标。

与IoU只关注重叠区域不同,GIoU****不仅关注重叠区域,还关注其他的非重合区域,能更好的反映两者的重合度。

img

img

三、DIoU(Distance-IoU)[2]

**1,**来源

DIoU要比GIou更加符合目标框回归的机制,将目标与anchor之间的距离,重叠率以及尺度都考虑进去,使得目标框回归变得更加稳定,不会像IoU和GIoU一样出现训练过程中发散等问题。论文中

Distance-IoU
https://arxiv.org/pdf/1911.08287.pdf

基于IoU和GIoU存在的问题,作者提出了两个问题:
\1. 直接最小化anchor框与目标框之间的归一化距离是否可行,以达到更快的收敛速度?
\2. 如何使回归在与目标框有重叠甚至包含时更准确、更快?

img

其中,img分别代表了预测框和真实框的中心点,img且代表的是计算两个中心点间的欧式距离。c代表的是能够同时包含预测框和真实框的最小闭包区域的对角线距离。

img

img

DIoU中对anchor框和目标框之间的归一化距离进行了建模

附:

YOLOV3 DIoU GitHub项目地址
https//github.com/Zzh-tju/DIoU-darknet

2****、优点

与GIoU loss类似,DIoU loss( )在与目标框不重叠时,仍然可以为边界框提供移动方向。

DIoU loss可以直接最小化两个目标框的距离,因此比GIoU loss收敛快得多。

对于包含两个框在水平方向和垂直方向上这种情况,DIoU损失可以使回归非常快,而GIoU损失几乎退化为IoU损失。

DIoU还可以替换普通的IoU评价策略,应用于NMS中,使得NMS得到的结果更加合理和有效。

实现代码:[3]

img

img

四、CIoU(Complete-IoU)

论文考虑到bbox回归三要素中的长宽比还没被考虑到计算中,因此,进一步在DIoU的基础上提出了CIoU。其惩罚项如下面公式:

img

实现代码:[5]

img

img

img

image-20231219142055992

image-20231219142702047

L(IoU)=1-IoU,L(GIoU)=1-GIoU

image-20231219143118491

image-20231219143242889

penalty item 惩罚项

image-20231219143834054

image-20231219143908214

image-20231219144615647

image-20231219144820908

用1替换

image-20231220151820969image-20231220151851064

image-20231220151924519

image-20231220152401000

YOLO训练技巧

1.

image-20231221102150112

2.

image-20231221102343926余弦退火学习率调整的原理是根据余弦函数的形状动态地调整学习率。它通过将学习率从一个较大的初始值逐渐减小到一个较小的最小值来控制训练过程中的学习率变化。

具体实现步骤如下:

  1. 设置一个最大学习率和最小学习率的范围。
  2. 定义一个周期数(通常是训练的总迭代次数)。
  3. 对于每个训练迭代,计算当前周期数与总周期数之间的比例。
  4. 使用余弦函数来动态计算学习率,公式如下:
txt
lr = lr_min + 0.5 * (lr_max - lr_min) * (1 + cos(epoch / T_total * pi))

其中,lr表示当前学习率,epoch表示当前周期数,T_total表示总周期数,lr_max表示最大学习率,lr_min表示最小学习率。

  1. 将计算得到的学习率应用于优化器中进行权重更新。

使用余弦退火学习率调整可以在训练初期使用较大的学习率来快速收敛,然后逐渐减小学习率以细化模型的优化过程。这种方法在训练中期能够跳出局部最优解并找到更好的全局最优解,有助于提高模型的泛化性能和训练效果。

3.

image-20231221103518038

4.

image-20231221103556292

5.遗传算法

image-20231221103654283

6.AMP

image-20231221103725894

image-202312211038364987.

image-20231221104450473

激活函数

image-20231222110059278

image-20231222110124317

image-20231222110150825

image-20231222110400513

image-20231222111314420

image-20231222111341197优点:激活区域可以更多样

image-20231222111510179

因此,引入了各种方法来压缩神经网络,以使大型模型可以在边缘设备上部署。模型压缩方法可以分为3类:剪枝、量化和知识蒸馏。在剪枝中,移除模型中不重要的冗余参数,以获得稀疏/紧凑的模型结构。量化涉及使用低精度数据类型表示模型的激活和权重。最后,知识蒸馏是指利用大型准确模型作为教师来训练一个小型模型,使用教师模型提供的软标签来进行训练。

cmake_minimum_required(VERSION 3.10) project(yolov5) add_definitions(-std=c++11) add_definitions(-DAPI_EXPORTS) option(CUDA_USE_STATIC_CUDA_RUNTIME OFF) set(CMAKE_CXX_STANDARD 11) set(CMAKE_BUILD_TYPE Debug) # TODO(Call for PR): make cmake compatible with Windows set(CMAKE_CUDA_COMPILER /usr/local/cuda-12.2/bin/nvcc) enable_language(CUDA) # include and link dirs of cuda and tensorrt, you need adapt them if yours are different # cuda include_directories(/usr/local/cuda-12.2/include) link_directories(/usr/local/cuda-12.2/lib64) # tensorrt # TODO(Call for PR): make TRT path configurable from command line include_directories(/home/nvidia/TensorRT-8.2.5.1/include/) link_directories(/home/nvidia/TensorRT-8.2.5.1/lib/) include_directories(${PROJECT_SOURCE_DIR}/src/) include_directories(${PROJECT_SOURCE_DIR}/plugin/) file(GLOB_RECURSE SRCS ${PROJECT_SOURCE_DIR}/src/.cpp ${PROJECT_SOURCE_DIR}/src/.cu) file(GLOB_RECURSE PLUGIN_SRCS ${PROJECT_SOURCE_DIR}/plugin/*.cu) add_library(myplugins SHARED ${PLUGIN_SRCS}) target_link_libraries(myplugins nvinfer cudart) find_package(OpenCV) include_directories(${OpenCV_INCLUDE_DIRS}) add_executable(yolov5_det yolov5_det.cpp ${SRCS}) target_link_libraries(yolov5_det nvinfer) target_link_libraries(yolov5_det cudart) target_link_libraries(yolov5_det myplugins) target_link_libraries(yolov5_det ${OpenCV_LIBS}) add_executable(yolov5_cls yolov5_cls.cpp ${SRCS}) target_link_libraries(yolov5_cls nvinfer) target_link_libraries(yolov5_cls cudart) target_link_libraries(yolov5_cls myplugins) target_link_libraries(yolov5_cls ${OpenCV_LIBS}) add_executable(yolov5_seg yolov5_seg.cpp ${SRCS}) target_link_libraries(yolov5_seg nvinfer) target_link_libraries(yolov5_seg cudart) target_link_libraries(yolov5_seg myplugins) target_link_libraries(yolov5_seg ${OpenCV_LIBS}) 这是cmakeLists.txt文件 cmake .. 报错: zgh@zgh-Legion-Y7000P-IAH7:~/tensorrtx/yolov5/build$ cmake .. CMake Error at /usr/local/share/cmake-3.27/Modules/CMakeDetermineCUDACompiler.cmake:277 (message): CMAKE_CUDA_ARCHITECTURES must be non-empty if set. Call Stack (most recent call first): CMakeLists.txt:13 (enable_language) – Configuring incomplete, errors occurred!

2024/1/20 11:33:33

该错误提示是由于没有指定 CMAKE_CUDA_ARCHITECTURES 变量,需要在 CMakeLists.txt 中添加以下语句:

txt

set(CMAKE_CUDA_ARCHITECTURES "60;61;70;75")

其中,CMAKE_CUDA_ARCHITECTURES 指定了支持的 CUDA 架构版本号,这里的值可以根据你的 GPU 型号进行调整。

在添加上述语句后,再次运行 cmake .. 命令即可。

txt
cmake_minimum_required(VERSION 3.5)
project(Ball_Det)
set(CMAKE_CXX_STANDARD 11)
set(Cudart_LIBS "/usr/local/cuda-12.2/targets/x86_64-linux/lib/libcudart.so")
set(CMAKE_CUDA_COMPILER /usr/local/cuda-12.2/bin/nvcc)
set(CMAKE_CUDA_ARCHITECTURES "80")
include_directories(/usr/local/cuda-12.2/include)
link_directories(/usr/local/cuda-12.2/lib64)
enable_language(CUDA)
find_package(CUDA REQUIRED)
find_package(k4a REQUIRED)
find_package(OpenCV REQUIRED)
include_directories(
       Yolo
        ${OpenCV_INCLUDE_DIRS}
       /usr/local/cuda12.2/include
       ${CMAKE_CURRENT_LIST_DIR}
)
add_library(
       Yolo
       Yolo/yolov5.cpp
)

cuda_add_library(myplugins SHARED ./Yolo/yololayer.cu)


add_executable(Ball_Det
       Mask_Detection.cpp
       Yolo/yolov5.cpp
       main.cpp
       Ball_Detection.cpp
       Yolo/calibrator.cpp
)
target_link_libraries(
       Ball_Det
       nvinfer
       cudart
       myplugins
       /usr/local/cuda12.2/lib64
       ${Cudart_LIBS}
       ${OpenCV_LIBS}
       libk4a.so
        )

deeplearning

在 Pandas 中,.apply() 是用于对 DataFrame 或 Series 中的元素应用指定函数的方法。

对于 DataFrame,.apply() 可以在行或列方向上应用函数。语法如下:

txt
DataFrame.apply(func, axis=0)
  • func 是要应用的函数,可以是一个已定义的函数,也可以是一个匿名函数(如 lambda 函数)。
  • axis 是指定应用函数的方向,默认为 0,表示按列应用函数;设置为 1 则表示按行应用函数。

对于 Series,.apply() 仅能在元素级别上应用函数,无需指定应用方向。语法如下:

txt
Series.apply(func)
  • func 是要应用的函数,可以是一个已定义的函数,也可以是一个匿名函数(如 lambda 函数)。

在上述代码中,.apply(lambda x: (x - x.mean()) / (x.std())) 就是将匿名函数 lambda x: (x - x.mean()) / (x.std()) 应用到 DataFrame 或 Series 中的每个元素上。结果是对 DataFrame 或 Series 中的每个元素进行标准化计算,并返回处理后的结果

image-20231218090813900

​ 右–按照时间线展开图

image-20231218141358079

查询(自主提示)和键(非自主提示)之间的交互形成了注意力汇聚;注意力汇聚有选择地聚合了值(感官输入)以生成最终的输出。

torch.repeat_interleave() 函数是 PyTorch 中的一个张量操作函数,用于生成一个重复值的张量。它的详细解释如下:

txt

torch.repeat_interleave(input, repeats, dim=None)

参数说明:

  • input:输入张量。
  • repeats:重复次数,可以是一个整数、一个一维张量或一个与 input 张量形状相匹配的张量。
  • dim(可选):指定重复操作的维度。

函数功能:

  • torch.repeat_interleave() 函数将输入张量 input 按指定的重复次数 repeats 进行重复,并生成一个新的张量。
txt
https://zhuanlan.zhihu.com/p/659067322

sk-QxaDRZHsiyhtTFpB3JXHMkQ5fiK0AnEQZgM27mbiEIaIkF0G

Pytorch

在 Python 中,lambda 是用来创建匿名函数的关键字。所谓匿名函数,即没有显式定义函数名的函数,通常用于需要临时定义简单函数的场景。

lambda 函数的语法如下:

txt
lambda arguments: expression

其中:

  • arguments 是函数的参数,可以有多个参数,用逗号隔开。
  • expression 是函数的返回值计算表达式。

lambda 函数通常用于需要一个函数,但是又不想正式定义一个函数的场景,比如作为其他函数的参数传递进去,或者在一些函数式编程的场景中使用。

params = [W_xh, W_hh, b_h, W_hq, b_q]
for param in params:
param.requires_grad_(True)

目的是告诉 PyTorch 在模型训练过程中需要计算这些参数的梯度,并且在反向传播时对其进行更新。

Xt*Wxh + Ht−1*Whh=cat(Xt,Ht−1)*cat(Wxh,Whh)

torch.matmul(X, W_xh) + torch.matmul(H, W_hh)

torch.matmul(torch.cat((X, H), 1), torch.cat((W_xh, W_hh), 0))

当一个类实现了 __call__ 方法时,它的实例对象可以像函数一样进行调用。这意味着你可以使用实例对象作为函数来调用,就好像调用一个函数一样。

例如,假设有一个类 MyClass,并且实现了 __call__ 方法:

txt
python
class MyClass:
    def __call__(self, x):
        print("Calling MyClass with argument:", x)

现在,你可以创建一个 MyClass 的实例,并将其作为函数进行调用:

txt
python
obj = MyClass()
obj(10)

输出结果将是:

txt

Calling MyClass with argument: 10

所以
class RNNModelScratch: #@save
"""从零开始实现的循环神经网络模型"""
def __init__(self, vocab_size, num_hiddens, device,
get_params, init_state, forward_fn):
self.vocab_size, self.num_hiddens = vocab_size, num_hiddens
self.params = get_params(vocab_size, num_hiddens, device)
self.init_state, self.forward_fn = init_state, forward_fn
def __call__(self, X, state):
X = F.one_hot(X.T, self.vocab_size).type(torch.float32)
return self.forward_fn(X, state, self.params)

可以这样调用:

net = RNNModelScratch(len(vocab), num_hiddens, d2l.try_gpu(), get_params,
init_rnn_state, rnn)

Y, new_state = net(X.to(d2l.try_gpu()), state)

**kwargs 是 Python 中的一种特殊语法,用于接收任意数量的关键字参数(keyword arguments)。在函数或方法的定义中,**kwargs 会将传递给函数的未命名关键字参数收集到一个字典中,其中字典的键是参数名,值是参数值。

在这段代码中,**kwargs 被用作 NWKernelRegression 类的初始化方法 __init__ 的参数。通过使用 **kwargs,可以接收任意数量的关键字参数,并将它们存储为类的属性。这样做可以使代码更加灵活,允许用户在创建 NWKernelRegression 实例时传递额外的参数。

例如,如果你创建了一个 NWKernelRegression 实例时传递了额外的参数,比如 model = NWKernelRegression(param1=10, param2='abc'),那么这些额外的参数会被收集到 kwargs 字典中,字典的键是参数名,值是参数值。你可以根据需要在 __init__ 方法中使用这些参数。

总而言之,**kwargs 允许在函数或方法定义中接收任意数量的关键字参数,并将它们保存为字典以供后续使用。

在 PyTorch 中,self.fc1=nn.Linear(16*5*5,120) 定义了一个全连接层(或称为线性层)。具体来说:

  • 16*5*5 是输入特征的数量,即展平后的张量长度。
  • 120 是全连接层输出的特征数量。

这个全连接层会将形状为 400400 的输入(展平后的张量)转换为形状为 120120 的输出。这个层的作用是通过一个权重矩阵和偏置向量对输入进行线性变换,以得到最终的输出。

是如何展平的?

展平(Flatten)是将多维张量转换为一维向量的过程。以一个形状为 (16 \times 5 \times 5) 的张量为例,这个过程如下:

  1. 输入张量:假设有一个张量,其形状为 (16 \times 5 \times 5),其中 (16) 是通道数,(5) 和 (5) 是每个通道的高和宽。

  2. 展平过程

    • 按照通道、行和列的顺序,将所有元素排列成一个一维向量。
    • 例如,假设张量的元素是 ( \text{A}_{i,j,k} ),展平后你将得到一个长度为 (16 \times 5 \times 5 = 400) 的一维向量。
  3. 展平后的结果

    • 这个一维向量的长度为 (400),即将原张量的所有数据连续地排列在一起。

在实际代码中,比如在 PyTorch 中,展平通常通过 nn.Flatten() 或者在前向传播方法中使用 torch.flatten() 来完成。

轴心时代

在优化算法中,momentum 是一个技术,用于加速收敛并减少震荡。具体来说:

  • momentum: 是一个动量因子,它在更新参数时考虑了之前梯度的影响。它通过引入过去梯度的加权平均来调整当前的梯度更新。
  • 作用: 它帮助优化过程在高曲率方向上加速,在低曲率方向上减缓,从而使优化过程更稳定,减少了震荡和加速收敛。

optim.SGD 中,momentum=0.9 表示将前一步梯度的 90% 加入到当前梯度更新中。

ubuntu20.04可以装ROS 2 humble