NanopcT4 系统 人脸检测实验 超详细教程 代码及操作步骤

news2024/11/26 13:53:52

文章目录

  • 1.NanopcT4 系统烧写详细操作步骤
  • 2.vim 使用与 gcc 使用
  • 3.makefile 使用
  • 4.GPIO 引脚查看与连接
  • 5.使用vim 编写 LED 灯闪烁c 语言程序test1.c
  • 6.使用vim 编写 LED 灯闪烁shell 脚本程序test2.sh
  • 7.在ARM 上实现人脸检测

1.NanopcT4 系统烧写详细操作步骤

1)准备一张 8G 或以上容量的 SDHC 卡;

2)下载并解压 固件文件 rk3399-eflasher-friendlydesktop-bionic-4.4- arm64-20200324.img.zip 和 工具 win32diskimager;

3)在 Windows 下以管理员身份运行 win32diskimager,在界面上选择你的SD 卡盘符,选择解压后的 EFlasher 固件,点击 Write 按钮烧写到 SD 卡; 或者在 Linux 下使用 dd 命令将 rk3399-eflasher-friendlydesktop-bionic-4.4-arm64-20200324.img 写入 SD 卡;

4)将 SD 卡从电脑端弹出,插入 NanoPC-T4 的 microSD 卡槽;

5)长按 NanoPC-T4 上的 Power 键直到板上的 PWR 灯亮,系统会从 SD 卡启动, 并自动启动 EFlasher 烧写工具,你有多种途径可以操作 EFlasher:

方法 1: 连接 LCD 或 HDMI 显示屏,在图形界面上操作 EFlasher,如果屏幕不支持触摸,则需要使用 USB 鼠标来操作;

方法 2: 将开发板通过网线接入局域网,通过 ssh 登录开发板,然后输入命令 eflasher,根据命令行的提示进行操作;(注: ssh 登录的用户是 root,密码为 fa,开发板 IP 可查看路由器后台获得)

方法 3: 通过调试串口登录到串口终端,在终端上输入命令 eflasher 来操作;

方法 4: 连接一个 lcd2usb 配件到 NanoPC-T4 上,按配件上面的 K1 键可以选择要烧写的系统,然后按 K2 键确定烧写,烧写进度会在 lcd2usb 上显示;

6)烧写完成后,轻按 Power 键关机,从 NanoPC-T4 端弹出 SD 卡;

7)长按 Power 开机,会从 eMMC 启动你刚刚烧写的系统;

2.vim 使用与 gcc 使用

1)使用 vim 编写 Hello world 程序。

#include <iostream> 
using namespace std; 
int main()
{
	cout << “Hello world” << endl; return 0;
}

2)将 Hello word 程序保存为 hello.cpp 后,终端执行: g++ -o hello hello.cpp 进行程序编译
./hello 运行生成的程序
可以看到执行结果:Hello world

3)利用 vim 中替换的操作::%s/world/vim
执行上述操作,将输出改为 Hello vim

3.makefile 使用

利用 vim 编写以下程序:
1)ex2-2.c 程序如下:

#include <stdio.h> 
#include "f2.h" 
main()
{
	printf("Hello world!\n"); 
	f2();
}

2)f2.h 程序如下:

#include <stdio.h> 
void f2(void);

3)f2.c 程序如下:

#include <stdio.h> 
void f2()
{
	printf("This is printed by f2!\n");
}

4)Makefile 程序如下:

ex2-2:ex2-2.o f2.o
	gcc ex2-2.o f2.o -o ex2-2 
ex2-2.o:ex2-2.c f2.h
	gcc -c ex2-2.c 
f2.o:f2.c f2.h
	gcc -c f2.c

clean:
	rm -f ex2-2*.o 
	rm -r f2.o
	rm -r ex2-2

创建好上述 4 个文件后,用 shell 命令:make 进行编译。文件夹中生成ex2-2.o、f2.o、ex2-2 三个文件,输入./ex2-2 查看程序运行效果。输入 make clean 可以自动清除生成文件。

4.GPIO 引脚查看与连接

