当前位置: 首页 > news >正文

基于Linux的云端垃圾分类助手

项目简介

本项目旨在开发一个基于嵌入式系统的智能垃圾分类装置。该装置能够通过串口通信、语音播报、网络通信等多种方式,实现垃圾的自动识别和分类投放。系统采用多线程设计,确保各功能模块高效并行工作。

项目功能

  1. 垃圾分类识别

系统使用摄像头拍摄垃圾图片,并将其上传到阿里云进行分类识别。
识别结果包括干垃圾、湿垃圾、可回收垃圾、有害垃圾等类别。

  1. 语言播报

系统通过串口与语言模块通信,根据垃圾分类结果进行语音播报。
语音模块接收指令并播放相应的提示音。

  1. OLED显示

系统通过OLED屏幕显示当前垃圾分类结果。

4.垃圾桶盖控制

系统根据识别结果控制相应垃圾桶的开关。
使用PWM信号控制舵机开关垃圾桶盖。

5.网络通信

系统支持通过网络接收客户端指令,实现远程控制。
通过TCP/IP协议接收来自客户端的“open”指令,触发垃圾分类操作。

硬件需求

Orange Pi Zero2
摄像头模块
语音播报模块SU-03T
128*64 OLED显示屏
SG90舵机
串口通信模块

运行环境

操作系统:Linux
编程语言:C语言、Python

功能实现

garbage.py

调用阿里云SDK API

# -*- coding: utf-8 -*-
# 引入依赖包
# pip install alibabacloud_imagerecog20190930
//引入必要的Python包,包括阿里云图像识别服务的SDK包。
import os
import io
from urllib.request import urlopen
from alibabacloud_imagerecog20190930.client import Client
from alibabacloud_imagerecog20190930.models import ClassifyingRubbishAdvanceRequest
from alibabacloud_tea_openapi.models import Config
from alibabacloud_tea_util.models import RuntimeOptions//通过读取环境变量中的AccessKey ID和AccessKey Secret,配置阿里云客户端的认证信息和访问域名。
config = Config(# 创建AccessKey ID和AccessKey Secret,请参考https://help.aliyun.com/document_detail/175144.html。# 如果您用的是RAM用户的AccessKey,还需要为RAM用户授予权限AliyunVIAPIFullAccess,请参考https://help.aliyun.com/document_detail/145025.html# 从环境变量读取配置的AccessKey ID和AccessKey Secret。运行代码示例前必须先配置环境变量。access_key_id=os.environ.get('ALIBABA_CLOUD_ACCESS_KEY_ID'),access_key_secret=os.environ.get('ALIBABA_CLOUD_ACCESS_KEY_SECRET'),# 访问的域名endpoint='imagerecog.cn-shanghai.aliyuncs.com',# 访问的域名对应的regionregion_id='cn-shanghai'
)//垃圾分类函数,提供了从本地文件读取和从URL读取,两种方式
def alibaba_garbage():#场景一:文件在本地img = open(r'/tmp/garbage.jpg', 'rb') //打开文件所在路径#场景二:使用任意可访问的url#url = 'https://viapi-test-bj.oss-cn-beijing.aliyuncs.com/viapi-3.0domepic/imagerecog/ClassifyingRubbish/ClassifyingRubbish1.jpg'#img = io.BytesIO(urlopen(url).read())classifying_rubbish_request = ClassifyingRubbishAdvanceRequest()classifying_rubbish_request.image_urlobject = imgruntime = RuntimeOptions()try:# 初始化Clientclient = Client(config)//调用阿里云图像识别服务,将上传的垃圾图片进行分类,并返回分类结果。response = client.classifying_rubbish_advance(classifying_rubbish_request, runtime)# 获取整体结果print(response.body.to_map()['Data']['Elements'][0]['Category'])return response.body.to_map()['Data']['Elements'][0]['Category']except Exception as error:return 'gat failed'在脚本被直接执行时,调用‘alibaba_garbage’函数。
if __name__ == "__main__":alibaba_garbage()

garbage.c

在C语言中嵌入Python解释器以调用Python函数。

