【阿里云】图像识别 智能分类识别 增加垃圾桶开关盖功能点和OLED显示功能点(二)
一、增加垃圾桶开关盖功能
- 环境准备
二、PWM 频率的公式
三、pthread_detach分离线程,使其在退出时能够自动释放资源
四、具体代码实现
- 图像识别数据及调试信息
- wget-log打印日志文件
五、增加OLED显示功能
六、功能点实现语音交互视频
一、增加垃圾桶开关盖功能
实现功能:使用语音模块和摄像头在香橙派上做垃圾智能分类识别, 同时根据识别结果开关不同的垃圾桶的盖子。
环境准备
在《语音模块和阿里云图像识别结合》搭建环境的基础上, 接上用于开关盖的舵机(舵机模块可以直接粘在垃圾桶内侧),当前代码里仅用了2个舵机用于示例代码的编写,可以自行多购买3个垃圾桶和舵机用于区分4垃圾类型,接线位置如下:

实物图




二、PWM 频率的公式
这个 PWM 频率的公式可以更详细地表示为:
P W M f r e q = 1 × 1 0 6 pulse-width × range \\{PWMfreq} = \frac{1 \times 10^6}{\text{pulse-width} \times \text{range}} \ PWMfreq=pulse-width×range1×106
其中:
- (\text{PWMfreq}) 是 PWM 的频率(赫兹)。
- (1 \times 10^6) 是为了将频率从赫兹(Hz)转换为微秒(μs)。
- (\text{pulse-width}) 是每个 PWM 脉冲的宽度(微秒)。
- (\text{range}) 是 PWM 的范围,即 PWM 值的最大范围。
这个公式的基本思想是,PWM 的频率与脉冲宽度和范围有关。脉冲宽度表示每个 PWM 脉冲的持续时间,而范围表示 PWM 值的最大范围。通过调整这两个参数,可以控制 PWM 的频率。
三、pthread_detach分离线程,使其在退出时能够自动释放资源
pthread_detach 函数是 POSIX 线程库提供的一个函数,用于将一个线程标记为可被回收的。标记为可被回收的线程在退出时会自动释放其占用的系统资源,无需等待其他线程调用 pthread_join。
具体来说,当一个线程被标记为可被回收时,其退出状态会自动被收回。这对于那些不需要其他线程等待其结束的线程是有用的,因为它允许主线程或其他线程继续执行而无需等待这个线程的完成。
#include <pthread.h>int pthread_detach(pthread_t thread);
pthread_detach的参数是一个线程标识符(pthread_t类型的变量),它表示要被标记为可被回收的线程。- 如果线程标识符为
thread的线程处于 joinable 状态,那么它会被标记为可被回收,并且在线程退出时,其资源将被自动释放。 - 如果线程已经处于 detached 状态,或者线程标识符不对应一个现存的线程,
pthread_detach函数将返回适当的错误码。
示例用法:
#include <pthread.h>void *thread_function(void *arg) {// 线程的执行体// ...return NULL;
}int main() {pthread_t my_thread;// 创建线程if (pthread_create(&my_thread, NULL, thread_function, NULL) != 0) {// 线程创建失败处理return 1;}// 将线程标记为可被回收if (pthread_detach(my_thread) != 0) {// 线程标记失败处理return 1;}// 主线程继续执行而不用等待子线程的结束// ...return 0;
}
在这个例子中,my_thread 线程被创建后立即被标记为可被回收,主线程可以继续执行而不用等待 my_thread 线程的完成。
总结:
你可以将这种机制称为“分离线程”或“分离父子线程”。当你将一个线程标记为可被回收,这个线程就不再和主线程形成关联,主线程不需要显式地等待它的结束。这样的线程就像“自洁”一样,它在结束时会自动释放资源。
这种机制对于那些主线程不关心其返回值,也不需要等待其结束的辅助线程是非常有用的。这样,主线程和辅助线程可以并行执行,提高了程序的性能。
四、具体代码实现
- 增加用于实现开光盖(驱动舵机)的源码文件(pwm.c):
#include <wiringPi.h>
#include <softPwm.h>
#include "pwm.h"// 根据PWM 频率公式:PWMfreq = 1 x 10^6 / (100 x range) 。
// 要得到PWM频率为50Hz,则range设置周期分为200步,周期20ms,控制精度相比硬件PWM较低。// 设置指定PWM引脚的输出,实现模拟PWM
void pwm_write(int pwm_pin)
{pinMode(pwm_pin, OUTPUT);softPwmCreate(pwm_pin, 0, 200); // 创建软件PWM,初始占空比为0%,范围为0到200softPwmWrite(pwm_pin, 10); // 设置占空比为10% 45度delay(1000); // 延时1秒softPwmStop(pwm_pin); // 停止软件PWM
}// 停止指定PWM引脚的输出
void pwm_stop(int pwm_pin)
{pinMode(pwm_pin, OUTPUT);softPwmCreate(pwm_pin, 0, 200); // 创建软件PWM,初始占空比为0%,范围为0到200softPwmWrite(pwm_pin, 5); // 设置占空比为5% 0度delay(1000); // 延时1秒softPwmStop(pwm_pin); // 停止软件PWM
}
- pwm.h代码:
#ifndef __PWM__H
#define __PWM__H#define PWM_GARBAGE 7 // 干垃圾
#define PWM_RECOVERABLE_GARBAGE 5 // 可回收垃圾
#define PWM_WET_GARBAGE 8 // 湿垃圾
#define PWM_HAZARDOUS_GARBAGE 9 // 有害垃圾void pwm_write(int pwm_pin); // 设置指定PWM引脚的输出
void pwm_stop(int pwm_pin); // 停止指定PWM引脚的输出#endif
- 修改main.c代码,调整整体main函数的代码架构,利用多线程实现具体的功能(用到了线程里的条件变量控制线程间的数据同步)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <wiringPi.h>
#include <pthread.h>#include "uartTool.h"
#include "garbage.h"
#include "pwm.h"int serial_fd = -1; // 串口文件描述符
pthread_cond_t cond; // 条件变量,用于线程之间的条件同步
pthread_mutex_t mutex; // 互斥锁,用于线程之间的互斥访问// 判断进程是否在运行
static int detect_process(const char * process_name)
{int n = -1; // 存储进程PID,默认为-1FILE *strm;char buf[128] = {0}; // 缓冲区// 构造命令字符串,通过ps命令查找进程sprintf(buf, "ps -ax | grep %s|grep -v grep", process_name);// 使用popen执行命令并读取输出if ((strm = popen(buf, "r")) != NULL) {if (fgets(buf, sizeof(buf), strm) != NULL) {printf("buf = %s\n", buf); //打印缓存区的内容n = atoi(buf); // 将进程ID字符串转换为整数printf("n = %d\n", n); // 打印下进程的PID}}else {return -1; // popen失败} pclose(strm); // 关闭popen打开的文件流return n;
}// 获取语音线程
void *pget_voice(void *arg)
{unsigned char buffer[6] = {0xAA, 0x55, 0x00, 0x00, 0X55, 0xAA};int len = 0;printf("%s|%s|%d\n", __FILE__, __func__, __LINE__);// 串口未打开,退出线程if (-1 == serial_fd) {printf("%s|%s|%d: open serial failed\n", __FILE__, __func__, __LINE__);pthread_exit(0);}printf("%s|%s|%d\n", __FILE__, __func__, __LINE__);// 循环读取串口数据while (1) {len = my_serialGetstring(serial_fd, buffer);printf("%s|%s|%d, len = %d\n", __FILE__, __func__, __LINE__, len);// 检测到特定数据,发出信号唤醒其他线程if (len > 0 && buffer[2] == 0x46) {printf("%s|%s|%d\n", __FILE__, __func__, __LINE__);pthread_mutex_lock(&mutex);buffer[2] = 0x00;pthread_cond_signal(&cond);pthread_mutex_unlock(&mutex);system(WGET_CMD);}}pthread_exit(0);
}// 发送语音线程
void *psend_voice(void *arg)
{pthread_detach(pthread_self());unsigned char *buffer = (unsigned char *)arg;// 串口未打开,退出线程if (-1 == serial_fd) {printf("%s|%s|%d: open serial failed\n", __FILE__, __func__, __LINE__);pthread_exit(0);}// buffer不为空时,通过串口发送数据(分类结果)if (NULL != buffer) {my_serialSendstring(serial_fd, buffer, 6);}pthread_exit(0);
}// 控制垃圾桶线程
void *popen_trash_can(void *arg)
{pthread_detach(pthread_self());unsigned char *buffer = (unsigned char *)arg;// 根据垃圾类型控制PWMif (buffer[2] == 0x43) { // 可回收垃圾printf("%s|%s|%d: buffer[2] = 0x%x\n", __FILE__, __func__, __LINE__, buffer[2]);pwm_write(PWM_RECOVERABLE_GARBAGE);delay(2000);pwm_stop(PWM_RECOVERABLE_GARBAGE);}else if (buffer[2] == 0x41) { // 干垃圾printf("%s|%s|%d: buffer[2] = 0x%x\n", __FILE__, __func__, __LINE__, buffer[2]);pwm_write(PWM_GARBAGE);delay(2000);pwm_stop(PWM_GARBAGE);}else if (buffer[2] == 0x42) { // 湿垃圾printf("%s|%s|%d: buffer[2]=0x%x\n", __FILE__, __func__, __LINE__,buffer[2]);pwm_write(PWM_WET_GARBAGE);delay(2000);pwm_stop(PWM_WET_GARBAGE);}else if (buffer[2] == 0x44) { // 有害垃圾printf("%s|%s|%d: buffer[2]=0x%x\n", __FILE__, __func__, __LINE__,buffer[2]);pwm_stop(PWM_HAZARDOUS_GARBAGE);delay(2000);pwm_write(PWM_HAZARDOUS_GARBAGE);}pthread_exit(0);
}// 垃圾分类线程
void *pcategory(void *arg)
{unsigned char buffer[6] = {0xAA, 0x55, 0x00, 0x00, 0X55, 0xAA};char *category = NULL;pthread_t send_voice_tid, trash_tid;while (1) {printf("%s|%s|%d: \n", __FILE__, __func__, __LINE__);pthread_mutex_lock(&mutex);pthread_cond_wait(&cond, &mutex);pthread_mutex_unlock(&mutex);printf("%s|%s|%d: \n", __FILE__, __func__, __LINE__);buffer[2] = 0x00;// 在执行wget命令之前添加调试输出printf("Executing wget command...\n");// 使用系统命令拍照system(WGET_CMD);// 在执行wget命令之后添加调试输出printf("Wget command executed.\n");// 判断垃圾种类if (0 == access(GARBAGE_FILE, F_OK)) {category = garbage_category(category);if (strstr(category, "干垃圾")) {buffer[2] = 0x41;}else if (strstr(category, "湿垃圾")) {buffer[2] = 0x42;}else if (strstr(category, "可回收垃圾")) {buffer[2] = 0x43;}else if (strstr(category, "有害垃圾")) {buffer[2] = 0x44;}else {buffer[2] = 0x45; // 未识别到垃圾类型}}else {buffer[2] = 0x45; // 识别失败}// 开垃圾桶开关pthread_create(&trash_tid, NULL, psend_voice, (void *)buffer);// 开语音播报线程pthread_create(&send_voice_tid, NULL, popen_trash_can, (void *)buffer);// buffer[2] = 0x00;// 删除拍照文件remove(GARBAGE_FILE); }pthread_exit(0);
}int main(int argc, char *argv[])
{int ret = -1;int len = 0;char *category = NULL;pthread_t get_voice_tid, category_tid;wiringPiSetup();// 初始化串口和垃圾分类模块garbage_init ();// 用于判断mjpg_streamer服务是否已经启动ret = detect_process ("mjpg_streamer");if (-1 == ret) {printf("detect process failed\n");goto END;}// 打开串口serial_fd = my_serialOpen (SERIAL_DEV, BAUD);if (-1 == serial_fd) {printf("open serial failed\n");goto END;}// 开语音线程printf("%s|%s|%d\n", __FILE__, __func__, __LINE__);pthread_create(&get_voice_tid, NULL, pget_voice, NULL);// 开阿里云交互线程printf("%s|%s|%d\n", __FILE__, __func__, __LINE__);pthread_create(&category_tid, NULL, pcategory, NULL);// 创建互斥锁和条件变量pthread_join(get_voice_tid, NULL);pthread_join(category_tid, NULL);// 销毁互斥锁和条件变量pthread_mutex_destroy(&mutex);pthread_cond_destroy(&cond);// 关闭串口close(serial_fd);
END:// 释放垃圾分类资源garbage_final();return 0;
}
图像识别数据及调试信息


wget-log打印日志文件

wget-log 文件名通常是 wget 命令行工具的默认日志文件名,用于记录 wget 下载命令执行过程中的信息、警告和错误。wget 是一个用于在命令行中下载文件的工具,而 wget-log 文件则用于记录执行 wget 命令时产生的输出。
如果你在使用类似如下的 wget 命令:
wget [URL]
wget 默认会将日志输出到 wget-log 文件中。如果你希望更改日志文件的名称,可以使用 -o 选项,例如:
wget -o mylog.txt [URL]
上述命令将日志输出到名为 mylog.txt 的文件中。因此,wget-log 文件的生成通常取决于 wget 命令的使用方式。
阿里云的相关操作(比如通过 wget 下载文件)也可能产生 wget-log 文件,具体情况可能取决于你执行的命令和阿里云环境的设置。如果有特定的 wget 命令或阿里云操作,你可以提供更多的上下文,以便我更好地理解你的问题。
五、增加OLED显示功能
- 环境配置
cat /boot/orangepiEnv.txt
ls -a /dev/i2c-3

- 《OLED屏应用-IIC协议》直接添在garbage项目中添加2个OLED实现代码文件
myoled.h
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdint.h>#include "oled.h"
#include "font.h"#ifndef __MYOLED__H
#define __MYOLED__Hint myoled_init(void);
int oled_show(void *arg);#endif
myoled.c:
#include "myoled.h"#define FILENAME "/dev/i2c-3"static struct display_info disp;// 在 OLED 上显示垃圾分类结果
int oled_show(void *arg)
{unsigned char *buffer = (unsigned char *)arg;// 在 OLED 上显示提示信息oled_putstrto(&disp, 0, 9+1, "THis garbage is:");disp.font = font2;// 根据垃圾类型显示相应信息switch(buffer[2]){case 0x41:oled_putstrto(&disp, 0, 20, "Dry_garbage");break;case 0x42:oled_putstrto(&disp, 0, 20, "Wet_garbage");break;case 0x43:oled_putstrto(&disp, 0, 20, "Recycle_garbage");break;case 0x44:oled_putstrto(&disp, 0, 20, "Hazardous_garbage");break;case 0x45:oled_putstrto(&disp, 0, 20, "recognition failed");break;}disp.font = font2;// 发送显示缓冲区到 OLEDoled_send_buffer(&disp);return 0;
}// 初始化 OLED
int myoled_init(void)
{int e;disp.address = OLED_I2C_ADDR;disp.font = font2;// 打开 OLED 设备文件e = oled_open(&disp, FILENAME);// 初始化 OLEDe = oled_init(&disp);return e;
}
- 然后修改下main.c文件, 增加OLED线程,用于显示识别后的垃圾类型:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <wiringPi.h>
#include <pthread.h>#include "uartTool.h"
#include "garbage.h"
#include "pwm.h"
#include "myoled.h"int serial_fd = -1; // 串口文件描述符
pthread_cond_t cond; // 条件变量,用于线程之间的条件同步
pthread_mutex_t mutex; // 互斥锁,用于线程之间的互斥访问// 判断进程是否在运行
static int detect_process(const char * process_name)
{int n = -1; // 存储进程PID,默认为-1FILE *strm;char buf[128] = {0}; // 缓冲区// 构造命令字符串,通过ps命令查找进程sprintf(buf, "ps -ax | grep %s|grep -v grep", process_name);// 使用popen执行命令并读取输出if ((strm = popen(buf, "r")) != NULL) {if (fgets(buf, sizeof(buf), strm) != NULL) {printf("buf = %s\n", buf); //打印缓存区的内容n = atoi(buf); // 将进程ID字符串转换为整数printf("n = %d\n", n); // 打印下进程的PID}}else {return -1; // popen失败} pclose(strm); // 关闭popen打开的文件流return n;
}// 获取语音线程
void *pget_voice(void *arg)
{unsigned char buffer[6] = {0xAA, 0x55, 0x00, 0x00, 0X55, 0xAA};int len = 0;printf("%s|%s|%d\n", __FILE__, __func__, __LINE__);// 串口未打开,退出线程if (-1 == serial_fd) {printf("%s|%s|%d: open serial failed\n", __FILE__, __func__, __LINE__);pthread_exit(0);}printf("%s|%s|%d\n", __FILE__, __func__, __LINE__);// 循环读取串口数据while (1) {len = my_serialGetstring(serial_fd, buffer);printf("%s|%s|%d, len = %d\n", __FILE__, __func__, __LINE__, len);// 检测到特定数据,发出信号唤醒其他线程if (len > 0 && buffer[2] == 0x46) {printf("%s|%s|%d\n", __FILE__, __func__, __LINE__);pthread_mutex_lock(&mutex);buffer[2] = 0x00;pthread_cond_signal(&cond);pthread_mutex_unlock(&mutex);system(WGET_CMD);}}pthread_exit(0);
}// 发送语音线程
void *psend_voice(void *arg)
{pthread_detach(pthread_self());unsigned char *buffer = (unsigned char *)arg;// 串口未打开,退出线程if (-1 == serial_fd) {printf("%s|%s|%d: open serial failed\n", __FILE__, __func__, __LINE__);pthread_exit(0);}// buffer不为空时,通过串口发送数据(分类结果)if (NULL != buffer) {my_serialSendstring(serial_fd, buffer, 6);}pthread_exit(0);
}// 控制垃圾桶线程
void *popen_trash_can(void *arg)
{pthread_detach(pthread_self());unsigned char *buffer = (unsigned char *)arg;// 根据垃圾类型控制PWMif (buffer[2] == 0x43) { // 可回收垃圾printf("%s|%s|%d: buffer[2] = 0x%x\n", __FILE__, __func__, __LINE__, buffer[2]);pwm_write(PWM_RECOVERABLE_GARBAGE);delay(2000);pwm_stop(PWM_RECOVERABLE_GARBAGE);}else if (buffer[2] == 0x41) { // 干垃圾printf("%s|%s|%d: buffer[2] = 0x%x\n", __FILE__, __func__, __LINE__, buffer[2]);pwm_write(PWM_GARBAGE);delay(2000);pwm_stop(PWM_GARBAGE);}else if (buffer[2] == 0x42) { // 湿垃圾printf("%s|%s|%d: buffer[2]=0x%x\n", __FILE__, __func__, __LINE__,buffer[2]);pwm_write(PWM_WET_GARBAGE);delay(2000);pwm_stop(PWM_WET_GARBAGE);}else if (buffer[2] == 0x44) { // 有害垃圾printf("%s|%s|%d: buffer[2]=0x%x\n", __FILE__, __func__, __LINE__,buffer[2]);pwm_stop(PWM_HAZARDOUS_GARBAGE);delay(2000);pwm_write(PWM_HAZARDOUS_GARBAGE);}pthread_exit(0);
}// 在线程中显示 OLED
void *poled_show(void *arg)
{// 分离线程,使其在退出时能够自动释放资源pthread_detach(pthread_self());// 初始化 OLEDmyoled_init();// 在 OLED 上显示垃圾分类结果oled_show(arg);// 退出线程 pthread_exit(0);
}// 垃圾分类线程
void *pcategory(void *arg)
{unsigned char buffer[6] = {0xAA, 0x55, 0x00, 0x00, 0X55, 0xAA};char *category = NULL;pthread_t send_voice_tid, trash_tid, oled_tid;while (1) {printf("%s|%s|%d: \n", __FILE__, __func__, __LINE__);pthread_mutex_lock(&mutex);pthread_cond_wait(&cond, &mutex);pthread_mutex_unlock(&mutex);printf("%s|%s|%d: \n", __FILE__, __func__, __LINE__);buffer[2] = 0x00;// 在执行wget命令之前添加调试输出printf("Executing wget command...\n");// 使用系统命令拍照system(WGET_CMD);// 在执行wget命令之后添加调试输出printf("Wget command executed.\n");// 判断垃圾种类if (0 == access(GARBAGE_FILE, F_OK)) {category = garbage_category(category);if (strstr(category, "干垃圾")) {buffer[2] = 0x41;}else if (strstr(category, "湿垃圾")) {buffer[2] = 0x42;}else if (strstr(category, "可回收垃圾")) {buffer[2] = 0x43;}else if (strstr(category, "有害垃圾")) {buffer[2] = 0x44;}else {buffer[2] = 0x45; // 未识别到垃圾类型}}else {buffer[2] = 0x45; // 识别失败}// 开垃圾桶开关pthread_create(&trash_tid, NULL, psend_voice, (void *)buffer);// 开语音播报线程pthread_create(&send_voice_tid, NULL, popen_trash_can, (void *)buffer);//oled显示线程pthread_create(&oled_tid, NULL, poled_show, (void *)buffer);// buffer[2] = 0x00;// 删除拍照文件remove(GARBAGE_FILE); }pthread_exit(0);
}int main(int argc, char *argv[])
{int ret = -1;int len = 0;char *category = NULL;pthread_t get_voice_tid, category_tid;wiringPiSetup();// 初始化串口和垃圾分类模块garbage_init ();// 用于判断mjpg_streamer服务是否已经启动ret = detect_process ("mjpg_streamer");if (-1 == ret) {printf("detect process failed\n");goto END;}// 打开串口serial_fd = my_serialOpen (SERIAL_DEV, BAUD);if (-1 == serial_fd) {printf("open serial failed\n");goto END;}// 开语音线程printf("%s|%s|%d\n", __FILE__, __func__, __LINE__);pthread_create(&get_voice_tid, NULL, pget_voice, NULL);// 开阿里云交互线程printf("%s|%s|%d\n", __FILE__, __func__, __LINE__);pthread_create(&category_tid, NULL, pcategory, NULL);// 创建互斥锁和条件变量pthread_join(get_voice_tid, NULL);pthread_join(category_tid, NULL);// 销毁互斥锁和条件变量pthread_mutex_destroy(&mutex);pthread_cond_destroy(&cond);// 关闭串口close(serial_fd);
END:// 释放垃圾分类资源garbage_final();return 0;
}

六、功能点实现语音交互视频
垃圾分类
相关文章:
【阿里云】图像识别 智能分类识别 增加垃圾桶开关盖功能点和OLED显示功能点(二)
一、增加垃圾桶开关盖功能 环境准备 二、PWM 频率的公式 三、pthread_detach分离线程,使其在退出时能够自动释放资源 四、具体代码实现 图像识别数据及调试信息wget-log打印日志文件 五、增加OLED显示功能 六、功能点实现语音交互视频 一、增加垃圾桶开关盖功能…...
linux centos上安装python3.11.x详细完整教程
一. 安装步骤 注意: 1、安装python3.11的其他版本替换下面的版本信息即可。(如想安装3.11.5将案例中的3.11.0替换成3.11.5即可) #下载最新的软件安装包 wget https://www.python.org/ftp/python/3.11.0/Python-3.11.0.tgz#解压缩安装包 tar -xzf Python-3.11.0.tg…...
itext - PDF模板套打
目录 环境配置 快速使用 代码实现 添加图片 封装 项目需求:获取列表数据之后直接将数据生成一个pdf。因此需要使用到 itext 对pdf进行直接操作。 环境配置 需要为pdf添加文字域,因此需要安装Adobe Acrobat 准备一个空的PDF文件,如果有现…...
指针的使用和传址调用
1.引入 学习指针的⽬的是使⽤指针解决问题,那什么问题,⾮指针不可呢? 例如:写⼀个函数,交换两个整型变量的值。 ⼀番思考后,我们可能写出这样的代码: #include <stdio.h> void Swap1(int…...
【Leetcode】【实现循环队列】【数据结构】
代码实现: typedef struct {int front;int back;int k;int* a;} MyCircularQueue;bool myCircularQueueIsEmpty(MyCircularQueue* obj) {return obj->frontobj->back; }bool myCircularQueueIsFull(MyCircularQueue* obj) {return (obj->back1)%(obj->…...
电力感知边缘计算网关产品设计方案-软件架构(业务流程)
软件架构(业务流程) 基于前端系统提供的硬件通信平台,后端系统以控制执行单元为核心,协同控制通信管理、驱动适配、存储单元等职能单元完成与前端系统的通信数据交互业务,在经历以下业务流程后,完成设备自适应通信业务功能。 1.外部设备通信前端系统 前端系统连接新的…...
【labelimg打不开】
labelimg打不开 一、 报错1.1 排除错误 **解决方法:** 一、 报错 当运行labelimg程序报错此条时 AssertionError: Missing string id : useDefaultLabel 1.1 排除错误 第一,进入创建的虚拟环境,输入pip list 查看是否安装了labelimg 第二&…...
JAVA之异常详解
1. 异常的概念与体系结构 1.1 异常的概念 在Java中,将程序执行过程中发生的不正常行为称为异常 1. 算术异常 public class Test {public static void main(String[] args) {System.out.println(10/0);} } 因为 0 不能当被除数,所以报出了异常&#…...
模型优化【2】-剪枝[局部剪枝]
模型剪枝是一种常见的模型压缩技术,它可以通过去除模型中不必要的参数和结构来减小模型的大小和计算量,从而提高模型的效率和速度。在 PyTorch 中,我们可以使用一些库和工具来实现模型剪枝。 pytorch实现剪枝的思路是生成一个掩码࿰…...
VMware 系列:ESXI6.7升级7.0
ESXI6.7升级7.0 一、下载补丁二、上传文件三 启用Shell四、登录Shell后台五、删除不兼容驱动六、正常升级最近,将一台使用ESXI6.7的虚拟机升级到了7.0版本,下面记录一下自己的升级过程。 升级条件 首先确保硬件是否能升级到7.0版本,物理网卡驱动为e1000e不能升级,如果是ig…...
4-20mA高精度采集方案
下载链接!https://mp.weixin.qq.com/s?__bizMzU2OTc4ODA4OA&mid2247557466&idx1&snb5a323285c2629a41d2a896764db27eb&chksmfcfaf28dcb8d7b9bb6211030d9bda53db63ab51f765b4165d9fa630e54301f0406efdabff0fb&token976581939&langzh_CN#rd …...
案例022:基于微信小程序的行政复议在线预约系统
文末获取源码 开发语言:Java 框架:SSM JDK版本:JDK1.8 数据库:mysql 5.7 开发软件:eclipse/myeclipse/idea Maven包:Maven3.5.4 小程序框架:uniapp 小程序开发软件:HBuilder X 小程序…...
Go 工具链详解(七):模块缓存清理工具
go mod 缓存 在 Golang 中,模块是对一组版本化的包的集合的描述。Go 1.11 版本引入了模块支持,通过 go mod 命令提供了对模块的管理。Go 模块的一个重要特性是依赖管理,可以清晰地定义项目所依赖的模块及对应的版本,并确保代码使…...
1.7 C语言之函数概述
1.7 C语言之函数概述 一、概述二、练习 一、概述 函数就是把一组计算操作封装起来,供程序员调用,我们只需知道其提供了什么功能,而无需关注具体实现细节(前提是其久经考验,设计没有问题,后续我们自己写的函数大概率还…...
CTA-GAN:基于生成对抗性网络的主动脉和颈动脉非集中CT血管造影 CT到增强CT的合成技术
Generative Adversarial Network–based Noncontrast CT Angiography for Aorta and Carotid Arteries 基于生成对抗性网络的主动脉和颈动脉非集中CT血管造影背景贡献实验方法损失函数Thinking 基于生成对抗性网络的主动脉和颈动脉非集中CT血管造影 https://github.com/ying-f…...
电源控制系统架构(PCSA)之电源管理基础设施组件
目录 6.5 电源管理基础设施组件 6.5.1 电源策略单元 6.5.2 时钟控制器 6.5.3 低功耗Distributor 6.5.4 低功耗Combiner 6.5.5 P-Channel到Q-Channel转换器 6.5 电源管理基础设施组件 6.5.1 电源策略单元 本节介绍电源策略单元(Power Policy Unit, PPU)。PPU的完整细节见…...
影刀RPA_boss直聘翻页(避坑)
boss直聘翻页这里有个坑 问题: 无限循环中,点击下一页按钮,直到不可点击为止。 发现,在点到第5页的时候,再次点击下一页,直接就点击了页码10,导致流程直接就结束了。 在第5页进行校验࿰…...
第十四章 控制值的转换 - 在DISPLAYLIST中投影值
文章目录 第十四章 控制值的转换 - 在DISPLAYLIST中投影值在DISPLAYLIST中投影值 第十四章 控制值的转换 - 在DISPLAYLIST中投影值 在DISPLAYLIST中投影值 对于 %String 类型(或任何子类)的属性,XML 投影可以使用 DISPLAYLIST 参数。 简单…...
C++类与对象(5)—流运算符重载、const、取地址
目录 一、流输出 1、实现单个输出 2、实现连续输出 二、流输入 总结: 三、const修饰 四、取地址 .取地址及const取地址操作符重载 五、[ ]运算符重载 一、流输出 1、实现单个输出 创建一个日期类。 class Date { public:Date(int year 1, int month 1,…...
Vue框架学习笔记——事件修饰符
文章目录 前文提要事件修饰符prevent(常用)stop(不常用)事件冒泡stop使用方法三层嵌套下的stop三层嵌套看出的stop: once(常用)capture(不常用)self(不常用&a…...
Linux 文件类型,目录与路径,文件与目录管理
文件类型 后面的字符表示文件类型标志 普通文件:-(纯文本文件,二进制文件,数据格式文件) 如文本文件、图片、程序文件等。 目录文件:d(directory) 用来存放其他文件或子目录。 设备…...
Docker 运行 Kafka 带 SASL 认证教程
Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明:server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...
深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法
深入浅出:JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中,随机数的生成看似简单,却隐藏着许多玄机。无论是生成密码、加密密钥,还是创建安全令牌,随机数的质量直接关系到系统的安全性。Jav…...
第7篇:中间件全链路监控与 SQL 性能分析实践
7.1 章节导读 在构建数据库中间件的过程中,可观测性 和 性能分析 是保障系统稳定性与可维护性的核心能力。 特别是在复杂分布式场景中,必须做到: 🔍 追踪每一条 SQL 的生命周期(从入口到数据库执行)&#…...
Linux中《基础IO》详细介绍
目录 理解"文件"狭义理解广义理解文件操作的归类认知系统角度文件类别 回顾C文件接口打开文件写文件读文件稍作修改,实现简单cat命令 输出信息到显示器,你有哪些方法stdin & stdout & stderr打开文件的方式 系统⽂件I/O⼀种传递标志位…...
上位机开发过程中的设计模式体会(1):工厂方法模式、单例模式和生成器模式
简介 在我的 QT/C 开发工作中,合理运用设计模式极大地提高了代码的可维护性和可扩展性。本文将分享我在实际项目中应用的三种创造型模式:工厂方法模式、单例模式和生成器模式。 1. 工厂模式 (Factory Pattern) 应用场景 在我的 QT 项目中曾经有一个需…...
绕过 Xcode?使用 Appuploader和主流工具实现 iOS 上架自动化
iOS 应用的发布流程一直是开发链路中最“苹果味”的环节:强依赖 Xcode、必须使用 macOS、各种证书和描述文件配置……对很多跨平台开发者来说,这一套流程并不友好。 特别是当你的项目主要在 Windows 或 Linux 下开发(例如 Flutter、React Na…...
链式法则中 复合函数的推导路径 多变量“信息传递路径”
非常好,我们将之前关于偏导数链式法则中不能“约掉”偏导符号的问题,统一使用 二重复合函数: z f ( u ( x , y ) , v ( x , y ) ) \boxed{z f(u(x,y),\ v(x,y))} zf(u(x,y), v(x,y)) 来全面说明。我们会展示其全微分形式(偏导…...
Python 高级应用10:在python 大型项目中 FastAPI 和 Django 的相互配合
无论是python,或者java 的大型项目中,都会涉及到 自身平台微服务之间的相互调用,以及和第三发平台的 接口对接,那在python 中是怎么实现的呢? 在 Python Web 开发中,FastAPI 和 Django 是两个重要但定位不…...
医疗AI模型可解释性编程研究:基于SHAP、LIME与Anchor
1 医疗树模型与可解释人工智能基础 医疗领域的人工智能应用正迅速从理论研究转向临床实践,在这一过程中,模型可解释性已成为确保AI系统被医疗专业人员接受和信任的关键因素。基于树模型的集成算法(如RandomForest、XGBoost、LightGBM)因其卓越的预测性能和相对良好的解释性…...
