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

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 为图像人脸检测。

文件下载

  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

R-G-B

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值