查看 Nanopc-T4 官方网站,查看 Nanopc-T4 的接口布局,如图 1 所示, GPIO 引脚定义对应 ARM 板实物,如图 1 所示,第一排 GPIO 引脚从左到右为Pin2、4、6 依次往下排,第二排为 Pin1、3、5 依次往下排。在 ARM 板终端输入 gpio readall,查看 wPi 与 Physical 对应的关系(GPIO0 引脚为 ARM 针脚11,GPIO7 引脚为 ARM 针脚 7),进行硬件的 GPIO 连接,接线图如图 2 所示。
在这里插入图片描述
图 1. NanopcT4

在这里插入图片描述

5.使用vim 编写 LED 灯闪烁c 语言程序test1.c

#include <wiringPi.h> 
int main(void)
{
	wiringPiSetup(); 
	pinMode(7, OUTPUT); 
	for (;;)
	{
		digitalWrite(7, HIGH); 
		delay(500); 
		digitalWrite(7, LOW); 
		delay(500);
	}
}

将上述程序编写并保存后,进行编译并运行:

gcc -Wall -o test1 test1.c -lwiringPi -lwiringPiDev -lpthread -lrt - lm -lcrypt
sudo ./test1

6.使用vim 编写 LED 灯闪烁shell 脚本程序test2.sh

LED=0
gpio mode $LED out 
while true; do
	gpio write $LED 1 
	sleep 0.5
	gpio write $LED 0 
	sleep 0.5
done

终端输入 sudo source test2.sh 并运行脚本

7.在ARM 上实现人脸检测

在终端输入 sudo qtcreator,使用权限打开 QT,ARM 对 GPIO 的控制需要权限,点击左侧”Welcome”→”Projects”→”New Project”;弹出窗口, 选择”Application”→”Qt Widgets Application”点击”Choose…”;新建工程,输入 Name(工程名)和 Create in(路径),一直点击”Next”,最后点击”Finish”;新建工程成功,左侧工程目录有文件和文件夹都是工程文件, 双击打开 pro 文件,将 opencv 库添加到 QT 工程中,添加内容为:

NCLUDEPATH += /usr/local/include \
			  /usr/local/include/opencv4 
LIBS += /usr/local/lib/libopencv*
LIBS += -lwiringPi \
	    -lwiringPiDev \
		-lpthread \
		-lrt \

		-lm \
		-lcrypt

双击打开 Forms 下的 mainwindow.ui,左侧为控件列表,中间部分为 QT 运行后界面,在左侧控件列表中找到”Label”和”Push Button”,使用控件可以用拖拽的方式将控件放到中间界面,界面和控件的大小均可使用鼠标直接拉伸, 也可以在右小角的属性列表中调节。本实验需要一个”Label” 控件和两个”Push Button”,将三个控件拖拽到界面中后,调节大小和位置,然后通过QT 控件创建控件相关槽函数,具体操作如下:

右键点击第一个放入的”Push Button”,选择”Go to slot…”→”OK” 后会转到一个函数, 回到 mainwindow.ui , 右键点击第二个放入的”Push Button”,选择”Go to slot…”→”OK”同样会转到一个函数。
修改和添加其它功能函数:

右 键 点 击 Headers, 选 择 ”Add New…”→”C++ Header File”→”Choose…”,在 Name 输入:dnnfacedetect.h ,Path 默认不变, 点击 ”Next”→”Finish”, 打开 dnnfacedetect.h 文件,在 ”#define DNNFACEDETECT_H“和”#endif // DNNFACEDETECT_H“添加以下代码:

#include <opencv2/opencv.hpp> 
#include <opencv2/dnn/dnn.hpp> 
#include <iostream>
#include <QFileDialog> 
#include <QLabel>
#include <opencv2/core/core.hpp> 
#include <opencv2/highgui/highgui.hpp> 
#include <opencv2/imgproc.hpp> 
#include <string>
#include <wiringPi.h> 
#include <sys/time.h> 
using namespace std; 
using namespace cv; 
struct M
{
	Mat frameR; bool markR;
};
class dnnfacedetect
{
private:
	string _modelbinary, _modeldesc; dnn::Net _net;
public:
	//构造函数 传入模型文件

	dnnfacedetect();
	dnnfacedetect(string modelBinary, string modelDesc);
	~dnnfacedetect();
	//置信阈值
	float confidenceThreshold; double inScaleFactor; size_t inWidth;
	size_t inHeight; Scalar meanVal;
	//初始化DNN网络bool initdnnNet();
	//人脸检测
	//vector<Mat> detect(Mat frame); M detect(Mat frame);
};

