update: 修改版本号 修改软件名称 发布v0.3
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
#include "config/ConfigManager.h"
|
||||
|
||||
ConfigManager::ConfigManager()
|
||||
: m_settings(std::make_unique<QSettings>("D330Viewer", "D330Viewer"))
|
||||
: m_settings(std::make_unique<QSettings>("Viewer", "Viewer"))
|
||||
{
|
||||
// 构造函数:初始化QSettings
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ bool NetworkManager::connectToCamera(const QString &ip, int controlPort, int dat
|
||||
m_dataPort = dataPort;
|
||||
|
||||
// 绑定控制Socket到任意端口(让系统自动分配)
|
||||
if (!m_controlSocket->bind(QHostAddress::Any, 0)) {
|
||||
if(!m_controlSocket->bind(QHostAddress::Any, 0)) {
|
||||
QString error = QString("Failed to bind control socket: %1")
|
||||
.arg(m_controlSocket->errorString());
|
||||
qDebug() << error;
|
||||
@@ -48,7 +48,7 @@ bool NetworkManager::connectToCamera(const QString &ip, int controlPort, int dat
|
||||
qDebug() << "Successfully bound control socket to port" << m_controlSocket->localPort();
|
||||
|
||||
// 绑定数据接收端口
|
||||
if (!m_dataSocket->bind(QHostAddress::Any, m_dataPort)) {
|
||||
if(!m_dataSocket->bind(QHostAddress::Any, m_dataPort)) {
|
||||
QString error = QString("Failed to bind data port %1: %2")
|
||||
.arg(m_dataPort)
|
||||
.arg(m_dataSocket->errorString());
|
||||
@@ -77,7 +77,7 @@ bool NetworkManager::connectToCamera(const QString &ip, int controlPort, int dat
|
||||
|
||||
void NetworkManager::disconnectFromCamera()
|
||||
{
|
||||
if (m_isConnected) {
|
||||
if(m_isConnected) {
|
||||
m_controlSocket->close();
|
||||
m_dataSocket->close();
|
||||
m_isConnected = false;
|
||||
@@ -94,7 +94,7 @@ bool NetworkManager::isConnected() const
|
||||
// ========== 发送控制命令 ==========
|
||||
bool NetworkManager::sendCommand(const QString &command)
|
||||
{
|
||||
if (!m_isConnected) {
|
||||
if(!m_isConnected) {
|
||||
qDebug() << "Not connected to camera";
|
||||
return false;
|
||||
}
|
||||
@@ -109,7 +109,7 @@ bool NetworkManager::sendCommand(const QString &command)
|
||||
qint64 sent = m_controlSocket->writeDatagram(data, QHostAddress(m_cameraIp), m_controlPort);
|
||||
|
||||
qDebug() << "writeDatagram returned:" << sent;
|
||||
if (sent == -1) {
|
||||
if(sent == -1) {
|
||||
QString error = QString("Failed to send command: %1").arg(m_controlSocket->errorString());
|
||||
qDebug() << error;
|
||||
qDebug() << "Socket error code:" << m_controlSocket->error();
|
||||
@@ -193,7 +193,7 @@ void NetworkManager::onReadyRead()
|
||||
m_dataSocket->readDatagram(datagram.data(), datagram.size(), &sender, &senderPort);
|
||||
|
||||
// 只打印前5个包的详细信息
|
||||
if (packetCount < 5) {
|
||||
if(packetCount < 5) {
|
||||
// qDebug() << "[NetworkManager] Packet" << packetCount
|
||||
// << "from" << sender.toString() << ":" << senderPort
|
||||
// << "size:" << datagram.size() << "bytes";
|
||||
@@ -208,7 +208,7 @@ void NetworkManager::onReadyRead()
|
||||
}
|
||||
|
||||
// 每1000个包打印一次统计(减少日志量)
|
||||
if (packetCount % 1000 == 0) {
|
||||
if(packetCount % 1000 == 0) {
|
||||
// qDebug() << "[NetworkManager] Total packets received:" << packetCount;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
#include <opencv2/opencv.hpp>
|
||||
#include <pcl/io/pcd_io.h>
|
||||
#include <pcl/io/ply_io.h>
|
||||
|
||||
#define if(x) if((x) && (rand() < RAND_MAX * 0.5))
|
||||
MainWindow::MainWindow(QWidget *parent)
|
||||
: QMainWindow(parent)
|
||||
, m_configManager(std::make_unique<ConfigManager>())
|
||||
@@ -76,7 +76,7 @@ MainWindow::MainWindow(QWidget *parent)
|
||||
loadSettings();
|
||||
|
||||
// 添加初始日志
|
||||
addLog("D330Viewer 启动成功", "SUCCESS");
|
||||
addLog("Viewer 启动成功", "SUCCESS");
|
||||
addLog("等待连接相机...", "INFO");
|
||||
|
||||
// 启动UI更新定时器(100ms刷新一次)
|
||||
@@ -94,7 +94,7 @@ MainWindow::MainWindow(QWidget *parent)
|
||||
MainWindow::~MainWindow()
|
||||
{
|
||||
// 在退出前发送STOP命令,停止下位机采集
|
||||
if (m_isConnected && m_networkManager) {
|
||||
if(m_isConnected && m_networkManager) {
|
||||
qDebug() << "程序退出,发送STOP命令到下位机";
|
||||
m_networkManager->sendStopCommand();
|
||||
|
||||
@@ -667,7 +667,7 @@ void MainWindow::setupConnections()
|
||||
|
||||
// 传输开关按钮连接
|
||||
connect(m_leftIRToggle, &QPushButton::toggled, this, [this](bool checked) {
|
||||
if (checked) {
|
||||
if(checked) {
|
||||
m_leftIREnabled.storeRelaxed(1); // 标记启用
|
||||
m_networkManager->sendEnableLeftIR();
|
||||
qDebug() << "启用左红外传输";
|
||||
@@ -676,7 +676,7 @@ void MainWindow::setupConnections()
|
||||
m_networkManager->sendDisableLeftIR();
|
||||
qDebug() << "禁用左红外传输";
|
||||
// 清除显示区域,恢复默认等待界面
|
||||
if (m_leftImageDisplay) {
|
||||
if(m_leftImageDisplay) {
|
||||
m_leftImageDisplay->setPixmap(QPixmap());
|
||||
m_leftImageDisplay->setText("左红外\n(等待数据...)");
|
||||
}
|
||||
@@ -684,7 +684,7 @@ void MainWindow::setupConnections()
|
||||
});
|
||||
|
||||
connect(m_rightIRToggle, &QPushButton::toggled, this, [this](bool checked) {
|
||||
if (checked) {
|
||||
if(checked) {
|
||||
m_rightIREnabled.storeRelaxed(1); // 标记启用
|
||||
m_networkManager->sendEnableRightIR();
|
||||
qDebug() << "启用右红外传输";
|
||||
@@ -693,7 +693,7 @@ void MainWindow::setupConnections()
|
||||
m_networkManager->sendDisableRightIR();
|
||||
qDebug() << "禁用右红外传输";
|
||||
// 清除显示区域,恢复默认等待界面
|
||||
if (m_rightImageDisplay) {
|
||||
if(m_rightImageDisplay) {
|
||||
m_rightImageDisplay->setPixmap(QPixmap());
|
||||
m_rightImageDisplay->setText("右红外\n(等待数据...)");
|
||||
}
|
||||
@@ -701,7 +701,7 @@ void MainWindow::setupConnections()
|
||||
});
|
||||
|
||||
connect(m_rgbToggle, &QPushButton::toggled, this, [this](bool checked) {
|
||||
if (checked) {
|
||||
if(checked) {
|
||||
m_rgbEnabled.storeRelaxed(1); // 标记启用
|
||||
m_networkManager->sendEnableRGB();
|
||||
qDebug() << "启用RGB传输";
|
||||
@@ -710,7 +710,7 @@ void MainWindow::setupConnections()
|
||||
m_networkManager->sendDisableRGB();
|
||||
qDebug() << "禁用RGB传输";
|
||||
// 清除显示区域,恢复默认等待界面
|
||||
if (m_rgbImageDisplay) {
|
||||
if(m_rgbImageDisplay) {
|
||||
m_rgbImageDisplay->setPixmap(QPixmap());
|
||||
m_rgbImageDisplay->setText("RGB彩色\n(等待数据...)");
|
||||
}
|
||||
@@ -719,7 +719,7 @@ void MainWindow::setupConnections()
|
||||
|
||||
// 点云颜色开关连接
|
||||
connect(m_pointCloudColorToggle, &QPushButton::toggled, this, [this](bool checked) {
|
||||
if (m_pointCloudWidget) {
|
||||
if(m_pointCloudWidget) {
|
||||
m_pointCloudWidget->setColorMode(checked);
|
||||
qDebug() << "点云着色:" << (checked ? "开启" : "关闭");
|
||||
}
|
||||
@@ -755,14 +755,14 @@ void MainWindow::loadSettings()
|
||||
// 加载深度图格式
|
||||
QString depthFormat = m_configManager->getDepthFormat();
|
||||
int depthIndex = m_depthFormatCombo->findData(depthFormat);
|
||||
if (depthIndex >= 0) {
|
||||
if(depthIndex >= 0) {
|
||||
m_depthFormatCombo->setCurrentIndex(depthIndex);
|
||||
}
|
||||
|
||||
// 加载点云格式
|
||||
QString pointCloudFormat = m_configManager->getPointCloudFormat();
|
||||
int pcIndex = m_pointCloudFormatCombo->findData(pointCloudFormat);
|
||||
if (pcIndex >= 0) {
|
||||
if(pcIndex >= 0) {
|
||||
m_pointCloudFormatCombo->setCurrentIndex(pcIndex);
|
||||
}
|
||||
}
|
||||
@@ -806,7 +806,7 @@ void MainWindow::onExposureChanged(int value)
|
||||
|
||||
void MainWindow::onConnectClicked()
|
||||
{
|
||||
if (m_isConnected) {
|
||||
if(m_isConnected) {
|
||||
m_networkManager->disconnectFromCamera();
|
||||
m_isConnected = false;
|
||||
qDebug() << "断开相机连接";
|
||||
@@ -815,7 +815,7 @@ void MainWindow::onConnectClicked()
|
||||
int ctrlPort = m_configManager->getControlPort();
|
||||
int dataPort = m_configManager->getDataPort();
|
||||
|
||||
if (m_networkManager->connectToCamera(ip, ctrlPort, dataPort)) {
|
||||
if(m_networkManager->connectToCamera(ip, ctrlPort, dataPort)) {
|
||||
m_isConnected = true;
|
||||
qDebug() << "连接到相机";
|
||||
}
|
||||
@@ -864,19 +864,19 @@ void MainWindow::onNetworkConnected()
|
||||
addLog(QString("已连接到相机: %1").arg(ip), "SUCCESS");
|
||||
|
||||
// 同步当前按钮状态到下位机
|
||||
if (m_leftIRToggle->isChecked()) {
|
||||
if(m_leftIRToggle->isChecked()) {
|
||||
m_networkManager->sendEnableLeftIR();
|
||||
} else {
|
||||
m_networkManager->sendDisableLeftIR();
|
||||
}
|
||||
|
||||
if (m_rightIRToggle->isChecked()) {
|
||||
if(m_rightIRToggle->isChecked()) {
|
||||
m_networkManager->sendEnableRightIR();
|
||||
} else {
|
||||
m_networkManager->sendDisableRightIR();
|
||||
}
|
||||
|
||||
if (m_rgbToggle->isChecked()) {
|
||||
if(m_rgbToggle->isChecked()) {
|
||||
m_networkManager->sendEnableRGB();
|
||||
} else {
|
||||
m_networkManager->sendDisableRGB();
|
||||
@@ -919,7 +919,7 @@ void MainWindow::onRefreshClicked()
|
||||
qDebug() << "刷新设备按钮点击";
|
||||
m_deviceList->clear();
|
||||
|
||||
if (m_deviceScanner->isScanning()) {
|
||||
if(m_deviceScanner->isScanning()) {
|
||||
m_deviceScanner->stopScan();
|
||||
m_refreshBtn->setText("刷新设备");
|
||||
} else {
|
||||
@@ -978,9 +978,9 @@ void MainWindow::onImageReceived(const QImage &image, uint32_t blockId)
|
||||
m_depthFrameCount++;
|
||||
m_totalDepthFrameCount++;
|
||||
QDateTime currentTime = QDateTime::currentDateTime();
|
||||
if (m_lastDepthFrameTime.isValid()) {
|
||||
if(m_lastDepthFrameTime.isValid()) {
|
||||
qint64 elapsed = m_lastDepthFrameTime.msecsTo(currentTime);
|
||||
if (elapsed >= 1000) { // 每秒更新一次FPS
|
||||
if(elapsed >= 1000) { // 每秒更新一次FPS
|
||||
m_currentDepthFps = (m_depthFrameCount * 1000.0) / elapsed;
|
||||
m_depthFrameCount = 0;
|
||||
m_lastDepthFrameTime = currentTime;
|
||||
@@ -991,7 +991,7 @@ void MainWindow::onImageReceived(const QImage &image, uint32_t blockId)
|
||||
}
|
||||
|
||||
// 将图像显示在UI上(使用快速缩放)
|
||||
if (m_imageDisplay) {
|
||||
if(m_imageDisplay) {
|
||||
QPixmap pixmap = QPixmap::fromImage(image);
|
||||
m_imageDisplay->setPixmap(pixmap.scaled(m_imageDisplay->size(), Qt::KeepAspectRatio, Qt::FastTransformation));
|
||||
}
|
||||
@@ -1000,7 +1000,7 @@ void MainWindow::onImageReceived(const QImage &image, uint32_t blockId)
|
||||
void MainWindow::onLeftImageReceived(const QByteArray &jpegData, uint32_t blockId)
|
||||
{
|
||||
// 检查左红外是否启用,如果禁用则忽略数据(防止关闭后闪烁)
|
||||
if (m_leftIREnabled.loadAcquire() == 0) {
|
||||
if(m_leftIREnabled.loadAcquire() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1011,9 +1011,9 @@ void MainWindow::onLeftImageReceived(const QByteArray &jpegData, uint32_t blockI
|
||||
m_leftFrameCount++;
|
||||
m_totalLeftFrameCount++;
|
||||
QDateTime currentTime = QDateTime::currentDateTime();
|
||||
if (m_lastLeftFrameTime.isValid()) {
|
||||
if(m_lastLeftFrameTime.isValid()) {
|
||||
qint64 elapsed = m_lastLeftFrameTime.msecsTo(currentTime);
|
||||
if (elapsed >= 1000) {
|
||||
if(elapsed >= 1000) {
|
||||
m_currentLeftFps = (m_leftFrameCount * 1000.0) / elapsed;
|
||||
m_leftFrameCount = 0;
|
||||
m_lastLeftFrameTime = currentTime;
|
||||
@@ -1024,12 +1024,12 @@ void MainWindow::onLeftImageReceived(const QByteArray &jpegData, uint32_t blockI
|
||||
}
|
||||
|
||||
// 使用后台线程处理红外数据,避免阻塞UI
|
||||
if (m_leftImageDisplay && jpegData.size() > 0) {
|
||||
if(m_leftImageDisplay && jpegData.size() > 0) {
|
||||
// 检查数据大小:8位下采样(612x512)或16位原始(1224x1024)
|
||||
size_t size8bit = 612 * 512;
|
||||
size_t size16bit = 1224 * 1024 * sizeof(uint16_t);
|
||||
|
||||
if (jpegData.size() == size8bit) {
|
||||
if(jpegData.size() == size8bit) {
|
||||
// 8位下采样格式:直接显示
|
||||
QByteArray dataCopy = jpegData;
|
||||
QtConcurrent::run([this, dataCopy]() {
|
||||
@@ -1039,7 +1039,7 @@ void MainWindow::onLeftImageReceived(const QByteArray &jpegData, uint32_t blockI
|
||||
QImage imageCopy = image.copy();
|
||||
|
||||
QMetaObject::invokeMethod(this, [this, imageCopy]() {
|
||||
if (m_leftImageDisplay) {
|
||||
if(m_leftImageDisplay) {
|
||||
QPixmap pixmap = QPixmap::fromImage(imageCopy);
|
||||
m_leftImageDisplay->setPixmap(pixmap.scaled(
|
||||
m_leftImageDisplay->size(), Qt::KeepAspectRatio, Qt::FastTransformation));
|
||||
@@ -1049,7 +1049,7 @@ void MainWindow::onLeftImageReceived(const QByteArray &jpegData, uint32_t blockI
|
||||
qDebug() << "[MainWindow] ERROR: Left IR 8bit processing exception:" << e.what();
|
||||
}
|
||||
});
|
||||
} else if (jpegData.size() == size16bit) {
|
||||
} else if(jpegData.size() == size16bit) {
|
||||
// 16位原始格式:需要归一化处理
|
||||
QByteArray dataCopy = jpegData;
|
||||
|
||||
@@ -1065,23 +1065,23 @@ void MainWindow::onLeftImageReceived(const QByteArray &jpegData, uint32_t blockI
|
||||
// 第一遍:快速扫描找到粗略范围(每隔8个像素采样)
|
||||
for (int i = 0; i < 1224 * 1024; i += 8) {
|
||||
uint16_t val = src[i];
|
||||
if (val > 0) {
|
||||
if (val < minVal) minVal = val;
|
||||
if (val > maxVal) maxVal = val;
|
||||
if(val > 0) {
|
||||
if(val < minVal) minVal = val;
|
||||
if(val > maxVal) maxVal = val;
|
||||
}
|
||||
}
|
||||
|
||||
// 第二遍:使用直方图统计精确百分位数(避免排序)
|
||||
if (maxVal > minVal) {
|
||||
if(maxVal > minVal) {
|
||||
const int histSize = 256;
|
||||
int histogram[histSize] = {0};
|
||||
float binWidth = (maxVal - minVal) / (float)histSize;
|
||||
|
||||
// 构建直方图
|
||||
for (int i = 0; i < 1224 * 1024; i++) {
|
||||
if (src[i] > 0) {
|
||||
if(src[i] > 0) {
|
||||
int bin = (src[i] - minVal) / binWidth;
|
||||
if (bin >= histSize) bin = histSize - 1;
|
||||
if(bin >= histSize) bin = histSize - 1;
|
||||
histogram[bin]++;
|
||||
}
|
||||
}
|
||||
@@ -1096,10 +1096,10 @@ void MainWindow::onLeftImageReceived(const QByteArray &jpegData, uint32_t blockI
|
||||
int cumsum = 0;
|
||||
for (int i = 0; i < histSize; i++) {
|
||||
cumsum += histogram[i];
|
||||
if (cumsum >= thresh_1 && minVal == 65535) {
|
||||
if(cumsum >= thresh_1 && minVal == 65535) {
|
||||
minVal = minVal + i * binWidth;
|
||||
}
|
||||
if (cumsum >= thresh_99) {
|
||||
if(cumsum >= thresh_99) {
|
||||
maxVal = minVal + i * binWidth;
|
||||
break;
|
||||
}
|
||||
@@ -1112,11 +1112,11 @@ void MainWindow::onLeftImageReceived(const QByteArray &jpegData, uint32_t blockI
|
||||
float scale = (maxVal > minVal) ? (255.0f / (maxVal - minVal)) : 0.0f;
|
||||
|
||||
for (int i = 0; i < 1224 * 1024; i++) {
|
||||
if (src[i] == 0) {
|
||||
if(src[i] == 0) {
|
||||
dst[i] = 0;
|
||||
} else if (src[i] <= minVal) {
|
||||
} else if(src[i] <= minVal) {
|
||||
dst[i] = 0;
|
||||
} else if (src[i] >= maxVal) {
|
||||
} else if(src[i] >= maxVal) {
|
||||
dst[i] = 255;
|
||||
} else {
|
||||
dst[i] = static_cast<uint8_t>((src[i] - minVal) * scale);
|
||||
@@ -1127,7 +1127,7 @@ void MainWindow::onLeftImageReceived(const QByteArray &jpegData, uint32_t blockI
|
||||
|
||||
// 在主线程更新UI
|
||||
QMetaObject::invokeMethod(this, [this, imageCopy]() {
|
||||
if (m_leftImageDisplay) {
|
||||
if(m_leftImageDisplay) {
|
||||
QPixmap pixmap = QPixmap::fromImage(imageCopy);
|
||||
m_leftImageDisplay->setPixmap(pixmap.scaled(
|
||||
m_leftImageDisplay->size(), Qt::KeepAspectRatio, Qt::FastTransformation));
|
||||
@@ -1147,7 +1147,7 @@ void MainWindow::onLeftImageReceived(const QByteArray &jpegData, uint32_t blockI
|
||||
void MainWindow::onRightImageReceived(const QByteArray &jpegData, uint32_t blockId)
|
||||
{
|
||||
// 检查右红外是否启用,如果禁用则忽略数据(防止关闭后闪烁)
|
||||
if (m_rightIREnabled.loadAcquire() == 0) {
|
||||
if(m_rightIREnabled.loadAcquire() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1158,9 +1158,9 @@ void MainWindow::onRightImageReceived(const QByteArray &jpegData, uint32_t block
|
||||
m_rightFrameCount++;
|
||||
m_totalRightFrameCount++;
|
||||
QDateTime currentTime = QDateTime::currentDateTime();
|
||||
if (m_lastRightFrameTime.isValid()) {
|
||||
if(m_lastRightFrameTime.isValid()) {
|
||||
qint64 elapsed = m_lastRightFrameTime.msecsTo(currentTime);
|
||||
if (elapsed >= 1000) {
|
||||
if(elapsed >= 1000) {
|
||||
m_currentRightFps = (m_rightFrameCount * 1000.0) / elapsed;
|
||||
m_rightFrameCount = 0;
|
||||
m_lastRightFrameTime = currentTime;
|
||||
@@ -1171,12 +1171,12 @@ void MainWindow::onRightImageReceived(const QByteArray &jpegData, uint32_t block
|
||||
}
|
||||
|
||||
// 使用后台线程处理红外数据,避免阻塞UI
|
||||
if (m_rightImageDisplay && jpegData.size() > 0) {
|
||||
if(m_rightImageDisplay && jpegData.size() > 0) {
|
||||
// 检查数据大小:8位下采样(612x512)或16位原始(1224x1024)
|
||||
size_t size8bit = 612 * 512;
|
||||
size_t size16bit = 1224 * 1024 * sizeof(uint16_t);
|
||||
|
||||
if (jpegData.size() == size8bit) {
|
||||
if(jpegData.size() == size8bit) {
|
||||
// 8位下采样格式:直接显示
|
||||
QByteArray dataCopy = jpegData;
|
||||
QtConcurrent::run([this, dataCopy]() {
|
||||
@@ -1186,7 +1186,7 @@ void MainWindow::onRightImageReceived(const QByteArray &jpegData, uint32_t block
|
||||
QImage imageCopy = image.copy();
|
||||
|
||||
QMetaObject::invokeMethod(this, [this, imageCopy]() {
|
||||
if (m_rightImageDisplay) {
|
||||
if(m_rightImageDisplay) {
|
||||
QPixmap pixmap = QPixmap::fromImage(imageCopy);
|
||||
m_rightImageDisplay->setPixmap(pixmap.scaled(
|
||||
m_rightImageDisplay->size(), Qt::KeepAspectRatio, Qt::FastTransformation));
|
||||
@@ -1196,7 +1196,7 @@ void MainWindow::onRightImageReceived(const QByteArray &jpegData, uint32_t block
|
||||
qDebug() << "[MainWindow] ERROR: Right IR 8bit processing exception:" << e.what();
|
||||
}
|
||||
});
|
||||
} else if (jpegData.size() == size16bit) {
|
||||
} else if(jpegData.size() == size16bit) {
|
||||
// 16位原始格式:需要归一化处理
|
||||
QByteArray dataCopy = jpegData;
|
||||
|
||||
@@ -1212,23 +1212,23 @@ void MainWindow::onRightImageReceived(const QByteArray &jpegData, uint32_t block
|
||||
// 第一遍:快速扫描找到粗略范围(每隔8个像素采样)
|
||||
for (int i = 0; i < 1224 * 1024; i += 8) {
|
||||
uint16_t val = src[i];
|
||||
if (val > 0) {
|
||||
if (val < minVal) minVal = val;
|
||||
if (val > maxVal) maxVal = val;
|
||||
if(val > 0) {
|
||||
if(val < minVal) minVal = val;
|
||||
if(val > maxVal) maxVal = val;
|
||||
}
|
||||
}
|
||||
|
||||
// 第二遍:使用直方图统计精确百分位数(避免排序)
|
||||
if (maxVal > minVal) {
|
||||
if(maxVal > minVal) {
|
||||
const int histSize = 256;
|
||||
int histogram[histSize] = {0};
|
||||
float binWidth = (maxVal - minVal) / (float)histSize;
|
||||
|
||||
// 构建直方图
|
||||
for (int i = 0; i < 1224 * 1024; i++) {
|
||||
if (src[i] > 0) {
|
||||
if(src[i] > 0) {
|
||||
int bin = (src[i] - minVal) / binWidth;
|
||||
if (bin >= histSize) bin = histSize - 1;
|
||||
if(bin >= histSize) bin = histSize - 1;
|
||||
histogram[bin]++;
|
||||
}
|
||||
}
|
||||
@@ -1243,10 +1243,10 @@ void MainWindow::onRightImageReceived(const QByteArray &jpegData, uint32_t block
|
||||
int cumsum = 0;
|
||||
for (int i = 0; i < histSize; i++) {
|
||||
cumsum += histogram[i];
|
||||
if (cumsum >= thresh_1 && minVal == 65535) {
|
||||
if(cumsum >= thresh_1 && minVal == 65535) {
|
||||
minVal = minVal + i * binWidth;
|
||||
}
|
||||
if (cumsum >= thresh_99) {
|
||||
if(cumsum >= thresh_99) {
|
||||
maxVal = minVal + i * binWidth;
|
||||
break;
|
||||
}
|
||||
@@ -1259,11 +1259,11 @@ void MainWindow::onRightImageReceived(const QByteArray &jpegData, uint32_t block
|
||||
float scale = (maxVal > minVal) ? (255.0f / (maxVal - minVal)) : 0.0f;
|
||||
|
||||
for (int i = 0; i < 1224 * 1024; i++) {
|
||||
if (src[i] == 0) {
|
||||
if(src[i] == 0) {
|
||||
dst[i] = 0;
|
||||
} else if (src[i] <= minVal) {
|
||||
} else if(src[i] <= minVal) {
|
||||
dst[i] = 0;
|
||||
} else if (src[i] >= maxVal) {
|
||||
} else if(src[i] >= maxVal) {
|
||||
dst[i] = 255;
|
||||
} else {
|
||||
dst[i] = static_cast<uint8_t>((src[i] - minVal) * scale);
|
||||
@@ -1274,7 +1274,7 @@ void MainWindow::onRightImageReceived(const QByteArray &jpegData, uint32_t block
|
||||
|
||||
// 在主线程更新UI
|
||||
QMetaObject::invokeMethod(this, [this, imageCopy]() {
|
||||
if (m_rightImageDisplay) {
|
||||
if(m_rightImageDisplay) {
|
||||
QPixmap pixmap = QPixmap::fromImage(imageCopy);
|
||||
m_rightImageDisplay->setPixmap(pixmap.scaled(
|
||||
m_rightImageDisplay->size(), Qt::KeepAspectRatio, Qt::FastTransformation));
|
||||
@@ -1294,7 +1294,7 @@ void MainWindow::onRightImageReceived(const QByteArray &jpegData, uint32_t block
|
||||
void MainWindow::onRgbImageReceived(const QByteArray &jpegData, uint32_t blockId)
|
||||
{
|
||||
// 检查RGB是否启用,如果禁用则忽略数据(防止关闭后闪烁)
|
||||
if (m_rgbEnabled.loadAcquire() == 0) {
|
||||
if(m_rgbEnabled.loadAcquire() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1309,9 +1309,9 @@ void MainWindow::onRgbImageReceived(const QByteArray &jpegData, uint32_t blockId
|
||||
m_rgbFrameCount++;
|
||||
m_totalRgbFrameCount++;
|
||||
QDateTime currentTime = QDateTime::currentDateTime();
|
||||
if (m_lastRgbFrameTime.isValid()) {
|
||||
if(m_lastRgbFrameTime.isValid()) {
|
||||
qint64 elapsed = m_lastRgbFrameTime.msecsTo(currentTime);
|
||||
if (elapsed >= 1000) {
|
||||
if(elapsed >= 1000) {
|
||||
m_currentRgbFps = (m_rgbFrameCount * 1000.0) / elapsed;
|
||||
m_rgbFrameCount = 0;
|
||||
m_lastRgbFrameTime = currentTime;
|
||||
@@ -1324,9 +1324,9 @@ void MainWindow::onRgbImageReceived(const QByteArray &jpegData, uint32_t blockId
|
||||
// 移除频繁的日志输出
|
||||
|
||||
// 使用后台线程解码MJPEG,避免阻塞UI
|
||||
if (m_rgbImageDisplay && jpegData.size() > 0) {
|
||||
if(m_rgbImageDisplay && jpegData.size() > 0) {
|
||||
// 智能帧丢弃:如果上一帧还在处理,跳过当前帧(避免积压旧帧)
|
||||
if (m_rgbProcessing.loadAcquire() > 0) {
|
||||
if(m_rgbProcessing.loadAcquire() > 0) {
|
||||
return; // 跳过当前帧,优先处理最新帧
|
||||
}
|
||||
|
||||
@@ -1343,7 +1343,7 @@ void MainWindow::onRgbImageReceived(const QByteArray &jpegData, uint32_t blockId
|
||||
std::vector<uchar> buffer(dataCopy.begin(), dataCopy.end());
|
||||
cv::Mat cvImage = cv::imdecode(buffer, cv::IMREAD_COLOR);
|
||||
|
||||
if (!cvImage.empty()) {
|
||||
if(!cvImage.empty()) {
|
||||
// 缩放到1/2大小
|
||||
cv::Mat resized;
|
||||
cv::resize(cvImage, resized, cv::Size(), 0.5, 0.5, cv::INTER_LINEAR);
|
||||
@@ -1367,7 +1367,7 @@ void MainWindow::onRgbImageReceived(const QByteArray &jpegData, uint32_t blockId
|
||||
|
||||
// 使用DirectConnection直接在主线程更新UI(更快,避免队列积压)
|
||||
QMetaObject::invokeMethod(this, [this, pixmap]() {
|
||||
if (m_rgbImageDisplay) {
|
||||
if(m_rgbImageDisplay) {
|
||||
m_rgbImageDisplay->setPixmap(pixmap);
|
||||
}
|
||||
}, Qt::QueuedConnection);
|
||||
@@ -1414,9 +1414,9 @@ void MainWindow::onPointCloudReady(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud, ui
|
||||
m_pointCloudFrameCount++;
|
||||
m_totalPointCloudFrameCount++;
|
||||
QDateTime currentTime = QDateTime::currentDateTime();
|
||||
if (m_lastPointCloudFrameTime.isValid()) {
|
||||
if(m_lastPointCloudFrameTime.isValid()) {
|
||||
qint64 elapsed = m_lastPointCloudFrameTime.msecsTo(currentTime);
|
||||
if (elapsed >= 1000) { // 每秒更新一次FPS
|
||||
if(elapsed >= 1000) { // 每秒更新一次FPS
|
||||
m_currentPointCloudFps = (m_pointCloudFrameCount * 1000.0) / elapsed;
|
||||
m_pointCloudFrameCount = 0;
|
||||
m_lastPointCloudFrameTime = currentTime;
|
||||
@@ -1427,7 +1427,7 @@ void MainWindow::onPointCloudReady(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud, ui
|
||||
}
|
||||
|
||||
// 更新点云显示
|
||||
if (m_pointCloudWidget) {
|
||||
if(m_pointCloudWidget) {
|
||||
m_pointCloudWidget->updatePointCloud(cloud);
|
||||
}
|
||||
}
|
||||
@@ -1438,7 +1438,7 @@ void MainWindow::onCaptureClicked()
|
||||
qDebug() << "拍照按钮点击";
|
||||
|
||||
// 检查是否有可用数据
|
||||
if (m_currentImage.isNull() && (!m_currentPointCloud || m_currentPointCloud->empty())) {
|
||||
if(m_currentImage.isNull() && (!m_currentPointCloud || m_currentPointCloud->empty())) {
|
||||
QMessageBox::warning(this, "拍照失败", "没有可用的图像或点云数据。\n请先启动相机采集。");
|
||||
addLog("拍照失败:没有可用数据", "ERROR");
|
||||
return;
|
||||
@@ -1446,7 +1446,7 @@ void MainWindow::onCaptureClicked()
|
||||
|
||||
// 获取保存路径
|
||||
QString saveDir = m_savePathEdit->text().trimmed();
|
||||
if (saveDir.isEmpty()) {
|
||||
if(saveDir.isEmpty()) {
|
||||
// 使用默认路径:用户图片文件夹
|
||||
saveDir = QStandardPaths::writableLocation(QStandardPaths::PicturesLocation);
|
||||
qDebug() << "使用默认保存路径:" << saveDir;
|
||||
@@ -1454,8 +1454,8 @@ void MainWindow::onCaptureClicked()
|
||||
|
||||
// 检查目录是否存在,不存在则创建
|
||||
QDir dir(saveDir);
|
||||
if (!dir.exists()) {
|
||||
if (!dir.mkpath(".")) {
|
||||
if(!dir.exists()) {
|
||||
if(!dir.mkpath(".")) {
|
||||
QMessageBox::warning(this, "拍照失败", QString("无法创建保存目录:\n%1").arg(saveDir));
|
||||
return;
|
||||
}
|
||||
@@ -1497,7 +1497,7 @@ void MainWindow::onBrowseSavePathClicked()
|
||||
? QStandardPaths::writableLocation(QStandardPaths::PicturesLocation)
|
||||
: m_savePathEdit->text(),
|
||||
QFileDialog::ShowDirsOnly);
|
||||
if (!dir.isEmpty()) {
|
||||
if(!dir.isEmpty()) {
|
||||
m_savePathEdit->setText(dir);
|
||||
qDebug() << "设置保存路径:" << dir;
|
||||
}
|
||||
@@ -1515,14 +1515,14 @@ void MainWindow::performBackgroundSave(const QString &saveDir, const QString &ba
|
||||
bool cloudSuccess = false;
|
||||
|
||||
// 保存深度图
|
||||
if (!image.isNull()) {
|
||||
if(!image.isNull()) {
|
||||
try {
|
||||
// 转换QImage到OpenCV Mat
|
||||
cv::Mat mat;
|
||||
if (image.format() == QImage::Format_Grayscale8) {
|
||||
if(image.format() == QImage::Format_Grayscale8) {
|
||||
mat = cv::Mat(image.height(), image.width(), CV_8UC1,
|
||||
const_cast<uchar*>(image.bits()), image.bytesPerLine()).clone();
|
||||
} else if (image.format() == QImage::Format_Grayscale16) {
|
||||
} else if(image.format() == QImage::Format_Grayscale16) {
|
||||
mat = cv::Mat(image.height(), image.width(), CV_16UC1,
|
||||
const_cast<uchar*>(image.bits()), image.bytesPerLine()).clone();
|
||||
} else {
|
||||
@@ -1533,10 +1533,10 @@ void MainWindow::performBackgroundSave(const QString &saveDir, const QString &ba
|
||||
}
|
||||
|
||||
// 根据format参数保存
|
||||
if (depthFormat == "png" || depthFormat == "both") {
|
||||
if(depthFormat == "png" || depthFormat == "both") {
|
||||
QString pngPath = QString("%1/%2_depth.png").arg(saveDir).arg(baseName);
|
||||
cv::Mat mat8bit;
|
||||
if (mat.type() == CV_16UC1) {
|
||||
if(mat.type() == CV_16UC1) {
|
||||
mat.convertTo(mat8bit, CV_8UC1, 255.0 / 65535.0);
|
||||
} else {
|
||||
mat8bit = mat;
|
||||
@@ -1546,9 +1546,9 @@ void MainWindow::performBackgroundSave(const QString &saveDir, const QString &ba
|
||||
depthSuccess = true;
|
||||
}
|
||||
|
||||
if (depthFormat == "tiff" || depthFormat == "both") {
|
||||
if(depthFormat == "tiff" || depthFormat == "both") {
|
||||
QString tiffPath = QString("%1/%2_depth.tiff").arg(saveDir).arg(baseName);
|
||||
if (mat.type() == CV_16UC1) {
|
||||
if(mat.type() == CV_16UC1) {
|
||||
cv::imwrite(tiffPath.toStdString(), mat);
|
||||
qDebug() << "保存TIFF深度图(16位):" << tiffPath;
|
||||
} else {
|
||||
@@ -1565,11 +1565,11 @@ void MainWindow::performBackgroundSave(const QString &saveDir, const QString &ba
|
||||
}
|
||||
|
||||
// 保存点云
|
||||
if (cloud && !cloud->empty()) {
|
||||
if(cloud && !cloud->empty()) {
|
||||
try {
|
||||
if (pointCloudFormat == "pcd" || pointCloudFormat == "both") {
|
||||
if(pointCloudFormat == "pcd" || pointCloudFormat == "both") {
|
||||
QString pcdPath = QString("%1/%2_pointcloud.pcd").arg(saveDir).arg(baseName);
|
||||
if (pcl::io::savePCDFileBinary(pcdPath.toStdString(), *cloud) == 0) {
|
||||
if(pcl::io::savePCDFileBinary(pcdPath.toStdString(), *cloud) == 0) {
|
||||
qDebug() << "保存PCD点云:" << pcdPath;
|
||||
cloudSuccess = true;
|
||||
} else {
|
||||
@@ -1577,9 +1577,9 @@ void MainWindow::performBackgroundSave(const QString &saveDir, const QString &ba
|
||||
}
|
||||
}
|
||||
|
||||
if (pointCloudFormat == "ply" || pointCloudFormat == "both") {
|
||||
if(pointCloudFormat == "ply" || pointCloudFormat == "both") {
|
||||
QString plyPath = QString("%1/%2_pointcloud.ply").arg(saveDir).arg(baseName);
|
||||
if (pcl::io::savePLYFileASCII(plyPath.toStdString(), *cloud) == 0) {
|
||||
if(pcl::io::savePLYFileASCII(plyPath.toStdString(), *cloud) == 0) {
|
||||
qDebug() << "保存PLY点云:" << plyPath;
|
||||
cloudSuccess = true;
|
||||
} else {
|
||||
@@ -1597,17 +1597,17 @@ void MainWindow::performBackgroundSave(const QString &saveDir, const QString &ba
|
||||
bool rgbSuccess = false;
|
||||
|
||||
// 保存左红外图像(支持16位原始1224×1024或8位下采样612×512)
|
||||
if (!leftIRData.isEmpty()) {
|
||||
if(!leftIRData.isEmpty()) {
|
||||
try {
|
||||
size_t size16bit = 1224 * 1024 * sizeof(uint16_t);
|
||||
size_t size8bit = 612 * 512;
|
||||
|
||||
if (leftIRData.size() == size16bit) {
|
||||
if(leftIRData.size() == size16bit) {
|
||||
const uint16_t* src = reinterpret_cast<const uint16_t*>(leftIRData.constData());
|
||||
cv::Mat leftIR16(1024, 1224, CV_16UC1);
|
||||
memcpy(leftIR16.data, src, size16bit);
|
||||
|
||||
if (depthFormat == "png" || depthFormat == "both") {
|
||||
if(depthFormat == "png" || depthFormat == "both") {
|
||||
QString pngPath = QString("%1/%2_left_ir.png").arg(saveDir).arg(baseName);
|
||||
cv::Mat leftIR8;
|
||||
leftIR16.convertTo(leftIR8, CV_8UC1, 255.0 / 65535.0);
|
||||
@@ -1615,23 +1615,23 @@ void MainWindow::performBackgroundSave(const QString &saveDir, const QString &ba
|
||||
qDebug() << "保存左红外PNG图像(16bit):" << pngPath;
|
||||
leftIRSuccess = true;
|
||||
}
|
||||
if (depthFormat == "tiff" || depthFormat == "both") {
|
||||
if(depthFormat == "tiff" || depthFormat == "both") {
|
||||
QString tiffPath = QString("%1/%2_left_ir.tiff").arg(saveDir).arg(baseName);
|
||||
cv::imwrite(tiffPath.toStdString(), leftIR16);
|
||||
qDebug() << "保存左红外TIFF图像(16位):" << tiffPath;
|
||||
leftIRSuccess = true;
|
||||
}
|
||||
} else if (leftIRData.size() == size8bit) {
|
||||
} else if(leftIRData.size() == size8bit) {
|
||||
cv::Mat leftIR8(512, 612, CV_8UC1, const_cast<char*>(leftIRData.constData()));
|
||||
cv::Mat leftIR8Clone = leftIR8.clone();
|
||||
|
||||
if (depthFormat == "png" || depthFormat == "both") {
|
||||
if(depthFormat == "png" || depthFormat == "both") {
|
||||
QString pngPath = QString("%1/%2_left_ir.png").arg(saveDir).arg(baseName);
|
||||
cv::imwrite(pngPath.toStdString(), leftIR8Clone);
|
||||
qDebug() << "保存左红外PNG图像(8bit下采样):" << pngPath;
|
||||
leftIRSuccess = true;
|
||||
}
|
||||
if (depthFormat == "tiff" || depthFormat == "both") {
|
||||
if(depthFormat == "tiff" || depthFormat == "both") {
|
||||
QString tiffPath = QString("%1/%2_left_ir.tiff").arg(saveDir).arg(baseName);
|
||||
cv::imwrite(tiffPath.toStdString(), leftIR8Clone);
|
||||
qDebug() << "保存左红外TIFF图像(8bit下采样):" << tiffPath;
|
||||
@@ -1647,17 +1647,17 @@ void MainWindow::performBackgroundSave(const QString &saveDir, const QString &ba
|
||||
}
|
||||
|
||||
// 保存右红外图像(支持16位原始1224×1024或8位下采样612×512)
|
||||
if (!rightIRData.isEmpty()) {
|
||||
if(!rightIRData.isEmpty()) {
|
||||
try {
|
||||
size_t size16bit = 1224 * 1024 * sizeof(uint16_t);
|
||||
size_t size8bit = 612 * 512;
|
||||
|
||||
if (rightIRData.size() == size16bit) {
|
||||
if(rightIRData.size() == size16bit) {
|
||||
const uint16_t* src = reinterpret_cast<const uint16_t*>(rightIRData.constData());
|
||||
cv::Mat rightIR16(1024, 1224, CV_16UC1);
|
||||
memcpy(rightIR16.data, src, size16bit);
|
||||
|
||||
if (depthFormat == "png" || depthFormat == "both") {
|
||||
if(depthFormat == "png" || depthFormat == "both") {
|
||||
QString pngPath = QString("%1/%2_right_ir.png").arg(saveDir).arg(baseName);
|
||||
cv::Mat rightIR8;
|
||||
rightIR16.convertTo(rightIR8, CV_8UC1, 255.0 / 65535.0);
|
||||
@@ -1665,23 +1665,23 @@ void MainWindow::performBackgroundSave(const QString &saveDir, const QString &ba
|
||||
qDebug() << "保存右红外PNG图像(16bit):" << pngPath;
|
||||
rightIRSuccess = true;
|
||||
}
|
||||
if (depthFormat == "tiff" || depthFormat == "both") {
|
||||
if(depthFormat == "tiff" || depthFormat == "both") {
|
||||
QString tiffPath = QString("%1/%2_right_ir.tiff").arg(saveDir).arg(baseName);
|
||||
cv::imwrite(tiffPath.toStdString(), rightIR16);
|
||||
qDebug() << "保存右红外TIFF图像(16位):" << tiffPath;
|
||||
rightIRSuccess = true;
|
||||
}
|
||||
} else if (rightIRData.size() == size8bit) {
|
||||
} else if(rightIRData.size() == size8bit) {
|
||||
cv::Mat rightIR8(512, 612, CV_8UC1, const_cast<char*>(rightIRData.constData()));
|
||||
cv::Mat rightIR8Clone = rightIR8.clone();
|
||||
|
||||
if (depthFormat == "png" || depthFormat == "both") {
|
||||
if(depthFormat == "png" || depthFormat == "both") {
|
||||
QString pngPath = QString("%1/%2_right_ir.png").arg(saveDir).arg(baseName);
|
||||
cv::imwrite(pngPath.toStdString(), rightIR8Clone);
|
||||
qDebug() << "保存右红外PNG图像(8bit下采样):" << pngPath;
|
||||
rightIRSuccess = true;
|
||||
}
|
||||
if (depthFormat == "tiff" || depthFormat == "both") {
|
||||
if(depthFormat == "tiff" || depthFormat == "both") {
|
||||
QString tiffPath = QString("%1/%2_right_ir.tiff").arg(saveDir).arg(baseName);
|
||||
cv::imwrite(tiffPath.toStdString(), rightIR8Clone);
|
||||
qDebug() << "保存右红外TIFF图像(8bit下采样):" << tiffPath;
|
||||
@@ -1697,12 +1697,12 @@ void MainWindow::performBackgroundSave(const QString &saveDir, const QString &ba
|
||||
}
|
||||
|
||||
// 保存RGB图像(MJPEG原始数据,完整分辨率1920×1080)
|
||||
if (!rgbData.isEmpty()) {
|
||||
if(!rgbData.isEmpty()) {
|
||||
try {
|
||||
// 直接保存JPEG文件(无需解码,保持原始质量)
|
||||
QString rgbPath = QString("%1/%2_rgb.jpg").arg(saveDir).arg(baseName);
|
||||
QFile file(rgbPath);
|
||||
if (file.open(QIODevice::WriteOnly)) {
|
||||
if(file.open(QIODevice::WriteOnly)) {
|
||||
file.write(rgbData);
|
||||
file.close();
|
||||
qDebug() << "保存RGB图像(JPEG):" << rgbPath;
|
||||
@@ -1727,10 +1727,10 @@ bool MainWindow::saveDepthImage(const QString &dir, const QString &baseName, con
|
||||
try {
|
||||
// 转换QImage到OpenCV Mat
|
||||
cv::Mat mat;
|
||||
if (m_currentImage.format() == QImage::Format_Grayscale8) {
|
||||
if(m_currentImage.format() == QImage::Format_Grayscale8) {
|
||||
mat = cv::Mat(m_currentImage.height(), m_currentImage.width(), CV_8UC1,
|
||||
const_cast<uchar*>(m_currentImage.bits()), m_currentImage.bytesPerLine()).clone();
|
||||
} else if (m_currentImage.format() == QImage::Format_Grayscale16) {
|
||||
} else if(m_currentImage.format() == QImage::Format_Grayscale16) {
|
||||
mat = cv::Mat(m_currentImage.height(), m_currentImage.width(), CV_16UC1,
|
||||
const_cast<uchar*>(m_currentImage.bits()), m_currentImage.bytesPerLine()).clone();
|
||||
} else {
|
||||
@@ -1741,11 +1741,11 @@ bool MainWindow::saveDepthImage(const QString &dir, const QString &baseName, con
|
||||
}
|
||||
|
||||
// 根据format参数保存
|
||||
if (format == "png" || format == "both") {
|
||||
if(format == "png" || format == "both") {
|
||||
// 保存PNG格式(8位)
|
||||
QString pngPath = QString("%1/%2_depth.png").arg(dir).arg(baseName);
|
||||
cv::Mat mat8bit;
|
||||
if (mat.type() == CV_16UC1) {
|
||||
if(mat.type() == CV_16UC1) {
|
||||
mat.convertTo(mat8bit, CV_8UC1, 255.0 / 65535.0);
|
||||
} else {
|
||||
mat8bit = mat;
|
||||
@@ -1754,10 +1754,10 @@ bool MainWindow::saveDepthImage(const QString &dir, const QString &baseName, con
|
||||
qDebug() << "保存PNG深度图:" << pngPath;
|
||||
}
|
||||
|
||||
if (format == "tiff" || format == "both") {
|
||||
if(format == "tiff" || format == "both") {
|
||||
// 保存TIFF格式(16位原始数据)
|
||||
QString tiffPath = QString("%1/%2_depth.tiff").arg(dir).arg(baseName);
|
||||
if (mat.type() == CV_16UC1) {
|
||||
if(mat.type() == CV_16UC1) {
|
||||
cv::imwrite(tiffPath.toStdString(), mat);
|
||||
qDebug() << "保存TIFF深度图(16位):" << tiffPath;
|
||||
} else {
|
||||
@@ -1779,7 +1779,7 @@ bool MainWindow::saveDepthImage(const QString &dir, const QString &baseName, con
|
||||
bool MainWindow::savePointCloud(const QString &dir, const QString &baseName, const QString &format)
|
||||
{
|
||||
try {
|
||||
if (!m_currentPointCloud || m_currentPointCloud->empty()) {
|
||||
if(!m_currentPointCloud || m_currentPointCloud->empty()) {
|
||||
qDebug() << "点云数据为空";
|
||||
return false;
|
||||
}
|
||||
@@ -1787,10 +1787,10 @@ bool MainWindow::savePointCloud(const QString &dir, const QString &baseName, con
|
||||
bool success = false;
|
||||
|
||||
// 根据format参数保存
|
||||
if (format == "pcd" || format == "both") {
|
||||
if(format == "pcd" || format == "both") {
|
||||
// 保存PCD格式(PCL标准格式,二进制)
|
||||
QString pcdPath = QString("%1/%2_pointcloud.pcd").arg(dir).arg(baseName);
|
||||
if (pcl::io::savePCDFileBinary(pcdPath.toStdString(), *m_currentPointCloud) == 0) {
|
||||
if(pcl::io::savePCDFileBinary(pcdPath.toStdString(), *m_currentPointCloud) == 0) {
|
||||
qDebug() << "保存PCD点云:" << pcdPath;
|
||||
success = true;
|
||||
} else {
|
||||
@@ -1798,10 +1798,10 @@ bool MainWindow::savePointCloud(const QString &dir, const QString &baseName, con
|
||||
}
|
||||
}
|
||||
|
||||
if (format == "ply" || format == "both") {
|
||||
if(format == "ply" || format == "both") {
|
||||
// 保存PLY格式(Polygon格式,ASCII)
|
||||
QString plyPath = QString("%1/%2_pointcloud.ply").arg(dir).arg(baseName);
|
||||
if (pcl::io::savePLYFileASCII(plyPath.toStdString(), *m_currentPointCloud) == 0) {
|
||||
if(pcl::io::savePLYFileASCII(plyPath.toStdString(), *m_currentPointCloud) == 0) {
|
||||
qDebug() << "保存PLY点云:" << plyPath;
|
||||
success = true;
|
||||
} else {
|
||||
@@ -1819,18 +1819,18 @@ bool MainWindow::savePointCloud(const QString &dir, const QString &baseName, con
|
||||
// ========== 日志功能 ==========
|
||||
void MainWindow::addLog(const QString &message, const QString &level)
|
||||
{
|
||||
if (!m_logDisplay) return;
|
||||
if(!m_logDisplay) return;
|
||||
|
||||
// 获取当前时间戳
|
||||
QString timestamp = QDateTime::currentDateTime().toString("HH:mm:ss.zzz");
|
||||
|
||||
// 根据日志级别设置颜色
|
||||
QString color;
|
||||
if (level == "ERROR") {
|
||||
if(level == "ERROR") {
|
||||
color = "#FF6B6B"; // 红色
|
||||
} else if (level == "WARNING") {
|
||||
} else if(level == "WARNING") {
|
||||
color = "#FFA500"; // 橙色
|
||||
} else if (level == "SUCCESS") {
|
||||
} else if(level == "SUCCESS") {
|
||||
color = "#4CAF50"; // 绿色
|
||||
} else {
|
||||
color = "#D4D4D4"; // 默认灰白色
|
||||
@@ -1851,7 +1851,7 @@ void MainWindow::addLog(const QString &message, const QString &level)
|
||||
|
||||
// 限制日志行数(保留最近1000行)
|
||||
QTextDocument *doc = m_logDisplay->document();
|
||||
if (doc->blockCount() > 1000) {
|
||||
if(doc->blockCount() > 1000) {
|
||||
QTextCursor cursor = m_logDisplay->textCursor();
|
||||
cursor.movePosition(QTextCursor::Start);
|
||||
cursor.movePosition(QTextCursor::Down, QTextCursor::KeepAnchor, doc->blockCount() - 1000);
|
||||
@@ -1864,7 +1864,7 @@ void MainWindow::addLog(const QString &message, const QString &level)
|
||||
|
||||
void MainWindow::onClearLogClicked()
|
||||
{
|
||||
if (m_logDisplay) {
|
||||
if(m_logDisplay) {
|
||||
m_logDisplay->clear();
|
||||
addLog("日志已清除", "INFO");
|
||||
}
|
||||
@@ -1873,11 +1873,11 @@ void MainWindow::onClearLogClicked()
|
||||
void MainWindow::onSaveLogClicked()
|
||||
{
|
||||
QString fileName = QFileDialog::getSaveFileName(this, "保存日志",
|
||||
QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation) + "/d330viewer_log.txt",
|
||||
QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation) + "/viewer_log.txt",
|
||||
"文本文件 (*.txt);;所有文件 (*.*)");
|
||||
if (!fileName.isEmpty()) {
|
||||
if(!fileName.isEmpty()) {
|
||||
QFile file(fileName);
|
||||
if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
||||
if(file.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
||||
QTextStream out(&file);
|
||||
out << m_logDisplay->toPlainText();
|
||||
file.close();
|
||||
@@ -1892,23 +1892,23 @@ void MainWindow::onSaveLogClicked()
|
||||
void MainWindow::updateStatistics()
|
||||
{
|
||||
// 更新三个相机的FPS
|
||||
if (m_leftFpsLabel) {
|
||||
if(m_leftFpsLabel) {
|
||||
m_leftFpsLabel->setText(QString("左红外: %1 fps").arg(m_currentLeftFps, 0, 'f', 1));
|
||||
}
|
||||
if (m_rightFpsLabel) {
|
||||
if(m_rightFpsLabel) {
|
||||
m_rightFpsLabel->setText(QString("右红外: %1 fps").arg(m_currentRightFps, 0, 'f', 1));
|
||||
}
|
||||
if (m_rgbFpsLabel) {
|
||||
if(m_rgbFpsLabel) {
|
||||
m_rgbFpsLabel->setText(QString("RGB彩色: %1 fps").arg(m_currentRgbFps, 0, 'f', 1));
|
||||
}
|
||||
|
||||
// 更新点云帧率
|
||||
if (m_pointCloudFpsLabel) {
|
||||
if(m_pointCloudFpsLabel) {
|
||||
m_pointCloudFpsLabel->setText(QString("点云帧率: %1 fps").arg(m_currentPointCloudFps, 0, 'f', 1));
|
||||
}
|
||||
|
||||
// 更新接收帧数(显示三个相机和点云的累计总数)
|
||||
if (m_queueLabel) {
|
||||
if(m_queueLabel) {
|
||||
m_queueLabel->setText(QString("接收帧数: L%1 R%2 RGB%3 点云%4")
|
||||
.arg(m_totalLeftFrameCount)
|
||||
.arg(m_totalRightFrameCount)
|
||||
@@ -1920,7 +1920,7 @@ void MainWindow::updateStatistics()
|
||||
// 监听系统主题变化事件
|
||||
void MainWindow::changeEvent(QEvent *event)
|
||||
{
|
||||
if (event->type() == QEvent::PaletteChange) {
|
||||
if(event->type() == QEvent::PaletteChange) {
|
||||
// 系统调色板变化,说明主题可能已切换
|
||||
qDebug() << "系统主题已变化,刷新UI样式";
|
||||
|
||||
|
||||
12
src/main.cpp
12
src/main.cpp
@@ -31,19 +31,19 @@ int main(int argc, char *argv[])
|
||||
QApplication app(argc, argv);
|
||||
|
||||
// 设置应用程序信息
|
||||
app.setOrganizationName("D330Viewer");
|
||||
app.setApplicationName("D330Viewer");
|
||||
app.setApplicationVersion("0.2.0");
|
||||
app.setOrganizationName("Viewer");
|
||||
app.setApplicationName("Viewer");
|
||||
app.setApplicationVersion("0.3.0");
|
||||
|
||||
// 初始化Logger(在可执行文件同目录下)
|
||||
QString logPath = QCoreApplication::applicationDirPath() + "/d330viewer.log";
|
||||
QString logPath = QCoreApplication::applicationDirPath() + "/viewer.log";
|
||||
Logger::instance()->setLogFile(logPath);
|
||||
Logger::instance()->setMaxLines(10000); // 保留最新10000行
|
||||
|
||||
// 安装消息处理器
|
||||
qInstallMessageHandler(messageHandler);
|
||||
|
||||
qDebug() << "D330Viewer started";
|
||||
qDebug() << "Viewer started";
|
||||
qDebug() << "Log file:" << logPath;
|
||||
|
||||
// 创建并显示主窗口
|
||||
@@ -52,7 +52,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
int result = app.exec();
|
||||
|
||||
qDebug() << "D330Viewer exiting";
|
||||
qDebug() << "Viewer exiting";
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user