#include <Python.h>
#include "garbage.h"void garbage_init(void)
{	//初始化Python解释器Py_Initialize();//导入‘sys’模块PyObject *sys = PyImport_ImportModule("sys");//获取‘sys.path’模块PyObject *path = PyObject_GetAttrString(sys, "path");//将当前目录‘.’添加到'sys.path'中,以便导入当前目录下的Python脚本。PyList_Append(path, PyUnicode_FromString("."));
}void garbage_final(void)
{//终止Python解释器。	Py_Finalize();
}char *garbage_category(char *category)
{//导入名为‘garbage.py’的python模块。//如果导入失败,打印错误信息并跳转到'FAILED_MODULE'表签进行清理。PyObject *pModule = PyImport_ImportModule("garbage");if(!pModule){PyErr_Print();printf("ERROR: faild to load garbage.py\n");goto FAILED_MODULE;}//获取'garbage'模块中的'alibaba_garbage'函数。//如果获取失败或函数不可调用,打印错误信息并跳转到 FAILED_FUNC 标签进行清理。PyObject *pFunc = PyObject_GetAttrString(pModule, "alibaba_garbage");if(!pFunc || !PyCallable_Check(pFunc)){PyErr_Print();printf("ERROR: function alibaba_garbage not found or not callable\n");goto FAILED_FUNC;}//调用 alibaba_garbage 函数,不传递参数。//如果调用失败,打印错误信息并跳转到 FAILED_VALUE 标签进行清理。PyObject *pValue = PyObject_CallObject(pFunc, NULL);if(!pValue){PyErr_Print();printf("ERROR: function call failed\n");goto FAILED_VALUE;}char *result = NULL;if(!PyArg_Parse(pValue, "s", &result)){PyErr_Print();printf("ERROR: parse failed\n");goto FAILED_RESULT;}category = (char *)malloc(sizeof(char *)*(strlen(result)+1));memset(category, 0 , (strlen(result)+1));strncpy(category, result, (strlen(result)+1));// 释放发生错误之前分配的内存空间
FAILED_RESULT:Py_DECREF(pValue);
FAILED_VALUE:Py_DECREF(pFunc);
FAILED_FUNC:Py_DECREF(pModule);
FAILED_MODULE:return category;
}

内存泄漏

内存泄漏是指在计算机程序中,动态分配的内存未被正确释放,导致这些内存块不能被重新分配和使用。随着程序的运行,未释放的内存不断累积,最终可能耗尽可用内存资源,导致系统性能下降,甚至使程序或系统崩溃。

内存泄漏的成因
  1. 未释放动态分配的内存:

程序在使用 malloc、calloc 或 realloc 分配内存后,没有使用 free 函数释放内存。

  1. 循环或递归调用中未释放内存:

在循环或递归调用中,动态分配的内存未被释放。

  1. 异常退出或提前返回:

程序在处理错误或异常时,没有正确释放已经分配的内存。

  1. 丢失指针引用:

动态分配的内存地址被覆盖或丢失,没有其他指针指向该内存块。

栈上分配和堆上分配
栈上分配

栈上分配的内存(例如局部变量)在函数调用结束后会自动释放。

void function() {int local_variable = 10; // 栈上分配// local_variable 在函数结束时自动释放
}
堆上分配

堆上分配的内存需要程序员手动释放,否则会导致内存泄漏。

void function() {int *heap_variable = (int *)malloc(sizeof(int) * 10); // 堆上分配// 使用完 heap_variable 后需要手动释放内存free(heap_variable);
}

garbage.h

#ifndef __GARBAGE__H
#define __GARBAGE__Hvoid garbage_init(void);
void garbage_final(void);
char *garbage_category(char *category);//宏定义拍照指令和图片地址
#define WGET_CMD "wget http://127.0.0.1:8080/?action=snapshot -O /tmp/garbage.jpg"
#define GARBAGE_FILE "/tmp/garbage.jpg"#endif

