QT+OpenCV在Android上实现人脸实时检测与目标检测
一、功能介绍
在当今的移动应用领域,随着技术的飞速发展和智能设备的普及,将先进的计算机视觉技术集成到移动平台,特别是Android系统中,已成为提升用户体验、拓展应用功能的关键。其中,目标检测与人脸识别作为计算机视觉领域的两大基石,广泛应用于安全监控、智能门禁、图像分类、增强现实等多个场景,对促进物联网、智慧城市等前沿科技的发展起着至关重要的作用。
YOLOv3,作为YOLO系列的最新版本,以其快速、准确的目标检测能力著称,能够在单个神经网络中同时进行对象分类和定位,特别适合实时应用需求。该模型通过优化的网络结构设计,实现了速度与精度的较好平衡,是目前广泛应用的目标检测模型之一。
卷积神经网络(CNN,Convolutional Neural Networks)作为深度学习领域的重要组成部分,尤其在图像识别和处理方面展现出了卓越的能力。在人脸识别任务中,CNN能够学习并提取人脸特征,实现高精度的人脸检测与识别。结合特定的人脸识别模型,如FaceNet等,可以在移动平台上实现快速且准确的人脸验证或识别功能,这对于安全认证、个性化服务等领域有着直接的应用价值。
本项目通过Qt框架整合OpenCV与YOLOv3及CNN模型,不仅展示了如何在Android平台上高效实现复杂计算机视觉算法的集成,还为开发者提供了一个实践案例,探索了移动设备上高性能目标检测与人脸识别技术的可行性。这不仅促进了人工智能技术在移动应用中的普及与深化,也为未来的智能安防、健康管理、娱乐互动等应用场景提供了坚实的技术基础。项目的跨平台特性也为软件的广泛部署与应用提供了便利,进一步推动了AI技术与移动互联网的融合创新。
Qt是一个由Qt Company(前身为Trolltech,后被诺基亚收购,再后由Digia接手,并最终成立Qt公司)开发的跨平台C++图形用户界面应用程序开发框架。它自1991年起由Haavard Nord和Eirik Chambe-Eng创建,支持多个主流平台的应用程序开发,包括Android、Windows、iOS和Linux等。Qt框架提供了丰富的功能和工具,涵盖图形用户界面设计、数据库操作、网络编程、文件处理等多个方面,并通过其广泛的类库加速应用程序的开发过程。Qt具有良好的文档和社区支持,广泛用于桌面应用、移动应用、嵌入式系统等多种类型的应用程序开发。不仅可用于开发图形用户界面程序,还可用于非GUI程序,如控制台工具和服务器。Qt的发展历程展现了其不断适应市场需求和技术进步的能力,为开发者提供了强大的工具和平台。
本篇文章用到的全部软件工具、库的模型,以及APP都可以在这里下载(网盘):https://pan.quark.cn/s/145a9b3f7f53
实现效果:
二、OpenCV下载
OpenCV是开源的计算机视觉、机器学习软件库,其图片处理的功能非常强大,并且速度很快。 作为目标检测功能,OpenCV里本身就自带了很多的模型,比如: 人眼检测、鼻子检测、嘴巴检测、人脸检测、人体检测、猫脸检测等等,下载完OpenCV,就能直接进行图像识别测试体验,并且OpenCV也可以直接调用YOLO的模型,精确识别各种物体,yolo v3 里自带的模型文件可以精确识别常见的很多物体: 比如: 狗、汽车、自行车、人体、书本、手机等等。
OpenCV下载地址:https://opencv.org/releases/page/3/
可以直接下载不同平台的SDK包,非常的方便。
下载下来之后。
主要需要使用的文件就在这里面。
三、YOLO目标检测算法
3.1 YOLO算法介绍
YOLO算法官网介绍:https://pjreddie.com/darknet/yolo/
You only look once (YOLO) is a state-of-the-art, real-time object detection system. On a Pascal Titan X it processes images at 30 FPS and has a mAP of 57.9% on COCO test-dev.
You Only Look Once (YOLO) 是最先进的实时目标检测系统。在 Pascal Titan X 上,它以 30 FPS 处理图像,并且在 COCO 测试开发上的 mAP 为 57.9%。
Comparison to Other Detectors
YOLOv3 is extremely fast and accurate. In mAP measured at .5 IOU YOLOv3 is on par with Focal Loss but about 4x faster. Moreover, you can easily tradeoff between speed and accuracy simply by changing the size of the model, no retraining required!
与其他探测器的比较
YOLOv3 非常快速且准确。在 mAP 中,测量结果为 0.5 IOU YOLOv3 与 Focal Loss 相当,但速度快约 4 倍。此外,只需更改模型的大小即可轻松在速度和准确性之间进行权衡,无需重新训练!
3.2 Linux快速体验
在Linux下快速体验YOLO算法的目标检测(采用官方的模型)。
(1)安装darknet
git clone https://github.com/pjreddie/darknet
cd darknet
make
(2)下载权重文件
wget https://pjreddie.com/media/files/yolov3.weights
yolov3.weights
是 YOLOv3 网络训练得到的权重文件,存储了神经网络中每个层次的权重和偏置信息。
在cfg/
目录下已经包含了yolov3对应的配置文件。
(3)运行detector
./darknet detect cfg/yolov3.cfg yolov3.weights data/dog.jpg
运行输出的信息:
layer filters size input output0 conv 32 3 x 3 / 1 416 x 416 x 3 -> 416 x 416 x 32 0.299 BFLOPs1 conv 64 3 x 3 / 2 416 x 416 x 32 -> 208 x 208 x 64 1.595 BFLOPs.......105 conv 255 1 x 1 / 1 52 x 52 x 256 -> 52 x 52 x 255 0.353 BFLOPs106 detection
truth_thresh: Using default '1.000000'
Loading weights from yolov3.weights...Done!
data/dog.jpg: Predicted in 0.029329 seconds.
dog: 99%
truck: 93%
bicycle: 99%
3.3 官方模型支持识别的目标类型
person
bicycle
car
motorbike
aeroplane
bus
train
truck
boat
traffic light
fire hydrant
stop sign
parking meter
bench
bird
cat
dog
horse
sheep
cow
elephant
bear
zebra
giraffe
backpack
umbrella
handbag
tie
suitcase
frisbee
skis
snowboard
sports ball
kite
baseball bat
baseball glove
skateboard
surfboard
tennis racket
bottle
wine glass
cup
fork
knife
spoon
bowl
banana
apple
sandwich
orange
broccoli
carrot
hot dog
pizza
donut
cake
chair
sofa
pottedplant
bed
diningtable
toilet
tvmonitor
laptop
mouse
remote
keyboard
cell phone
microwave
oven
toaster
sink
refrigerator
book
clock
vase
scissors
teddy bear
hair drier
toothbrush
四、Qt Android工程配置
4.1 搭建Qt Android的开发环境
我用的开发环境是:QT5.12.6 ,下面是Android开发环境的配置。
4.2 编译选择的编译器
4.3 pro工程文件配置(很重要)
下面是介绍OpenCV的库引用如何配置。 分别贴出来了Windows、Android的32位和64位的库引用配置办法。
下面是Windows、Android的32位和64位的库引用配置代码。
# 根据操作系统选择编译器
win32 {# Windows下的编译器选择# 32位equals(QT_ARCH, x86) {# 32位编译器设置message("<----选择 windows电脑 32 编译器----->")}# 64位equals(QT_ARCH, x86_64) {# 64位编译器设置message("<----选择 windows电脑 64 编译器----->")#添加opencv头文件的路径,需要根据自己的头文件路径进行修改
INCLUDEPATH += C:/opencv_4.x/opencv/build/include
INCLUDEPATH += C:/opencv_4.x/opencv/build/include/opencv
INCLUDEPATH += C:/opencv_4.x/opencv/build/include/opencv2LIBS += -LC:/opencv_4.x/opencv/build/x64/vc15/lib\-lopencv_world430}
}#Android环境配置
android {
message("<----选择 Android 编译器----->")
contains(ANDROID_TARGET_ARCH,armeabi-v7a) {message("armeabi-v7a")ANDROID_OPENCV = C:/Users/11266/Downloads/opencv-4.3.0-android-sdk/OpenCV-android-sdk/sdk/nativeANDROID_EXTRA_LIBS = $$ANDROID_OPENCV/libs/armeabi-v7a/libopencv_java4.soINCLUDEPATH += $$ANDROID_OPENCV/jni/include/opencv2
INCLUDEPATH += $$ANDROID_OPENCV/jni/includeLIBS += $$ANDROID_OPENCV/libs/armeabi-v7a/libopencv_java4.so
LIBS += $$ANDROID_OPENCV/staticlibs/armeabi-v7a/libopencv_core.a
LIBS += $$ANDROID_OPENCV/staticlibs/armeabi-v7a/libopencv_calib3d.a
LIBS += $$ANDROID_OPENCV/staticlibs/armeabi-v7a/libopencv_dnn.a
LIBS += $$ANDROID_OPENCV/staticlibs/armeabi-v7a/libopencv_features2d.a
LIBS += $$ANDROID_OPENCV/staticlibs/armeabi-v7a/libopencv_flann.a
LIBS += $$ANDROID_OPENCV/staticlibs/armeabi-v7a/libopencv_highgui.a
LIBS += $$ANDROID_OPENCV/staticlibs/armeabi-v7a/libopencv_imgcodecs.a
LIBS += $$ANDROID_OPENCV/staticlibs/armeabi-v7a/libopencv_imgproc.a
LIBS += $$ANDROID_OPENCV/staticlibs/armeabi-v7a/libopencv_ml.a
LIBS += $$ANDROID_OPENCV/staticlibs/armeabi-v7a/libopencv_objdetect.a
LIBS += $$ANDROID_OPENCV/staticlibs/armeabi-v7a/libopencv_photo.a
LIBS += $$ANDROID_OPENCV/staticlibs/armeabi-v7a/libopencv_stitching.a
LIBS += $$ANDROID_OPENCV/staticlibs/armeabi-v7a/libopencv_video.a
LIBS += $$ANDROID_OPENCV/staticlibs/armeabi-v7a/libopencv_videoio.a
LIBS += $$ANDROID_OPENCV/3rdparty/libs/armeabi-v7a/libcpufeatures.a
LIBS += $$ANDROID_OPENCV/3rdparty/libs/armeabi-v7a/libIlmImf.a
LIBS += $$ANDROID_OPENCV/3rdparty/libs/armeabi-v7a/liblibjasper.a
LIBS += $$ANDROID_OPENCV/3rdparty/libs/armeabi-v7a/liblibjpeg-turbo.a
LIBS += $$ANDROID_OPENCV/3rdparty/libs/armeabi-v7a/liblibpng.a
LIBS += $$ANDROID_OPENCV/3rdparty/libs/armeabi-v7a/liblibprotobuf.a
LIBS += $$ANDROID_OPENCV/3rdparty/libs/armeabi-v7a/liblibtiff.a
LIBS += $$ANDROID_OPENCV/3rdparty/libs/armeabi-v7a/liblibwebp.a
LIBS += $$ANDROID_OPENCV/3rdparty/libs/armeabi-v7a/libquirc.a
LIBS += $$ANDROID_OPENCV/3rdparty/libs/armeabi-v7a/libtbb.a
LIBS += $$ANDROID_OPENCV/3rdparty/libs/armeabi-v7a/libtegra_hal.a}contains(ANDROID_TARGET_ARCH,arm64-v8a) {message("arm64-v8a")ANDROID_OPENCV = C:/Users/11266/Downloads/opencv-4.3.0-android-sdk/OpenCV-android-sdk/sdk/nativeANDROID_EXTRA_LIBS = $$ANDROID_OPENCV/libs/arm64-v8a/libopencv_java4.soINCLUDEPATH += $$ANDROID_OPENCV/jni/include/opencv2
INCLUDEPATH += $$ANDROID_OPENCV/jni/includeLIBS += $$ANDROID_OPENCV/libs/arm64-v8a/libopencv_java4.so
LIBS += $$ANDROID_OPENCV/staticlibs/arm64-v8a/libopencv_core.a
LIBS += $$ANDROID_OPENCV/staticlibs/arm64-v8a/libopencv_calib3d.a
LIBS += $$ANDROID_OPENCV/staticlibs/arm64-v8a/libopencv_dnn.a
LIBS += $$ANDROID_OPENCV/staticlibs/arm64-v8a/libopencv_features2d.a
LIBS += $$ANDROID_OPENCV/staticlibs/arm64-v8a/libopencv_flann.a
LIBS += $$ANDROID_OPENCV/staticlibs/arm64-v8a/libopencv_highgui.a
#LIBS += $$ANDROID_OPENCV/staticlibs/arm64-v8aa/libopencv_imgcodecs.a
LIBS += $$ANDROID_OPENCV/staticlibs/arm64-v8a/libopencv_imgproc.a
LIBS += $$ANDROID_OPENCV/staticlibs/arm64-v8a/libopencv_ml.a
LIBS += $$ANDROID_OPENCV/staticlibs/arm64-v8a/libopencv_objdetect.a
LIBS += $$ANDROID_OPENCV/staticlibs/arm64-v8a/libopencv_photo.a
LIBS += $$ANDROID_OPENCV/staticlibs/arm64-v8a/libopencv_stitching.a
LIBS += $$ANDROID_OPENCV/staticlibs/arm64-v8a/libopencv_video.a
LIBS += $$ANDROID_OPENCV/staticlibs/arm64-v8a/libopencv_videoio.a
LIBS += $$ANDROID_OPENCV/3rdparty/libs/arm64-v8a/libcpufeatures.a
LIBS += $$ANDROID_OPENCV/3rdparty/libs/arm64-v8a/libIlmImf.a
LIBS += $$ANDROID_OPENCV/3rdparty/libs/arm64-v8a/liblibjasper.a
LIBS += $$ANDROID_OPENCV/3rdparty/libs/arm64-v8a/liblibjpeg-turbo.a
LIBS += $$ANDROID_OPENCV/3rdparty/libs/arm64-v8a/liblibpng.a
LIBS += $$ANDROID_OPENCV/3rdparty/libs/arm64-v8a/liblibprotobuf.a
LIBS += $$ANDROID_OPENCV/3rdparty/libs/arm64-v8a/liblibtiff.a
LIBS += $$ANDROID_OPENCV/3rdparty/libs/arm64-v8a/liblibwebp.a
LIBS += $$ANDROID_OPENCV/3rdparty/libs/arm64-v8a/libquirc.a
LIBS += $$ANDROID_OPENCV/3rdparty/libs/arm64-v8a/libtbb.a
LIBS += $$ANDROID_OPENCV/3rdparty/libs/arm64-v8a/libtegra_hal.a
}}
五、代码实现
5.1 C++实现(人脸检测)
#include <opencv2/opencv.hpp>int main() {std::string prototxt_path = "D:/deploy.prototxt.txt";std::string model_path = "D:/res10_300x300_ssd_iter_140000_fp16.caffemodel";cv::dnn::Net model = cv::dnn::readNetFromCaffe(prototxt_path, model_path);cv::VideoCapture capture(0); // 打开默认摄像头(设备号为0)if (!capture.isOpened()) {std::cout << "Failed to open the camera." << std::endl;return -1;}while (true) {cv::Mat frame;capture >> frame; // 读取视频帧if (frame.empty()) {break;}int h = frame.rows;int w = frame.cols;cv::Mat blob = cv::dnn::blobFromImage(frame, 1.0, cv::Size(300, 300), cv::Scalar(104.0, 177.0, 123.0));model.setInput(blob);cv::Mat output = model.forward();cv::Mat detectionMat(output.size[2], output.size[3], CV_32F, output.ptr<float>());float font_scale = 1.0;for (int i = 0; i < detectionMat.rows; ++i) {float confidence = detectionMat.at<float>(i, 2);if (confidence > 0.5) {int start_x = static_cast<int>(detectionMat.at<float>(i, 3) * w);int start_y = static_cast<int>(detectionMat.at<float>(i, 4) * h);int end_x = static_cast<int>(detectionMat.at<float>(i, 5) * w);int end_y = static_cast<int>(detectionMat.at<float>(i, 6) * h);cv::rectangle(frame, cv::Point(start_x, start_y), cv::Point(end_x, end_y), cv::Scalar(255, 0, 0), 2);std::ostringstream ss;ss << confidence * 100 << "%";cv::putText(frame, ss.str(), cv::Point(start_x, start_y - 5), cv::FONT_HERSHEY_SIMPLEX, font_scale, cv::Scalar(255, 0, 0), 2);}}cv::imshow("Face Detection", frame);char c = cv::waitKey(1);if (c == 27) { // 按下Esc键退出循环break;}}capture.release();cv::destroyAllWindows();return 0;
}
运行效果如下:
代码运行解释:
当运行这段代码时,执行操作的步骤:
(1)导入必要的OpenCV库:
#include <opencv2/opencv.hpp>
(2)指定人脸检测模型的路径和配置文件的路径:
std::string prototxt_path = "./deploy.prototxt.txt";
std::string model_path = "./res10_300x300_ssd_iter_140000_fp16.caffemodel";
(3)使用cv::dnn::readNetFromCaffe
函数读取人脸检测模型:
cv::dnn::Net model = cv::dnn::readNetFromCaffe(prototxt_path, model_path);
(4)创建一个cv::VideoCapture
对象来打开默认摄像头(设备号为0):
cv::VideoCapture capture(0);
(5)检查摄像头是否成功打开,如果没有成功打开则结束程序:
if (!capture.isOpened()) {std::cout << "Failed to open the camera." << std::endl;return -1;
}
(6)开始一个无限循环,用于处理实时视频流中的每一帧:
while (true) {// 读取视频帧cv::Mat frame;capture >> frame;if (frame.empty()) {break;}// 在帧上进行人脸检测// ...// 显示带有人脸检测结果的帧cv::imshow("Face Detection", frame);// 等待按键输入并检查是否按下了Esc键char c = cv::waitKey(1);if (c == 27) {break;}
}
在循环中,从摄像头读取一帧视频,并将其存储在名为frame
的cv::Mat
对象中。如果读取的帧为空,则退出循环。 使用cv::dnn::blobFromImage
函数将frame
图像转换为神经网络可以处理的格式。然后,将输入转换后的图像数据到人脸检测模型,并进行前向传播计算。之后,在每一帧上遍历检测到的人脸,并对于置信度高于0.5的人脸,在图像上绘制矩形框和置信度百分比。最后,使用cv::imshow
函数显示带有人脸检测结果的帧。
通过cv::waitKey
等待用户按键输入,并在用户按下Esc键时退出循环。对于其他按键,将继续循环处理下一帧。
当循环结束后,释放摄像头资源并关闭所有窗口:
capture.release();
cv::destroyAllWindows();
这样,代码就完成了从本地摄像头获取实时视频流并进行人脸检测的功能。
5.2 python实现(人脸检测)
下面的python代码与上面的C++代码一样,使用了OpenCV的深度学习模块(dnn)来进行人脸检测。
import cv2
import numpy as npprototxt_path = r"./deploy.prototxt.txt"
model_path =r"./res10_300x300_ssd_iter_140000_fp16.caffemodel"
model = cv2.dnn.readNetFromCaffe(prototxt_path, model_path)
image = cv2.imread("2.jpg")
h, w = image.shape[:2]
blob = cv2.dnn.blobFromImage(image, 1.0, (300, 300),(104.0, 177.0, 123.0))
model.setInput(blob)
output = np.squeeze(model.forward())
font_scale = 1.0
for i in range(0, output.shape[0]):confidence = output[i, 2]if confidence > 0.5:box = output[i, 3:7] * np.array([w, h, w, h])start_x, start_y, end_x, end_y = box.astype(np.int)cv2.rectangle(image, (start_x, start_y), (end_x, end_y), color=(255, 0, 0), thickness=2)cv2.putText(image, f"{confidence*100:.2f}%", (start_x, start_y-5), cv2.FONT_HERSHEY_SIMPLEX, font_scale, (255, 0, 0), 2)
cv2.imshow("image", image)
cv2.waitKey(0)
cv2.imwrite("beauty_detected.jpg", image)
代码功能流程解释:
(1)导入必要的库和模型:
- 导入cv2和numpy库,用于图像处理和数组操作。
- 设置人脸检测模型的路径。
(2)读取和预处理图像:
- 使用cv2.imread函数读取图像文件。
- 获取图像的高度和宽度(h, w)。
- 使用cv2.dnn.blobFromImage函数将图像转换为一个4维blob,这是深度学习模型输入的格式。
(3)加载模型并进行前向推理:
- 使用cv2.dnn.readNetFromCaffe函数加载人脸检测模型。
- 将预处理后的图像数据作为模型的输入。
- 使用模型的forward方法进行前向推理,得到输出结果。
(4)处理模型输出:
- 将输出结果转换为numpy数组,并使用np.squeeze函数去除维度为1的维度。
- 遍历输出结果的每个检测框。
- 对于置信度大于0.5的检测框:
- 计算检测框在原始图像中的坐标。
- 使用cv2.rectangle函数绘制人脸框。
- 使用cv2.putText函数在人脸框上方显示置信度百分比。
(5)显示和保存结果:
- 使用cv2.imshow函数显示处理后的图像。
- 使用cv2.waitKey函数等待键盘输入。
- 如果按下任意键,则使用cv2.imwrite函数保存结果图像。
5.3 目标检测示例代码(摄像头实时画面检测)
下面这份代码采用OpenCV打开摄像头,实时读取摄像头画面,调用YOLOV3模型,完成目标检测。
模型采用的是官方训练的模型,可以检测80种目标物体。
完整的代码如下:
#include <opencv2/opencv.hpp>
#include <opencv2/dnn.hpp>#include <fstream>
#include <iostream>
#include <algorithm>
#include <cstdlib>using namespace std;
using namespace cv;
using namespace cv::dnn;String yolo_cfg = "D:/linux-share-dir/yolov3/yolov3.cfg";
String yolo_model = "D:/linux-share-dir/yolov3/yolov3.weights";void image_detection(VideoCapture& cap);int main(int argc, char** argv)
{VideoCapture cap(0); // 打开默认摄像头if (!cap.isOpened()){cout << "无法打开摄像头" << endl;return -1;}image_detection(cap);return 0;
}void image_detection(VideoCapture& cap) {// 加载网络模型Net net = readNetFromDarknet(yolo_cfg, yolo_model);net.setPreferableTarget(DNN_TARGET_CPU);std::vector<String> outNames = net.getUnconnectedOutLayersNames();for (int i = 0; i < outNames.size(); i++) {printf("output layer name : %s\n", outNames[i].c_str());}vector<string> classNamesVec;ifstream classNamesFile("D:/linux-share-dir/yolov3/coco.names");if (classNamesFile.is_open()){string className = "";while (std::getline(classNamesFile, className))classNamesVec.push_back(className);}while (true){Mat frame;cap >> frame; // 读取摄像头数据Mat inputBlob = blobFromImage(frame, 1 / 255.F, Size(416, 416), Scalar(), true, false);net.setInput(inputBlob);// 进行检测std::vector<Mat> outs;net.forward(outs, outNames);vector<double> layersTimings;double freq = getTickFrequency() / 1000;double time = net.getPerfProfile(layersTimings) / freq;ostringstream ss;ss << "detection time: " << time << " ms";putText(frame, ss.str(), Point(20, 20), 0, 0.5, Scalar(0, 0, 255));vector<Rect> boxes;vector<int> classIds;vector<float> confidences;for (size_t i = 0; i < outs.size(); ++i){// Network produces output blob with a shape NxC where N is a number of// detected objects and C is a number of classes + 4 where the first 4// numbers are [center_x, center_y, width, height]float* data = (float*)outs[i].data;for (int j = 0; j < outs[i].rows; ++j, data += outs[i].cols){Mat scores = outs[i].row(j).colRange(5, outs[i].cols);Point classIdPoint;double confidence;minMaxLoc(scores, 0, &confidence, 0, &classIdPoint);if (confidence > 0.5){int centerX = (int)(data[0] * frame.cols);int centerY = (int)(data[1] * frame.rows);int width = (int)(data[2] * frame.cols);int height = (int)(data[3] * frame.rows);int left = centerX - width / 2;int top = centerY - height / 2;classIds.push_back(classIdPoint.x);confidences.push_back((float)confidence);boxes.push_back(Rect(left, top, width, height));}}}vector<int> indices;NMSBoxes(boxes, confidences, 0.5, 0.2, indices);for (size_t i = 0; i < indices.size(); ++i){int idx = indices[i];Rect box = boxes[idx];String className = classNamesVec[classIds[idx]];putText(frame, className.c_str(), box.tl(), FONT_HERSHEY_SIMPLEX, 1.0, Scalar(255, 0, 0), 2, 8);rectangle(frame, box, Scalar(0, 0, 255), 2, 8, 0);}imshow("YOLOv3-Detections", frame);char c = waitKey(1);if (c == 27) // 按下Esc键退出程序break;}return;
}
示例1:
5.4 目标检测示例代码(加载图片检测)
下面这份代码采用OpenCV加载本地磁盘的一张图片,调用YOLOV3模型,完成目标检测。
模型采用的是官方训练的模型,可以检测80种目标物体。
完整的代码如下:
#include <opencv2/opencv.hpp>
#include <opencv2/dnn.hpp>#include <fstream>
#include <iostream>
#include <algorithm>
#include <cstdlib>using namespace std;
using namespace cv;
using namespace cv::dnn;
void image_detection();String yolo_cfg = "D:/linux-share-dir/yolov3/yolov3.cfg";
String yolo_model = "D:/linux-share-dir/yolov3/yolov3.weights";int main(int argc, char** argv)
{image_detection();
}void image_detection() {//加载网络模型Net net = readNetFromDarknet(yolo_cfg, yolo_model);//net.setPreferableBackend(DNN_BACKEND_INFERENCE_ENGINE);net.setPreferableTarget(DNN_TARGET_CPU);std::vector<String> outNames = net.getUnconnectedOutLayersNames();for (int i = 0; i < outNames.size(); i++) {printf("output layer name : %s\n", outNames[i].c_str());}vector<string> classNamesVec;ifstream classNamesFile("D:/linux-share-dir/yolov3/coco.names");if (classNamesFile.is_open()){string className = "";while (std::getline(classNamesFile, className))classNamesVec.push_back(className);}// 加载图像 Mat frame = imread("D:/1.png");Mat inputBlob = blobFromImage(frame, 1 / 255.F, Size(416, 416), Scalar(), true, false);net.setInput(inputBlob);// 检测std::vector<Mat> outs;net.forward(outs, outNames);vector<double> layersTimings;double freq = getTickFrequency() / 1000;double time = net.getPerfProfile(layersTimings) / freq;ostringstream ss;ss << "detection time: " << time << " ms";putText(frame, ss.str(), Point(20, 20), 0, 0.5, Scalar(0, 0, 255));vector<Rect> boxes;vector<int> classIds;vector<float> confidences;for (size_t i = 0; i < outs.size(); ++i){// Network produces output blob with a shape NxC where N is a number of// detected objects and C is a number of classes + 4 where the first 4// numbers are [center_x, center_y, width, height]float* data = (float*)outs[i].data;for (int j = 0; j < outs[i].rows; ++j, data += outs[i].cols){Mat scores = outs[i].row(j).colRange(5, outs[i].cols);Point classIdPoint;double confidence;minMaxLoc(scores, 0, &confidence, 0, &classIdPoint);if (confidence > 0.5){int centerX = (int)(data[0] * frame.cols);int centerY = (int)(data[1] * frame.rows);int width = (int)(data[2] * frame.cols);int height = (int)(data[3] * frame.rows);int left = centerX - width / 2;int top = centerY - height / 2;classIds.push_back(classIdPoint.x);confidences.push_back((float)confidence);boxes.push_back(Rect(left, top, width, height));}}}vector<int> indices;NMSBoxes(boxes, confidences, 0.5, 0.2, indices);for (size_t i = 0; i < indices.size(); ++i){int idx = indices[i];Rect box = boxes[idx];String className = classNamesVec[classIds[idx]];putText(frame, className.c_str(), box.tl(), FONT_HERSHEY_SIMPLEX, 1.0, Scalar(255, 0, 0), 2, 8);rectangle(frame, box, Scalar(0, 0, 255), 2, 8, 0);}imshow("YOLOv3-Detections", frame);waitKey(0);return;
}
测试图片1:
测试图片2:
相关文章:

QT+OpenCV在Android上实现人脸实时检测与目标检测
一、功能介绍 在当今的移动应用领域,随着技术的飞速发展和智能设备的普及,将先进的计算机视觉技术集成到移动平台,特别是Android系统中,已成为提升用户体验、拓展应用功能的关键。其中,目标检测与人脸识别作为计算机视…...
常见网络攻击方式及防御方法
1. DDOS攻击(分布式拒绝服务攻击) 概念:借助于C/S(客户端/服务器)技术,将多个计算机联合起来作为攻击平台,对一个或多个目标发动DDOS攻击,从而成倍地提高拒绝服务攻击的威力。防护方…...
使用 ESP32 实现无线对讲机功能涉及音频采集、音频传输以及音频播放等多个方面。实现无线对讲机功能的基本步骤和示例代码。
硬件准备 两个 ESP32 开发板两个 MAX9814 麦克风模块(或其他兼容的模拟麦克风模块)两个 MAX98357A DAC 模块(或其他兼容的音频放大器模块)扬声器 接线 麦克风模块 -> ESP32 ADC 引脚ESP32 DAC 引脚 -> 音频放大器模块 -&…...
SpringBoot项目,配置文件pom.xml的结构解析
pom.xml 是 Maven 项目对象模型(Project Object Model)的配置文件,它定义了 Maven 项目的基本设置和构建过程。以下是 pom.xml 文件的基本结构和一些常见元素的解析: 项目声明 (<project>): <modelVersion>: 通常设置…...
教程:Spring Boot中集成Memcached的详细步骤
教程:Spring Boot中集成Memcached的详细步骤 大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿! 在现代应用开发中,缓存是提升性能和扩展性…...