双击打开 mainwindow.h 文件,将文件内容修改和添加成以下内容:

#ifndef MAINWINDOW_H 
#define MAINWINDOW_H 
#include <QMainWindow> 
#include "dnnfacedetect.h"
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
	Q_OBJECT
public:
	MainWindow(QWidget* parent = nullptr);
	~MainWindow(); private slots:
	void on_pushButton_clicked(); 
	void on_pushButton_2_clicked();
private:
	Ui::MainWindow* ui;
	QImage cvMat_to_QImage(const cv::Mat& mat); 
	VideoCapture cap;
	Mat frame; 
	Mat pic; 
	QImage image; 
	bool mark;
	M checkR;
	int cameraMark;
};
#endif // MAINWINDOW_H

双击打开 main.cpp 文件修改成以下内容:

#include "mainwindow.h" 
#include <QApplication>
int main(int argc, char* argv[])
{
	wiringPiSetup(); 
	pinMode(7, OUTPUT); 
	pinMode(0, OUTPUT); 
	digitalWrite(7, LOW); 
	digitalWrite(0, LOW);
	QApplication a(argc, argv); 
	MainWindow w;
	w.show();
	return a.exec();
}

右 键 点 击 Sources, 选 择 ”Add New…”→”C++ Source
File”→”Choose…”,在 Name 输入:dnnfacedetect.cpp ,Path 默认不变, 点击”Next”→”Finish”,打开 dnnfacedetect.cpp 文件添加以下代码:

#include "dnnfacedetect.h" 
dnnfacedetect::dnnfacedetect()
{
	dnnfacedetect("", "");
}
//构造函数
dnnfacedetect::dnnfacedetect(string modelBinary, string modelDesc)
{
	_modelbinary = modelBinary;
	_modeldesc = modelDesc;
	//初始化置信阈值confidenceThreshold = 0.6;
	inScaleFactor = 0.5;
	inWidth = 300;
	inHeight = 300;
	meanVal = Scalar(104.0, 177.0, 123.0);
}
dnnfacedetect::~dnnfacedetect()
{
	_net.~Net();
}

//初始化dnnnet
bool dnnfacedetect::initdnnNet()
{
	_net = dnn::readNetFromTensorflow(_modelbinary, _modeldesc);

	_net.setPreferableBackend(dnn::DNN_BACKEND_OPENCV);
	_net.setPreferableTarget(dnn::DNN_TARGET_CPU); 
	return !_net.empty();
}
//人脸检测
M dnnfacedetect::detect(Mat frame)
{
	Mat tmpsrc = frame; 
	M reu;
	reu.markR = false;
	vector<Mat> dsts = vector<Mat>();
	// 修改通道数
	if (tmpsrc.channels() == 4)
		cvtColor(tmpsrc, tmpsrc, COLOR_BGRA2BGR);
	// 输入数据调整
	Mat inputBlob = dnn::blobFromImage(tmpsrc, inScaleFactor, Size(inWidth, inHeight), meanVal, false, false);
	_net.setInput(inputBlob, "data");

	//人脸检测
	Mat detection = _net.forward("detection_out");

	Mat detectionMat(detection.size[2], detection.size[3], CV_32F, detection.ptr<float>());

	//检测出的结果进行绘制和存放到dsts中
	for (int i = 0; i < detectionMat.rows; i++) {
		//置值度获取
		float confidence = detectionMat.at<float>(i, 2);
		//如果大于阈值说明检测到人脸
		if (confidence > confidenceThreshold) {
			reu.markR = true;
			//计算矩形
			int xLeftBottom = static_cast<int>(detectionMat.at<float>(i, 3) * tmpsrc.cols);
			int yLeftBottom = static_cast<int>(detectionMat.at<float>(i, 4) * tmpsrc.rows);
			int xRightTop = static_cast<int>(detectionMat.at<float>(i, 5) * tmpsrc.cols);
			int yRightTop = static_cast<int>(detectionMat.at<float>(i, 6) * tmpsrc.rows);
			//生成矩形
			Rect rect((int)xLeftBottom, (int)yLeftBottom,

				(int)(xRightTop - xLeftBottom), (int)(yRightTop - yLeftBottom));

			//截出图矩形存放到dsts数组中Mat tmp = tmpsrc(rect); dsts.push_back(tmp);

			//在原图上用红框画出矩形
			rectangle(frame, rect, Scalar(0, 0, 255));
		}
	}
	cv::resize(frame, reu.frameR, Size(640, 480), 0, 0, INTER_LINEAR); 
	return reu;
}