main.c

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <wiringPi.h>
#include <pthread.h>#include "uartTool.h"
#include "garbage.h"
#include "pwm.h"
#include "myoled.h"
#include "socket.h"int serial_fd = -1;
pthread_cond_t cond;
pthread_mutex_t mutex;//该函数通过执行 shell 命令 ps 检测特定进程是否正在运行。
static int detect_process(const char *process_name)
{int n = -1;FILE *strm;char buf[128] = {0};sprintf(buf, "ps -ax | grep %s | grep -v grep", process_name);if ((strm = popen(buf, "r")) != NULL) {if (fgets(buf, sizeof(buf), strm) != NULL) {n = atoi(buf);}}else{return -1;}pclose(strm);return n;
}//从串口读取语音命令,并根据特定条件触发条件变量信号。
void *pget_voice(void *arg)
{unsigned char buffer[6] = {0xAA, 0x55, 0x00, 0x00, 0x55, 0xAA};int len = 0;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 = serialGetstring(serial_fd, buffer);if (len > 0 && buffer[2] == 0x46) {pthread_mutex_lock(&mutex);buffer[2] = 0x00;pthread_cond_signal(&cond);pthread_mutex_unlock(&mutex);}}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);}if (NULL != buffer){serialSendstring(serial_fd, buffer, 6);}pthread_exit(0);
}//控制垃圾桶打开和关闭。
void *popen_trash_can(void *arg)
{pthread_detach(pthread_self());unsigned char *buffer = (unsigned char *)arg;if (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] != 0x45){printf("%s|%s|%d: buffer[2]=0x%x\n", __FILE__, __func__, __LINE__, buffer[2]);pwm_write(PWM_GARBAGE);delay(2000);pwm_stop(PWM_GARBAGE);}pthread_exit(0);
}//初始化 OLED 显示屏并显示垃圾分类结果。
void*poled_show(void *arg)
{pthread_detach(pthread_self());myoled_init();oled_show(arg);pthread_exit(0);
}//等待条件变量信号,执行垃圾分类逻辑,并触发语音、垃圾桶和 OLED 显示。
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){pthread_mutex_lock(&mutex);pthread_cond_wait(&cond, &mutex);pthread_mutex_unlock(&mutex);buffer[2] = 0x00;system(WGET_CMD);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);remove(GARBAGE_FILE);}}void *pget_socket(void *arg)
{int s_fd = -1;// 服务器套接字文件描述符int c_fd = -1;// 客户端套接字文件描述符char buffer[6];// 接收数据缓冲区int nread = -1;// 接收到的数据长度struct sockaddr_in c_addr;// 客户端地址结构memset(&c_addr,0,sizeof(struct sockaddr_in));// 初始化客户端地址结构s_fd = socket_init(IPADDR, IPPORT);// 初始化服务器套接字printf("%s|%s|%d:s_fd=%d\n", __FILE__, __func__, __LINE__, s_fd);if (-1 == s_fd){pthread_exit(0);}sleep(3);int clen = sizeof(struct sockaddr_in);// 客户端地址结构的长度while(1){c_fd = accept(s_fd,(struct sockaddr *)&c_addr,&clen);// 接受客户端连接int keepalive = 1; // 开启TCP KeepAlive功能int keepidle = 5; // 5s内没收到数据开始发送心跳包int keepcnt = 3; // 每次发送心跳包的次数int keepintvl = 3; // 每3s发送一次心跳包setsockopt(c_fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&keepalive, sizeof(keepalive));setsockopt(c_fd, SOL_TCP, TCP_KEEPIDLE, (void *) &keepidle, sizeof(keepidle));setsockopt(c_fd, SOL_TCP, TCP_KEEPCNT, (void *)&keepcnt, sizeof(keepcnt));setsockopt(c_fd, SOL_TCP, TCP_KEEPINTVL, (void *)&keepintvl, sizeof(keepintvl));        printf("%s|%s|%d: Accept a connection from %s:%d\n", __FILE__, __func__, __LINE__, inet_ntoa(c_addr.sin_addr), ntohs(c_addr.sin_port));if(c_fd == -1){perror("accept");continue;}while(1){memset(buffer, 0, sizeof(buffer));nread = recv(c_fd, buffer, sizeof(buffer), 0); //n_read = read(c_fd,buffer, sizeof(buffer));printf("%s|%s|%d:nread=%d, buffer=%s\n", __FILE__, __func__,__LINE__, nread, buffer);if (nread > 0){if (strstr(buffer, "open")){pthread_mutex_lock(&mutex);pthread_cond_signal(&cond);pthread_mutex_unlock(&mutex);}}else if(0 == nread || -1 == nread){break;}}close(c_fd);}pthread_exit(0);
}int main(int argc, char *argv[])
{   int len = 0;int ret = -1;char *category = NULL;pthread_t get_voice_tid, category_tid, get_socket_tid;wiringPiSetup();garbage_init();ret = detect_process("mjpg_streamer"); //判断mjpg_streamer是否已经在运行if (-1 == ret){goto END;}else{printf("已运行mjpg_streamer,可以开始垃圾分类识别\n");}serial_fd = myserialOpen(SERIAL_DEV, BAUD);if (-1 == serial_fd) {goto END;}//开语音线程printf("%s|%s|%d\n", __FILE__, __func__, __LINE__);pthread_create(&get_voice_tid, NULL, pget_voice, NULL);//开网络线程pthread_create(&get_socket_tid, NULL, pget_socket, 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_join(get_socket_tid, NULL);pthread_mutex_destroy(&mutex);pthread_cond_destroy(&cond);close(serial_fd);
END:garbage_final;return 0; 
}

