untitled1.pro
# Qt项目配置
QT += core gui multimedia widgets
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = untitled1
TEMPLATE = app
# C++标准配置
CONFIG += c++17
# 源文件
SOURCES += \
main.cpp \
MainWindow.cpp
HEADERS += \
MainWindow.h
FORMS += \
MainWindow.ui
# OpenPose配置
OPENPOSE_ROOT = C:/openpose-prosperity
INCLUDEPATH += $$OPENPOSE_ROOT/include
LIBS += -L"C:/openpose-prosperity/build_CPU/src/openpose/Release"
LIBS += -L$$OPENPOSE_ROOT/lib -lopenpose
# OpenCV配置
OPENCV_ROOT = C:/opencv/build
INCLUDEPATH += $$OPENCV_ROOT/include
LIBS += -L$$OPENCV_ROOT/x64/vc15/lib \
-lopencv_core455 \
-lopencv_highgui455 \
-lopencv_imgproc455 \
-lopencv_imgcodecs455 \
-lopencv_videoio455
# Windows特定配置
win32 {
LIBS += -lws2_32 -lgdi32
QMAKE_CXXFLAGS += -permissive-
}
# 调试信息
CONFIG += debug_and_release
INCLUDEPATH += "C:\Program Files\Microsoft Visual Studio\18\Community\VC\Tools\MSVC\14.44.35207\include"
main.cpp
#include "MainWindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
MainWindow.cpp
#include "MainWindow.h"
#include "ui_MainWindow.h"
#include <QFileDialog>
#include <QMessageBox>
#include <opencv2/imgproc.hpp>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
, m_poseExtractor(nullptr)
, m_netWidth(368)
, m_netHeight(368)
{
ui->setupUi(this);
initializeOpenPose();
// 连接按钮信号
connect(ui->processButton, &QPushButton::clicked,
this, &MainWindow::on_processButton_clicked);
connect(ui->closeButton, &QPushButton::clicked,
this, &MainWindow::on_closeButton_clicked);
}
MainWindow::~MainWindow()
{
if (m_poseExtractor) delete m_poseExtractor;
delete ui;
}
// 初始化OpenPose(兼容旧版本)
void MainWindow::initializeOpenPose()
{
try {
const op::PoseModel poseModel = op::PoseModel::COCO_18;
const std::string modelFolder = "C:/openpose-prosperity/models/"; // 替换为你的模型路径
const int gpuId = -1; // CPU模式
const std::vector<op::HeatMapType> heatMapTypes;
const op::ScaleMode scaleMode = op::ScaleMode::InputResolution;
const bool maximizePositives = false;
const bool disableBlending = false;
const std::string modelProto = "";
const std::string modelWeights = "";
const float renderThreshold = 0.1f;
const bool enableGoogleLogging = false;
// 严格匹配构造函数参数
m_poseExtractor = new op::PoseExtractorCaffe(
poseModel, modelFolder, gpuId, heatMapTypes, scaleMode,
maximizePositives, disableBlending, modelProto, modelWeights,
renderThreshold, enableGoogleLogging
);
}
catch (const std::exception& e) {
QMessageBox::critical(this, "初始化失败",
QString("OpenPose错误:%1").arg(e.what()));
close();
}
}
// 处理图像按钮点击事件
void MainWindow::on_processButton_clicked()
{
const QString filePath = QFileDialog::getOpenFileName(
this, "选择图像", "", "图像文件 (*.jpg *.png *.bmp)"
);
if (filePath.isEmpty()) return;
cv::Mat frame = cv::imread(filePath.toStdString());
if (frame.empty()) {
QMessageBox::warning(this, "错误", "无法读取图像");
return;
}
const cv::Mat processedFrame = processFrame(frame);
displayImage(processedFrame);
}
// 关闭按钮点击事件
void MainWindow::on_closeButton_clicked()
{
close();
}
// 处理图像帧(核心功能)
cv::Mat MainWindow::processFrame(cv::Mat& frame)
{
try {
// 缩放图像至网络输入尺寸
cv::Mat resizedFrame;
cv::resize(frame, resizedFrame, cv::Size(m_netWidth, m_netHeight));
// 转换为OpenPose数组格式
op::Array<float> inputArray = matToOpArray(resizedFrame);
const std::vector<op::Array<float>> inputVector{inputArray};
// 执行姿态检测
m_poseExtractor->forwardPass(
inputVector,
op::Point<int>(frame.cols, frame.rows)
);
// 获取检测结果并绘制
const op::Array<float> keypoints = m_poseExtractor->getPoseKeypoints();
drawPose(frame, keypoints);
return frame;
}
catch (const std::exception& e) {
QMessageBox::warning(this, "处理错误",
QString("处理失败:%1").arg(e.what()));
return frame;
}
}
// 显示图像
void MainWindow::displayImage(const cv::Mat& image)
{
const QImage qImg = cvMatToQImage(image);
if (qImg.isNull()) {
ui->label->setText("无法显示图像");
return;
}
ui->label->setPixmap(QPixmap::fromImage(qImg).scaled(
ui->label->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation
));
}
// OpenCV图像转Qt图像
QImage MainWindow::cvMatToQImage(const cv::Mat& mat)
{
if (mat.empty() || mat.type() != CV_8UC3)
return QImage();
return QImage(mat.data, mat.cols, mat.rows, mat.step,
QImage::Format_BGR888).copy();
}
// 修正:不依赖setDimensions的图像转换函数
op::Array<float> MainWindow::matToOpArray(const cv::Mat& mat)
{
// 计算总元素数量(行×列×3通道)
const int totalElements = mat.rows * mat.cols * 3;
// 创建一维数组(旧版本兼容方式)
op::Array<float> array(totalElements);
// 获取可修改的原始数据指针
float* data = array.getPtr();
// 手动填充数据(BGR转RGB)
for (int y = 0; y < mat.rows; ++y) {
for (int x = 0; x < mat.cols; ++x) {
const cv::Vec3b& bgr = mat.at<cv::Vec3b>(y, x);
const int index = (y * mat.cols + x) * 3; // 计算一维索引
data[index] = static_cast<float>(bgr[2]); // R通道
data[index + 1] = static_cast<float>(bgr[1]); // G通道
data[index + 2] = static_cast<float>(bgr[0]); // B通道
}
}
// 移除setDimensions调用,完全适配旧版本
return array;
}
// 修正:获取const对象的指针
void MainWindow::drawPose(cv::Mat& frame, const op::Array<float>& keypoints)
{
// COCO模型骨骼连接关系
const std::vector<std::pair<int, int>> skeleton = {
{0,1}, {1,2}, {2,3}, {3,4}, // 右臂
{0,5}, {5,6}, {6,7}, {7,8}, // 左臂
{0,9}, {9,10}, {10,11}, {11,12}, // 右腿
{0,13}, {13,14}, {14,15}, {15,16}, // 左腿
{0,17} // 头部
};
const float threshold = 0.1f;
// 获取关键点数量信息(兼容旧版本)
const int numPersons = keypoints.getSize(0); // 检测到的人数
const int numParts = keypoints.getSize(1); // 每个对象的关键点数量
// 修正:使用const版本的getPtr方法
const float* data = keypoints.getConstPtr();
// 绘制骨骼
for (const auto& pair : skeleton) {
const int index1 = pair.first;
const int index2 = pair.second;
for (int person = 0; person < numPersons; ++person) {
// 计算一维索引
const int baseIdx1 = (person * numParts + index1) * 3;
const int baseIdx2 = (person * numParts + index2) * 3;
// 提取坐标和置信度
const float x1 = data[baseIdx1];
const float y1 = data[baseIdx1 + 1];
const float c1 = data[baseIdx1 + 2];
const float x2 = data[baseIdx2];
const float y2 = data[baseIdx2 + 1];
const float c2 = data[baseIdx2 + 2];
// 绘制骨骼(只绘制置信度高的)
if (c1 > threshold && c2 > threshold) {
cv::line(frame,
cv::Point(static_cast<int>(x1), static_cast<int>(y1)),
cv::Point(static_cast<int>(x2), static_cast<int>(y2)),
cv::Scalar(0, 255, 0), 2);
}
}
}
// 绘制关键点
for (int person = 0; person < numPersons; ++person) {
for (int part = 0; part < numParts; ++part) {
const int baseIdx = (person * numParts + part) * 3;
const float x = data[baseIdx];
const float y = data[baseIdx + 1];
const float c = data[baseIdx + 2];
if (c > threshold) {
cv::circle(frame,
cv::Point(static_cast<int>(x), static_cast<int>(y)),
5, cv::Scalar(0, 0, 255), -1);
}
}
}
}
MainWindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <opencv2/opencv.hpp>
#include "openpose/pose/poseExtractorCaffe.hpp"
#include "openpose/core/array.hpp"
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_processButton_clicked();
void on_closeButton_clicked();
private:
Ui::MainWindow *ui;
op::PoseExtractorCaffe* m_poseExtractor;
int m_netWidth; // 网络输入宽度
int m_netHeight; // 网络输入高度
// 工具函数
void initializeOpenPose();
cv::Mat processFrame(cv::Mat& frame);
void displayImage(const cv::Mat& image);
QImage cvMatToQImage(const cv::Mat& mat);
op::Array<float> matToOpArray(const cv::Mat& mat); // 图像转换
void drawPose(cv::Mat& frame, const op::Array<float>& keypoints); // 姿态绘制
};
#endif // MAINWINDOW_H
MainWindow.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1327</width>
<height>980</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget">
<widget class="QLabel" name="label">
<property name="geometry">
<rect>
<x>40</x>
<y>120</y>
<width>1280</width>
<height>720</height>
</rect>
</property>
<property name="text">
<string>Label</string>
</property>
<property name="alignment">
<set>Qt::AlignmentFlag::AlignCenter</set>
</property>
</widget>
<widget class="QPushButton" name="processButton">
<property name="geometry">
<rect>
<x>290</x>
<y>840</y>
<width>200</width>
<height>40</height>
</rect>
</property>
<property name="text">
<string>处理图像</string>
</property>
</widget>
<widget class="QPushButton" name="closeButton">
<property name="geometry">
<rect>
<x>840</x>
<y>840</y>
<width>200</width>
<height>40</height>
</rect>
</property>
<property name="text">
<string>关闭</string>
</property>
</widget>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1327</width>
<height>25</height>
</rect>
</property>
</widget>
<widget class="QStatusBar" name="statusbar"/>
</widget>
<resources/>
<connections/>
</ui>
这是qt6.10.0的工程代码,编译后出现以下问题:cl -c -nologo -Zc:wchar_t -FS -Zc:rvalueCast -Zc:inline -Zc:strictStrings -Zc:throwingNew -permissive- -Zc:__cplusplus -Zc:externConstexpr -permissive- -Zi -MDd -std:c++17 -utf-8 -W3 -w34100 -w34189 -w44456 -w44457 -w44458 -wd4577 -wd4467 -EHsc /Fddebug\untitled1.vc.pdb -DUNICODE -D_UNICODE -DWIN32 -D_ENABLE_EXTENDED_ALIGNED_STORAGE -DWIN64 -DQT_QML_DEBUG -DQT_MULTIMEDIA_LIB -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -I..\..\..\untitled1 -I. -IC:\openpose-prosperity\include -IC:\opencv\build\include -I"C:\Program Files\Microsoft Visual Studio\18\Community\VC\Tools\MSVC\14.44.35207\include" -IC:\Qt\6.10.0\msvc2022_64\include -IC:\Qt\6.10.0\msvc2022_64\include\QtMultimedia -IC:\Qt\6.10.0\msvc2022_64\include\QtWidgets -IC:\Qt\6.10.0\msvc2022_64\include\QtGui -IC:\Qt\6.10.0\msvc2022_64\include\QtNetwork -IC:\Qt\6.10.0\msvc2022_64\include\QtCore -Idebug -I. -I/include -IC:\Qt\6.10.0\msvc2022_64\mkspecs\win32-msvc -Fodebug\ @C:\Users\admin\AppData\Local\Temp\moc_MainWindow.obj.7132.594.jom
moc_MainWindow.cpp
link /NOLOGO /DYNAMICBASE /NXCOMPAT /DEBUG /SUBSYSTEM:WINDOWS "/MANIFESTDEPENDENCY:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' publicKeyToken='6595b64144ccf1df' language='*' processorArchitecture='*'" /MANIFEST:embed /OUT:debug\untitled1.exe @C:\Users\admin\AppData\Local\Temp\untitled1.exe.7132.5438.jom
LINK : fatal error LNK1104: 无法打开文件“opencv_core455.lib”
jom: C:\Users\admin\Desktop\QT\untitled1\build\Desktop_Qt_6_10_0_MSVC2022_64bit-Debug\Makefile.Debug [debug\untitled1.exe] Error 1104
jom: C:\Users\admin\Desktop\QT\untitled1\build\Desktop_Qt_6_10_0_MSVC2022_64bit-Debug\Makefile [debug] Error 2
02:15:06: The command "C:\Qt\Tools\QtCreator\bin\jom\jom.exe" terminated with exit code 2.
02:15:06: Error while building/deploying project untitled1 (kit: Desktop Qt 6.10.0 MSVC2022 64bit)
02:15:06: The kit Desktop Qt 6.10.0 MSVC2022 64bit has configuration issues which might be the root cause for this problem.
02:15:06: When executing step "Make"
02:15:06: Elapsed time: 00:06.
最新发布