双击打开 mainwindow.cpp 文件修改成以下内容:

#include "mainwindow.h" 
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget* parent)
	: QMainWindow(parent)
	, ui(new Ui::MainWindow)
{
	ui->setupUi(this);
}

MainWindow::~MainWindow()
{
	delete ui;
}
/********************Mat转QImage函数*********************/ 
QImage MainWindow::cvMat_to_QImage(const cv::Mat& mat)
{
	switch (mat.type())
	{
		// 8-bit, 4 channel case CV_8UC4:
		{
			QImage image(mat.data, mat.cols, mat.rows, mat.step, QImage::Format_RGB32); 
			return image;
		}
		// 8-bit, 3 channel case CV_8UC3:
		{
			QImage image(mat.data, mat.cols, mat.rows, mat.step, QImage::Format_RGB888); 
			return image.rgbSwapped();

		}
		// 8-bit, 1 channel case CV_8UC1:
		{
			static QVector<QRgb> sColorTable;
			// only create our color table once if (sColorTable.isEmpty())
			{
				for (int i = 0; i < 256; ++i) sColorTable.push_back(qRgb(i, i, i));
			}
			QImage image(mat.data, mat.cols, mat.rows, mat.step, QImage::Format_Indexed8); 
			image.setColorTable(sColorTable);
			return image;
		}
	default:
		qDebug("Image format is not supported: depth=%d and %d channels\n", mat.depth(), mat.channels());
		break;
	}
	return QImage();
}
/*********************开始按键************************/ 
void MainWindow::on_pushButton_clicked()
{
	cameraMark = 10; 
	cap.open(cameraMark); 
	mark = true;
	if (!cap.open(cameraMark))
	{
		ui->label->setText("camera error"); 
		digitalWrite(7, HIGH);
		delay(500); 
		digitalWrite(7, LOW); 
		delay(500); 
		digitalWrite(7, HIGH);
		delay(500); 
		digitalWrite(7, LOW); 
		return;
	}
	digitalWrite(0, LOW); 
	digitalWrite(7, HIGH); 
	namedWindow("test"); 
	while (mark)
	{
		cap >> frame;
		cv::resize(frame, pic, Size(640, 480), 0, 0, INTER_LINEAR); 
		image = cvMat_to_QImage(pic);
		ui->label->setPixmap(QPixmap::fromImage(image)); 
		ui->label->update();
		waitKey(5);
	}
}
/*********************检测按键************************/ 
void MainWindow::on_pushButton_2_clicked()
{
	string ModelBinary = ".pb"; 
	string ModelDesc = ".pbtxt"; 
	if (mark == false)
	{
		return;
	}
	mark = false; 
	destroyWindow("test"); 
	cap.release();
	//初始化
	dnnfacedetect fdetect = dnnfacedetect(ModelBinary, ModelDesc); 
	if (!fdetect.initdnnNet())
	{
		ui->label->setText("初始化DNN人脸检测失败!"); 
		digitalWrite(7, HIGH);
		delay(500);
		digitalWrite(7, LOW); 
		delay(500); 
		digitalWrite(7, HIGH); 
		delay(500); 
		digitalWrite(7, LOW); 
		return;
	}
	if (!frame.empty()) {
		checkR = fdetect.detect(frame); 
		if (checkR.markR == true)
		{
			digitalWrite(7, LOW); 
			digitalWrite(0, HIGH);
		}
		image = cvMat_to_QImage(checkR.frameR);
		ui->label->setPixmap(QPixmap::fromImage(image));

	}
	//waitKey(5);
}

将文件 opencv_face_detector.pbtxt 和 opencv_face_detector_uint8.pb复制粘贴到 ARM 中,将路径添加到检测按键的函数中。

将 USB 相机插在 ARM 板上,建议使用 USB3.0 的接口,然后点击 QT 中左下第二个运行程序。