关于TCP KeepAlive

通过设置 TCP KeepAlive 选项,可以在客户端异常断开连接时检测到失效连接,并在必要时关闭它。它会自动发生在操作系统内核层面。

  1. KeepAlive 探测: 当启用了 TCP KeepAlive 并设置了相关参数后,操作系统内核会在连接空闲指定时间(TCP_KEEPIDLE)后开始发送 KeepAlive 探测包。
  2. 检测响应: 内核会等待客户端对探测包的响应。如果在指定的次数(TCP_KEEPCNT)内没有收到客户端的响应,内核会认为该连接已经失效。
  3. 关闭连接: 当探测包没有得到响应时,内核会自动关闭该连接,并通知应用程序。此时,你在应用程序中的 recv 调用会返回 -1,表示连接已经断开。

oled.c

这段代码实现了一个 OLED 显示功能,用于在一个指定位置上显示垃圾分类的结果。具体来说,代码分为两个主要部分:oled_show 函数和 myoled_init 函数。

#include <error.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdint.h>#include "oled.h"
#include "font.h"
#include "myoled.h"#define FILENAME "/dev/i2c-3"static struct display_info disp;int oled_show(void *arg)
{unsigned char *buffer = (unsigned char *)arg;//在屏幕上的指定位置显示指定内容oled_putstrto(&disp, 0, 9+1, "This garbage is:");// 设置字体disp.font = font2;//根据 buffer[2] 的值显示相应的垃圾分类结果switch(buffer[2]){case 0x41:oled_putstrto(&disp, 0, 20, "dry waste");break;case 0x42:oled_putstrto(&disp, 0, 20, "wet waste");break;case 0x43:oled_putstrto(&disp, 0, 20, "recyclable waste");break;case 0x44:oled_putstrto(&disp, 0, 20, "hazardous waste");break;case 0x45:oled_putstrto(&disp, 0, 20, "recognition failed");break;}// 再次设置字体disp.font = font2;//把需要显示的内容刷新到屏幕上oled_send_buffer(&disp); return 0;
}int myoled_init(void)
{int e;// 设置显示屏地址和字体disp.address = OLED_I2C_ADDR;disp.font = font2;// 打开和初始化 OLED 显示屏e = oled_open(&disp, FILENAME);e = oled_init(&disp);return e;
}

相关文章:

基于Linux的云端垃圾分类助手

项目简介 本项目旨在开发一个基于嵌入式系统的智能垃圾分类装置。该装置能够通过串口通信、语音播报、网络通信等多种方式&#xff0c;实现垃圾的自动识别和分类投放。系统采用多线程设计&#xff0c;确保各功能模块高效并行工作。 项目功能 垃圾分类识别 系统使用摄像头拍摄…...

【PYG】Planetoid中边存储的格式,为什么打印前十条边用edge_index[:, :10]

edge_index 是 PyTorch Geometric 中常用的表示图边的张量。它通常是一个形状为 [2, num_edges] 的二维张量&#xff0c;其中 num_edges 表示图中边的数量。每一列表示一条边&#xff0c;包含两个节点的索引。 实际上这是COO存储格式&#xff0c;官方文档里也有写&#xff0c;…...

【知识图谱系列】(实例)python操作neo4j构建企业间的业务往来的知识图谱

本章节通过聚焦于"金额"这一核心属性&#xff0c;构建了一幅知识图谱&#xff0c;旨在揭示"销售方"与"购买方"间的商业互动网。在这张图谱中&#xff0c;绿色节点象征着购买方&#xff0c;而红色节点则代表了销售方。这两类节点间的紧密连线&…...

解决MySQL删除/var/lib/mysql下的所有文件后无法启动的问题