Websocket通信实战项目(图片互传应用)+PyQt界面+python异步编程(async) (上)服务器端python实现
Rqtz : 个人主页 共享IT之美,共创机器未来 Sharing the Beauty of IT and Creating the Future of Machines Together 目录 项目背景 编辑专有名词介绍 服务器GUI展示 功能(位置见上图序号) 客户端GUI展示(h5cssjs…...

实验一 MATLAB \ Python数字图像处理初步
一、实验目的: 1.熟悉及掌握在MATLAB\Python中能够处理哪些格式图像。 2.熟练掌握在MATLAB\Python中如何读取图像。 3.掌握如何利用MATLAB\Python来获取图像的大小、颜色、高度、宽度等等相关信息。 4.掌握如何在M…...

echarts柱状选中shadow阴影背景宽度设置
使用line,宽度增大到所需要的宽度,设置下颜色透明度就行 tooltip: {trigger: axis,//把阴影的层级往下降z:-15,axisPointer: {type: line,lineStyle: {color: rgba(150,150,150,0.3),width: 44,type: solid,},}, }, series: [{type: bar,barWidth:20,//…...
ArrayBuffer 对象常见的几个用途
ArrayBuffer 在 JavaScript 中的用途广泛,主要用于处理二进制数据。 ArrayBuffer 对象、 TypedArray 视图和 DataView 视图是 JavaScript 操作二进制数据的一个接口。本文介绍ArrayBuffer 对象的常见的一些用法。 1. 网络传输二进制数据 使用方法:通过 …...

STC89C52RC单片机设计的FM收音机+自动搜台+存储电台(程序+原理图+PCB)
资料下载地址:STC89C52RC单片机设计的FM收音机自动搜台存储电台(程序原理图PCB) 1、实物图 2、部分程序 #include <reg52.h> #include "tea5767.h" #include "delay.h" #include "lcd1602.h" //K1:上一台 K2:下一…...
【若依】关闭当前标签页并跳转路由到其他页面
使用场景如:当在新增/编辑路由页面提交成功后,需要关闭当前页,并跳转回列表页。 实现代码: this.$store.dispatch("tagsView/delView", this.$route); //关闭当前页 this.$router.replace({ path: "/xxx/xxx"…...

防爆智能手机如何解决危险环境下通信难题?
在化工厂、石油行业、矿山等危险环境中,通信安全一直是难题。传统手机因不具备防爆功能,可能引发火花、爆炸等安全风险,让工作人员在关键时刻难以及时沟通。但如今,防爆智能手机的出现彻底改变了这一现状! 安全通信&am…...

软件测试最全面试题及答案整理(2024最新版)
1、你的测试职业发展是什么? 测试经验越多,测试能力越高。所以我的职业发展是需要时间积累的,一步步向着高级测试工程师奔去。而且我也有初步的职业规划,前3年积累测试经验,按如何做好测试工程师的要点去要求自己,不断…...

11 - matlab m_map地学绘图工具基础函数 - 绘制航迹、椭圆、风向玫瑰图和特定的圆形区域的有关函数及其用法
11 - matlab m_map地学绘图工具基础函数 - 绘制航迹、椭圆、风向玫瑰图和特定的圆形区域的有关函数及其用法 0. 引言1. 关于m_track2. 关于m_range_ring3. 关于m_ellipse4. 关于m_windrose5. 结语 0. 引言 本篇介绍下m_map中绘制航迹图函数(m_track)、绘…...
长安链安装及使用问题
1. 关于golang编译出错: Get “https://proxy.golang.org/chainmaker.org/chainmaker/common/v2/v/v2.2.0.mod“: dial 在网上查阅资料后发现是自己的golang版本太低(1.3一下),因为goalng在最初开发时,国内基本上都会遇到依赖下载不了的问题, 然而在1.3版本后,go…...

大学生竞赛管理系统-计算机毕业设计源码37276
大学生竞赛管理系统的设计与实现 摘 要 随着教育信息化的不断发展,大学生竞赛已成为高校教育的重要组成部分。传统的竞赛组织和管理方式存在着诸多问题,如信息不透明、效率低下、管理不便等。为了解决这些问题,提高竞赛组织和管理效率&#x…...

去中心化 RAG 先行者,KIP Protocol 如何保护数据所有权、激活 AI 资产
AI 时代,人人都应实现 KnowledgeFi 的梦想或许并不遥远,KIP Protocol 正在生动践行这一价值理念,带动去中心化数字产权的创建与盈利,面向 CryptoAI 的蓝海市场迈出创新探索的技术步伐,朝着 Web3 行业打造去中心化 AI 的…...
numpy库(python)
文章目录 1.numpy简介2.安装numpy3.ndarry : numpy库的心脏3.1 创建数组3.2数据类型3.3dtype NumPy是用Python.进行科学计算,尤其是数据分析时,所用到的一个基础库。它是大量Python 数学和科学计算包的基础,比如后面要讲到的pandas)库就用到了…...

AI技术在招聘行业的应用
大模型AI技术在招聘行业的应用正变得越来越广泛,以下是一些关键领域的应用实例。大模型AI技术在招聘行业的应用不仅提高了效率和精确度,还帮助企业在竞争激烈的人才市场中获得优势。随着技术的不断发展,预计AI将在招聘领域扮演更加重要的角色…...

代谢组数据分析(十二):岭回归、Lasso回归、弹性网络回归构建预测模型
欢迎大家关注全网生信学习者系列: WX公zhong号:生信学习者Xiao hong书:生信学习者知hu:生信学习者CDSN:生信学习者2介绍 在代谢物预测模型的构建中,我们采用了三种主流的回归分析方法:岭回归、Lasso回归以及弹性网络回归。这三种方法各有其独特的原理和适用场景,因此在…...
Vim 调用外部命令学习笔记
Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...

【OSG学习笔记】Day 18: 碰撞检测与物理交互
物理引擎(Physics Engine) 物理引擎 是一种通过计算机模拟物理规律(如力学、碰撞、重力、流体动力学等)的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互,广泛应用于 游戏开发、动画制作、虚…...

Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件
今天呢,博主的学习进度也是步入了Java Mybatis 框架,目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学,希望能对大家有所帮助,也特别欢迎大家指点不足之处,小生很乐意接受正确的建议&…...

【单片机期末】单片机系统设计
主要内容:系统状态机,系统时基,系统需求分析,系统构建,系统状态流图 一、题目要求 二、绘制系统状态流图 题目:根据上述描述绘制系统状态流图,注明状态转移条件及方向。 三、利用定时器产生时…...
【HTTP三个基础问题】
面试官您好!HTTP是超文本传输协议,是互联网上客户端和服务器之间传输超文本数据(比如文字、图片、音频、视频等)的核心协议,当前互联网应用最广泛的版本是HTTP1.1,它基于经典的C/S模型,也就是客…...
Device Mapper 机制
Device Mapper 机制详解 Device Mapper(简称 DM)是 Linux 内核中的一套通用块设备映射框架,为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程,并配以详细的…...

零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)
本期内容并不是很难,相信大家会学的很愉快,当然对于有后端基础的朋友来说,本期内容更加容易了解,当然没有基础的也别担心,本期内容会详细解释有关内容 本期用到的软件:yakit(因为经过之前好多期…...

深入浅出深度学习基础:从感知机到全连接神经网络的核心原理与应用
文章目录 前言一、感知机 (Perceptron)1.1 基础介绍1.1.1 感知机是什么?1.1.2 感知机的工作原理 1.2 感知机的简单应用:基本逻辑门1.2.1 逻辑与 (Logic AND)1.2.2 逻辑或 (Logic OR)1.2.3 逻辑与非 (Logic NAND) 1.3 感知机的实现1.3.1 简单实现 (基于阈…...

从 GreenPlum 到镜舟数据库:杭银消费金融湖仓一体转型实践
作者:吴岐诗,杭银消费金融大数据应用开发工程师 本文整理自杭银消费金融大数据应用开发工程师在StarRocks Summit Asia 2024的分享 引言:融合数据湖与数仓的创新之路 在数字金融时代,数据已成为金融机构的核心竞争力。杭银消费金…...

解析奥地利 XARION激光超声检测系统:无膜光学麦克风 + 无耦合剂的技术协同优势及多元应用
在工业制造领域,无损检测(NDT)的精度与效率直接影响产品质量与生产安全。奥地利 XARION开发的激光超声精密检测系统,以非接触式光学麦克风技术为核心,打破传统检测瓶颈,为半导体、航空航天、汽车制造等行业提供了高灵敏…...