注意时间戳问题,系统时间要修改为当前时间使用指令 sudo date -s ‘20201213 21:14:50’(当前时间)对系统时间进行修改。

按键 1 为开始采集图像,按键 2 为图像人脸检测。

文件下载

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

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

相关文章

口语理解任务源码详解系列(二)利用seq2seq-attention模型实现

利用seq2seq-attention模型实现 写在前面 在前文介绍了项目的数据集构建&#xff1a;传送门 本文利用seq2seq-attention实现&#xff1a;实现细节请参考论文&#xff1a;《Attention-Based Recurrent Neural Network Models for Joint Intent Detection and Slot Filling》 1.意…

喜羊羊贴吧顶帖软件实战教学

喜羊羊贴吧顶帖软件实战教学#贴吧顶帖#贴吧推广 大家好&#xff0c;欢迎来到百收网SEO这期视频&#xff0c;给大家更新一下百度贴最新的一个顶帖视频教程。首先我们今天用的顶帖软件是我们的喜羊羊173 的一个版本&#xff0c;软件的话在我们的群文件去下载&#xff0c;就是我们…

如何查看货物的物流状态

想不想有一个一键批量查询快递号的软件&#xff1f;今天&#xff0c;小编向您介绍一款软件&#xff1a;“固乔快递查询助手”&#xff0c;该软件是固乔工作室正式推出的专业快递和物流单号出货信息批量查询软件。这款软件功能实用&#xff0c;操作简单&#xff0c;页面简单&…

使用 Jackson 库对日期时间的动态序列化反序列化操作

0.背景 因某项目中的数据报表功能在创建年报 和月报时需要生成不同的日期格式&#xff0c;但数据结构未变&#xff0c;为避免类的冗余定义&#xff0c;故使用如下方式来动态设置日期格式&#xff0c;在不同报表是使用不同格式的时间格式来保存数据。 1.代码介绍 PS:此介绍有Cha…

深度学习技巧应用23-利用latex对深度学习各种网络模型的图像进行绘制

大家好,我是微学AI,今天给大家介绍一下深度学习技巧应用23-利用latex对深度学习各种网络模型的图像进行绘制,大家知道那些好看的模型结构图是怎么画的吗?今天就给大家手把手的利用latex绘画出深度学习模型图出来,我将利用latex画出AlexNet,LeNet,VGG16,U-Net高清的网络模型…

微服务一 实用篇 - 5.1 ElasticSearch安装

《微服务一 实用篇 - 5.1 ElasticSearch安装》 提示: 本材料只做个人学习参考,不作为系统的学习流程,请注意识别!!! 《微服务一 实用篇 - 5.1 ElasticSearch安装》 《微服务一 实用篇 - 5.1 ElasticSearch安装》1.部署单点es1.1.创建网络1.2.加载镜像1.3.运行 2.部署kibana2.1…

达芬奇快编键盘使用指南——个人白皮书分享

文章目录 序言常见问题&#xff08;陆续更新&#xff09;1.没有指示灯&#xff0c;不知道怎么开机 功能分区和翻译查询A快编工具&#xff08;Smart Insrt&#xff09;B修剪工具&#xff08;Trim In&#xff09;C多功能按键&#xff08;Esc&#xff09;D多机位区&#xff08;Cam…

新加坡访问学者签证申请的三个注意事项

新加坡是一个独特而美丽的国家&#xff0c;吸引了许多学者和研究人员前来访问和交流。如果您计划前往新加坡进行学术交流&#xff0c;下面是知识人网小编整理的关于新加坡访问学者签证申请的三个注意事项&#xff0c;希望对您有所帮助。 1. 签证申请和文件准备&#xff1a; 在…

Scala入门到放弃—01—概述

文章目录 概述什么是是Scala&#xff1f;为什么要使用Scala? 配置环境安装测试附 基本语法定义变量基本数据类型lazy在Scala中的应用 概述 什么是是Scala&#xff1f; https://www.scala-lang.org/ Scala combines object-oriented and functional programming in one conci…

ELK实验部署过程