解决MySQL删除/var/lib/mysql下的所有文件后无法启动的问题 确保清空/var/lib/mysql初始化启动mysql参考 确保清空/var/lib/mysql rm-rf /var/lib/mysql/* 初始化 mysql_install_db --usermysql --basedir/usr --datadir/var/lib/mysql 其中的mysql用户不要改成root。否则会…...

探索WebKit的Flexbox奇境:CSS Flexbox支持全解析

探索WebKit的Flexbox奇境&#xff1a;CSS Flexbox支持全解析 在现代网页设计中&#xff0c;响应式布局的需求日益增长&#xff0c;CSS Flexbox作为布局模式的一个突破性进展&#xff0c;提供了一种更加高效和灵活的方式来设计复杂的用户界面。WebKit&#xff0c;作为众多流行浏…...

Unity--协程--Coroutine

Unity–协程–Coroutine 1. 协程的基本概念 基本概念:不是线程,将代码按照划分的时间来执行,这个时间可以是具体的多少秒,也可以是物理帧的时间,也可以是一帧的绘制结束的时间。 协程的写法&#xff1a;通过返回IEnumerator的函数实现&#xff0c;使用yield return语句暂停执…...

详解COB显示屏的技术特点

COB&#xff08;Chip on Board&#xff09;显示屏作为一种采用倒装COB封装技术的LED显示屏&#xff0c;在显示效果以及使用稳定性跟防护性方面&#xff0c;拥有更大优势&#xff0c;今天跟随COB显示屏厂家中品瑞科技一起来看看&#xff0c;COB显示屏的技术特点&#xff1a; 1、…...

富唯智能推出的AMR复合机器人铝板CNC上下料方案

随着科技的不断进步&#xff0c;CNC加工行业正面临着前所未有的变革。传统的CNC上下料方式已无法满足现代生产对效率、精度和安全性的高要求。在这样的背景下&#xff0c;富唯智能推出的AMR复合机器人铝板CNC上下料方案&#xff0c;以其智能化、自动化的特点&#xff0c;引领了…...

springcloud-config服务器,同样的配置在linux环境下不生效

原本在windows下能争取的获取远程配置但是部署到linux上死活都没有内容&#xff0c;然后开始了远程调试&#xff0c;这里顺带讲解下获取配置文件如果使用的是Git源&#xff0c;config service是如何响应接口并返回配置信息的。先说问题&#xff0c;我的服务名原本是abc-abc-abc…...

写代码,为什么还需要作图?

引言 古人云 &#xff1a;一图胜千言&#xff0c;闲人说&#xff1a;无图无真相。 在日常的聊天工具当中&#xff0c;无论是使用微信&#xff0c;还是钉钉。使用图片或表情包的频次越来越高&#xff0c;那是为什么呢&#xff1f;其实在互联网没有那么发达的时候&#xff0c;我…...

一句话介绍什么是AI智能体?

什么是AI智能体&#xff1f; 一句话说就是利用各种AI的功能的api组合&#xff0c;完成你想要的结果。 例如你希望完成一个关于主题为啤酒主题的小红书文案图片&#xff0c;那么它就可以完成 前面几个步骤类似automa的组件&#xff0c;最后生成一个结果。...

32.哀家要长脑子了!

1.299. 猜数字游戏 - 力扣&#xff08;LeetCode&#xff09; 公牛还是挺好数的&#xff0c;奶牛。。。妈呀&#xff0c;一朝打回解放前 抓本质抓本质&#xff0c;有多少位非公牛数可以通过重新排列转换公牛数字&#xff0c;意思就是&#xff0c;当这个数不是公牛数字时&#x…...

Vue2 - 项目上线后生产环境中去除console.log的输出以及断点的解决方案

前言 当你准备将Vue.js应用程序部署到生产环境时,一个关键的优化步骤是移除代码中的所有 console.log 语句以及断点。在开发阶段,console.log 是一个非常有用的调试工具,但在生产环境中保留它们可能会影响性能和安全性。在本文中,我将向你展示如何通过使用Vue CLI 2来自动…...

phpword生成PDF

接上一篇phpword生成word文档&#xff0c;如有不明白的问题可以先查看上一篇文章 首先&#xff0c;生成PDF需要先生成word文档&#xff0c;而后通过word文档生成HTML文档&#xff0c;最后才可以通过HTML文档生成PDF文件&#xff0c;详细代码如下。 执行命令安装phpword&#…...

Linux进程优先级

1. 基本概念 cpu 资源分配的先后顺序&#xff0c;就是指进程的优先权&#xff08; priority &#xff09;。 优先权高的进程有优先执行权利。配置进程优先权对多任务环境的 linux 很有用&#xff0c;可以改善系统性能。还可以把进程运行到指定的CPU 上&#xff0c;这样一来&a…...

每日一题——Python实现PAT乙级1096 大美数(举一反三+思想解读+逐步优化)3千字好文

一个认为一切根源都是“自己不够强”的INTJ 个人主页&#xff1a;用哲学编程-CSDN博客专栏&#xff1a;每日一题——举一反三Python编程学习Python内置函数 Python-3.12.0文档解读 目录 我的写法 时间复杂度分析 空间复杂度分析 总结 哲学和编程思想 1. 抽象与具体化 …...

无锁编程——从CPU缓存一致性讲到内存模型(1)

一.前言 1.什么是有锁编程&#xff0c;什么是无锁编程&#xff1f; 在编程中&#xff0c;特别是在并发编程的上下文中&#xff0c;“无锁”和“有锁”是描述线程同步和资源访问控制的两种不同策略。有锁&#xff08;Locked&#xff09;: 有锁编程是指使用锁&#xff08;例如互…...

C++编程(七)继承

文章目录 一、继承&#xff08;一&#xff09;概念&#xff08;二&#xff09;语法格式&#xff08;三&#xff09;通过子类访问父类中的成员1. 类内2. 类外 &#xff08;四&#xff09;继承中的特殊成员函数1. 构造函数2. 析构函数3. 拷贝构造函数4. 拷贝赋值函数 二、多重继承…...

【ACM_2023】3D Gaussian Splatting for Real-Time Radiance Field Rendering

【ACM_2023】3D Gaussian Splatting for Real-Time Radiance Field Rendering 一、前言Abstract1 INTRODUCTION2 RELATED WORK2.1 Traditional Scene Reconstruction and Rendering2.2 Neural Rendering and Radiance Fields2.3 Point-Based Rendering and Radiance Fields 3 O…...

【TB作品】atmega16 计算器,ATMEGA16单片机,Proteus仿真

实验报告&#xff1a;基于ATmega16单片机的简易计算器设计 1. 实验背景 计算器是日常生活和工作中不可或缺的工具&#xff0c;通过按键输入即可实现基本的四则运算。通过本实验&#xff0c;我们将利用ATmega16单片机、矩阵键盘和LCD1602显示屏&#xff0c;设计并实现一个简易…...

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...

Nuxt.js 中的路由配置详解

Nuxt.js 通过其内置的路由系统简化了应用的路由配置&#xff0c;使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...

如何为服务器生成TLS证书

TLS&#xff08;Transport Layer Security&#xff09;证书是确保网络通信安全的重要手段&#xff0c;它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书&#xff0c;可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...

从零实现STL哈希容器:unordered_map/unordered_set封装详解

本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说&#xff0c;直接开始吧&#xff01; 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...

【Java_EE】Spring MVC

目录 Spring Web MVC ​编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 ​编辑参数重命名 RequestParam ​编辑​编辑传递集合 RequestParam 传递JSON数据 ​编辑RequestBody ​…...

网络编程(UDP编程)

思维导图 UDP基础编程&#xff08;单播&#xff09; 1.流程图 服务器&#xff1a;短信的接收方 创建套接字 (socket)-----------------------------------------》有手机指定网络信息-----------------------------------------------》有号码绑定套接字 (bind)--------------…...

Mysql中select查询语句的执行过程

目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析&#xff08;Parser&#xff09; 2.4、执行sql 1. 预处理&#xff08;Preprocessor&#xff09; 2. 查询优化器&#xff08;Optimizer&#xff09; 3. 执行器…...

零知开源——STM32F103RBT6驱动 ICM20948 九轴传感器及 vofa + 上位机可视化教程

STM32F1 本教程使用零知标准板&#xff08;STM32F103RBT6&#xff09;通过I2C驱动ICM20948九轴传感器&#xff0c;实现姿态解算&#xff0c;并通过串口将数据实时发送至VOFA上位机进行3D可视化。代码基于开源库修改优化&#xff0c;适合嵌入式及物联网开发者。在基础驱动上新增…...

深度学习之模型压缩三驾马车:模型剪枝、模型量化、知识蒸馏

一、引言 在深度学习中&#xff0c;我们训练出的神经网络往往非常庞大&#xff08;比如像 ResNet、YOLOv8、Vision Transformer&#xff09;&#xff0c;虽然精度很高&#xff0c;但“太重”了&#xff0c;运行起来很慢&#xff0c;占用内存大&#xff0c;不适合部署到手机、摄…...

Linux中《基础IO》详细介绍

目录 理解"文件"狭义理解广义理解文件操作的归类认知系统角度文件类别 回顾C文件接口打开文件写文件读文件稍作修改&#xff0c;实现简单cat命令 输出信息到显示器&#xff0c;你有哪些方法stdin & stdout & stderr打开文件的方式 系统⽂件I/O⼀种传递标志位…...