ELK集群部署环境准备 配置ELK日志分析系统 192.168.1.51 elk-node1 es、logstash、kibana 192.168.1.52 elk-node2 es、logstash 192.168.1.53 apache logstash &#xff08;我这里是把虚拟机的配置全部都改为2核3G的&#xff09; 2台linux 第1台&#xff1a;elk-nod…

大数据开发工程师前景如何?

大数据需求越来越多&#xff0c;只有技术在手不愁找不到工作。 大数据工程师的技术要求如下&#xff1a; 1、掌握至少一种数据库开发技术&#xff1a;Oracle、Teradata、DB2、Mysql等&#xff0c;灵活运用SQL实现海量数据ETL加工处理&#xff1b; 2、熟悉Linux系统常规shell…

软件工程——第8章维护知识点整理

本专栏是博主个人笔记&#xff0c;主要目的是利用碎片化的时间来记忆软工知识点&#xff0c;特此声明&#xff01; 文章目录 1.维护阶段的基本任务是&#xff1f; 2.大型软件的维护成本大概是开发成本的几倍&#xff1f; 3.什么是软件维护&#xff1f; 4.软件维护分为哪几类…

python代码练习:猜成语游戏

python代码练习&#xff1a;猜成语游戏 题目结果展示源代码 题目 成语填填乐&#xff0c;随机输出一条包含一个空格的成语&#xff0c;填写答案并判断是否正确&#xff0c;正确加2分&#xff0c;输出“正确&#xff0c;你真棒”&#xff0c;错误减2分&#xff0c;输出“错了”…

git tag详解

文章目录 前言1. Git tag的基本概念和用法1.1. 什么是 Git tag&#xff1f;1.2. Git 标签有什么作用&#xff1f; 2. 创建 Git tag2.1. 创建轻量级tag2.2. 创建带有注释的tag2.3. 编辑已有的tag 3. 列出和检出 Git tag3.1. 列出所有tag3.3. 列出匹配的tag3.4. 检出tag 4. 将 Gi…

可视化 | Flask+Mysql+PyEcharts 电影Top250数据分析系统

文章目录 &#x1f3f3;️‍&#x1f308; 1. 数据库数据表1. 电影信息数据表2. 用户数据表 &#x1f3f3;️‍&#x1f308; 2. 各子界面1. 登陆界面2. 注册界面3. 电影信息概要界面4. 搜索界面5. 各年份上映电影数量6. 电影榜单TOP107. 评价人数TOP208. 地区电影TOP109. 电影…

uniapp 微信小程序导航功能(单个地址)

获取终点的坐标&#xff0c;根据终点的坐标&#xff0c;终点名称&#xff0c;终点详细地址&#xff0c;调起地图导航到第三方APP 1、针对单个地址导航 <template><view click"toGetLocation"></view><view click"toNavigation">&…

利用Docker实现容器互连

实验要求 掌握利用Docker实现跨主机容器互连的方法。 实验准备 要求实验主机能够连接外网&#xff0c;已经正确安装Docker&#xff0c;并关闭防火墙和selinux&#xff0c;各主机配置信息如表所示 表 主机配置信息表 主机名 IP地址/子网掩码 容器名 容器IP地址 node1 你…

选对方法,K8s 多集群管理没那么难

作者&#xff1a;庄宇 Kubernetes 作为一项核心技术已成为现代应用程序架构的基础&#xff0c;将 Kubernetes 作为容器编排系统已发展为越来越多企业的必然选择。 随着对云计算接受程度不断提高&#xff0c;以及企业规模和业务持续发展的共同驱动下&#xff0c;越来越多的企业…

开发模式、API接口

文章目录 一、web开发模式1.1 前后端混合开发1.2 前后端分离开发 二、API接口2.1 简介2.2 RESTful API接口规范 道阻且长&#xff0c;行则将至&#xff0c;行而不辍&#xff0c;未来可期&#x1f31f;。人生是一条且漫长且充满荆棘的道路&#xff0c;一路上充斥着各种欲望与诱惑…

rtdetr:paddledetection与ultralytics对比

转眼间&#xff0c;自DETR被提出已经过去了2年了&#xff0c;如今又迎来了2023年&#xff0c;可以说&#xff0c;这是Transformer框架在CV领域发力的第3个年头了。时至今日&#xff0c;对Transformer的质疑声越来越小了&#xff0c;它的强大得到了越来越多、越来越广泛的认可。…