add,单反相机

1、分离功能:单反相机的实时视频流和拍照;
2、将视频流和拍照功能状态反馈到界面上,并做简单控制;
This commit is contained in:
tangchao0503
2026-05-28 13:51:15 +08:00
parent 525b39851a
commit 6456232114
3 changed files with 149 additions and 30 deletions

View File

@ -197,11 +197,42 @@ QPushButton:pressed
</property> </property>
</spacer> </spacer>
</item> </item>
<item row="2" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QPushButton" name="takePhoto_btn">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>拍 摄</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="stopTakePhoto_btn">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>停 拍</string>
</property>
</widget>
</item>
</layout>
</item>
</layout> </layout>
<zorder>dataFolderLineEdit</zorder> <zorder>dataFolderLineEdit</zorder>
<zorder>dataFolderBtn</zorder> <zorder>dataFolderBtn</zorder>
<zorder>label</zorder> <zorder>label</zorder>
<zorder>openSLRCamera_btn</zorder> <zorder>openSLRCamera_btn</zorder>
<zorder>layoutWidget</zorder>
</widget> </widget>
<layoutdefault spacing="6" margin="11"/> <layoutdefault spacing="6" margin="11"/>
<resources/> <resources/>

View File

@ -23,6 +23,11 @@ SingleLensReflexCameraWindow::SingleLensReflexCameraWindow(QWidget* parent)
connect(ui.closeSLRCamera_btn, &QPushButton::clicked, this, &SingleLensReflexCameraWindow::closeSLRCamera); connect(ui.closeSLRCamera_btn, &QPushButton::clicked, this, &SingleLensReflexCameraWindow::closeSLRCamera);
connect(this, &SingleLensReflexCameraWindow::closeSLRCameraSignal, m_SingleLensReflexCameraOperation, &SingleLensReflexCameraOperation::CloseSLRCamera); connect(this, &SingleLensReflexCameraWindow::closeSLRCameraSignal, m_SingleLensReflexCameraOperation, &SingleLensReflexCameraOperation::CloseSLRCamera);
connect(ui.takePhoto_btn, &QPushButton::clicked, this, &SingleLensReflexCameraWindow::takePhoto);
connect(this, &SingleLensReflexCameraWindow::takePhotoSignal, m_SingleLensReflexCameraOperation, &SingleLensReflexCameraOperation::takePhoto);
connect(ui.stopTakePhoto_btn, &QPushButton::clicked, this, &SingleLensReflexCameraWindow::stopTakePhoto);
connect(this, &SingleLensReflexCameraWindow::stopTakePhotoSignal, m_SingleLensReflexCameraOperation, &SingleLensReflexCameraOperation::stopTakePhoto);
connect(m_SingleLensReflexCameraOperation, &SingleLensReflexCameraOperation::CamOpenedSignal, this, &SingleLensReflexCameraWindow::onCamOpened); connect(m_SingleLensReflexCameraOperation, &SingleLensReflexCameraOperation::CamOpenedSignal, this, &SingleLensReflexCameraWindow::onCamOpened);
connect(m_SingleLensReflexCameraOperation, &SingleLensReflexCameraOperation::CamClosedSignal, this, &SingleLensReflexCameraWindow::onCamClosed); connect(m_SingleLensReflexCameraOperation, &SingleLensReflexCameraOperation::CamClosedSignal, this, &SingleLensReflexCameraWindow::onCamClosed);
@ -40,6 +45,10 @@ SingleLensReflexCameraWindow::SingleLensReflexCameraWindow(QWidget* parent)
connect(m_SingleLensReflexCameraOperation, &SingleLensReflexCameraOperation::LiveViewStarted, this, &SingleLensReflexCameraWindow::LiveViewStarted); connect(m_SingleLensReflexCameraOperation, &SingleLensReflexCameraOperation::LiveViewStarted, this, &SingleLensReflexCameraWindow::LiveViewStarted);
connect(m_SingleLensReflexCameraOperation, &SingleLensReflexCameraOperation::LiveViewStopped, this, &SingleLensReflexCameraWindow::LiveViewStopped); connect(m_SingleLensReflexCameraOperation, &SingleLensReflexCameraOperation::LiveViewStopped, this, &SingleLensReflexCameraWindow::LiveViewStopped);
// 拍照状态信号连接
connect(m_SingleLensReflexCameraOperation, &SingleLensReflexCameraOperation::CaptureStartedSignal, this, &SingleLensReflexCameraWindow::onCaptureStarted);
connect(m_SingleLensReflexCameraOperation, &SingleLensReflexCameraOperation::CaptureStoppedSignal, this, &SingleLensReflexCameraWindow::onCaptureStopped);
// 拍照控制信号连接 // 拍照控制信号连接
connect(this, &SingleLensReflexCameraWindow::startCaptureSignal, m_SingleLensReflexCameraOperation, &SingleLensReflexCameraOperation::startCapture); connect(this, &SingleLensReflexCameraWindow::startCaptureSignal, m_SingleLensReflexCameraOperation, &SingleLensReflexCameraOperation::startCapture);
connect(this, &SingleLensReflexCameraWindow::stopCaptureSignal, m_SingleLensReflexCameraOperation, &SingleLensReflexCameraOperation::stopCapture); connect(this, &SingleLensReflexCameraWindow::stopCaptureSignal, m_SingleLensReflexCameraOperation, &SingleLensReflexCameraOperation::stopCapture);
@ -91,6 +100,22 @@ void SingleLensReflexCameraWindow::openSLRCamera()
} }
} }
void SingleLensReflexCameraWindow::takePhoto()
{
if (m_SingleLensReflexCameraOperation->getRecordStatus())
{
emit takePhotoSignal();
}
}
void SingleLensReflexCameraWindow::stopTakePhoto()
{
if (m_SingleLensReflexCameraOperation->getRecordStatus())
{
emit stopTakePhotoSignal();
}
}
void SingleLensReflexCameraWindow::onCamOpened() void SingleLensReflexCameraWindow::onCamOpened()
{ {
ui.openSLRCamera_btn->setEnabled(false); ui.openSLRCamera_btn->setEnabled(false);
@ -112,6 +137,22 @@ void SingleLensReflexCameraWindow::onCamClosed()
m_isCapturing = false; m_isCapturing = false;
} }
void SingleLensReflexCameraWindow::onCaptureStarted()
{
ui.takePhoto_btn->setEnabled(false);
ui.stopTakePhoto_btn->setEnabled(true);
m_btnOldText = ui.takePhoto_btn->text();
ui.takePhoto_btn->setText(QString::fromLocal8Bit("采集中"));
}
void SingleLensReflexCameraWindow::onCaptureStopped()
{
ui.takePhoto_btn->setEnabled(true);
ui.stopTakePhoto_btn->setEnabled(false);
ui.takePhoto_btn->setText(m_btnOldText);
}
void SingleLensReflexCameraWindow::onImageCaptured(const QString& filePath) void SingleLensReflexCameraWindow::onImageCaptured(const QString& filePath)
{ {
std::cout << "Image captured: " << filePath.toStdString() << std::endl; std::cout << "Image captured: " << filePath.toStdString() << std::endl;
@ -153,13 +194,11 @@ void SingleLensReflexCameraWindow::onCaptureOnce()
SingleLensReflexCameraOperation::SingleLensReflexCameraOperation() SingleLensReflexCameraOperation::SingleLensReflexCameraOperation()
{ {
m_func = nullptr; m_func = nullptr;
record = false; m_isRecord = false;
m_camera = nullptr; m_camera = nullptr;
m_isSDKInitialized = false; m_isSDKInitialized = false;
m_isSessionOpen = false; m_isSessionOpen = false;
m_isLiveViewActive = false; m_isLiveViewActive = false;
m_captureTimer = nullptr;
m_liveViewTimer = nullptr;
m_imageCounter = 0; m_imageCounter = 0;
// 设置保存路径(从 AppSettings 获取,如果为空则使用默认的 CapturedImages 目录) // 设置保存路径(从 AppSettings 获取,如果为空则使用默认的 CapturedImages 目录)
@ -172,16 +211,37 @@ SingleLensReflexCameraOperation::SingleLensReflexCameraOperation()
dir.mkpath(m_savePath); dir.mkpath(m_savePath);
} }
// 创建定时器
m_captureTimer = new QTimer(this);
connect(m_captureTimer, &QTimer::timeout, this, &SingleLensReflexCameraOperation::onCaptureTimer);
m_liveViewTimer = new QTimer(this);
connect(m_liveViewTimer, &QTimer::timeout, this, &SingleLensReflexCameraOperation::onLiveViewTimer);
g_cameraOperation = this; g_cameraOperation = this;
} }
SingleLensReflexCameraOperation::~SingleLensReflexCameraOperation() SingleLensReflexCameraOperation::~SingleLensReflexCameraOperation()
{ {
if (record) if (m_isRecord)
{ {
CloseSLRCamera(); CloseSLRCamera();
} }
g_cameraOperation = nullptr; g_cameraOperation = nullptr;
// 销毁定时器
if (m_captureTimer)
{
m_captureTimer->stop();
m_captureTimer->deleteLater();
m_captureTimer = nullptr;
}
if (m_liveViewTimer)
{
m_liveViewTimer->stop();
m_liveViewTimer->deleteLater();
m_liveViewTimer = nullptr;
}
} }
void SingleLensReflexCameraOperation::setSavePath(const QString& path) void SingleLensReflexCameraOperation::setSavePath(const QString& path)
@ -548,7 +608,7 @@ EdsError SingleLensReflexCameraOperation::downloadImage(EdsDirectoryItemRef dire
// 生成保存文件名(使用时间戳) // 生成保存文件名(使用时间戳)
QString timestamp = QDateTime::currentDateTime().toString("yyyyMMdd_HHmmss_zzz"); QString timestamp = QDateTime::currentDateTime().toString("yyyyMMdd_HHmmss_zzz");
QString fileName = m_savePath + "IMG_" + timestamp + "_" + QString::fromLocal8Bit(dirItemInfo.szFileName); QString fileName = m_savePath + QDir::separator() + "IMG_" + timestamp + "_" + QString::fromLocal8Bit(dirItemInfo.szFileName);
std::cout << "Downloading image to: " << fileName.toStdString() << std::endl; std::cout << "Downloading image to: " << fileName.toStdString() << std::endl;
@ -642,7 +702,7 @@ EdsError EDSCALLBACK SingleLensReflexCameraOperation::handleStateEvent(EdsStateE
{ {
case kEdsStateEvent_Shutdown: case kEdsStateEvent_Shutdown:
std::cout << "Camera disconnected" << std::endl; std::cout << "Camera disconnected" << std::endl;
if (pThis != nullptr && pThis->record) if (pThis != nullptr && pThis->m_isRecord)
{ {
pThis->CloseSLRCamera(); pThis->CloseSLRCamera();
} }
@ -703,22 +763,39 @@ void SingleLensReflexCameraOperation::OpenSLRCamera()
// 实时取景启动失败不是致命错误,继续执行 // 实时取景启动失败不是致命错误,继续执行
} }
record = true; m_isRecord = true;
// 创建实时取景定时器约30fps // 启动实时取景定时器约30fps
m_liveViewTimer = new QTimer(this); if (m_liveViewTimer && !m_liveViewTimer->isActive()) {
connect(m_liveViewTimer, &QTimer::timeout, this, &SingleLensReflexCameraOperation::onLiveViewTimer); m_liveViewTimer->start(33); // 约30fps
m_liveViewTimer->start(33); // 约30fps }
// 创建拍照定时器1秒拍一张但不立即启动
m_captureTimer = new QTimer(this);
connect(m_captureTimer, &QTimer::timeout, this, &SingleLensReflexCameraOperation::onCaptureTimer);
// 默认启动定时拍照
m_captureTimer->start(3000); // 1000毫秒 = 1秒
emit CamOpenedSignal(); emit CamOpenedSignal();
std::cout << "Camera opened, live view started, capture timer started (1 photo per second)" << std::endl; std::cout << "Camera opened, live view started." << std::endl;
}
void SingleLensReflexCameraOperation::takePhoto()
{
// 启动拍照定时器每3秒拍一张
if (m_captureTimer && !m_captureTimer->isActive())
{
m_captureTimer->start(3000);
std::cout << "capture timer started (1 photo 3 second)" << std::endl;
emit CaptureStartedSignal();
}
}
void SingleLensReflexCameraOperation::stopTakePhoto()
{
if (m_captureTimer && m_captureTimer->isActive())
{
m_captureTimer->stop();
std::cout << "capture timer stopped" << std::endl;
emit CaptureStoppedSignal();
}
} }
void SingleLensReflexCameraOperation::OpenSLRCamera_callback() void SingleLensReflexCameraOperation::OpenSLRCamera_callback()
@ -733,7 +810,7 @@ void SingleLensReflexCameraOperation::setCallback(void(*func)())
void SingleLensReflexCameraOperation::onLiveViewTimer() void SingleLensReflexCameraOperation::onLiveViewTimer()
{ {
if (!record || !m_isLiveViewActive) if (!m_isRecord || !m_isLiveViewActive)
{ {
return; return;
} }
@ -747,7 +824,7 @@ void SingleLensReflexCameraOperation::onLiveViewTimer()
void SingleLensReflexCameraOperation::onCaptureTimer() void SingleLensReflexCameraOperation::onCaptureTimer()
{ {
if (!record) if (!m_isRecord)
{ {
return; return;
} }
@ -776,6 +853,7 @@ void SingleLensReflexCameraOperation::startCapture()
{ {
m_captureTimer->start(1000); m_captureTimer->start(1000);
std::cout << "Capture timer started" << std::endl; std::cout << "Capture timer started" << std::endl;
emit CaptureStartedSignal();
} }
} }
@ -785,12 +863,13 @@ void SingleLensReflexCameraOperation::stopCapture()
{ {
m_captureTimer->stop(); m_captureTimer->stop();
std::cout << "Capture timer stopped" << std::endl; std::cout << "Capture timer stopped" << std::endl;
emit CaptureStoppedSignal();
} }
} }
void SingleLensReflexCameraOperation::captureOnce() void SingleLensReflexCameraOperation::captureOnce()
{ {
if (record) if (m_isRecord)
{ {
QMutexLocker locker(&m_mutex); QMutexLocker locker(&m_mutex);
takePicture(); takePicture();
@ -803,22 +882,17 @@ void SingleLensReflexCameraOperation::CloseSLRCamera()
QMutexLocker locker(&m_mutex); QMutexLocker locker(&m_mutex);
record = false; m_isRecord = false;
// 停止拍照定时器 // 停止定时器
if (m_captureTimer != nullptr) if (m_captureTimer != nullptr)
{ {
m_captureTimer->stop(); m_captureTimer->stop();
delete m_captureTimer;
m_captureTimer = nullptr;
} }
// 停止实时取景定时器
if (m_liveViewTimer != nullptr) if (m_liveViewTimer != nullptr)
{ {
m_liveViewTimer->stop(); m_liveViewTimer->stop();
delete m_liveViewTimer;
m_liveViewTimer = nullptr;
} }
// 停止实时取景 // 停止实时取景

View File

@ -38,7 +38,7 @@ public:
QImage m_colorImage; QImage m_colorImage;
QImage m_depthImage; QImage m_depthImage;
void setCallback(void(*func)()); void setCallback(void(*func)());
bool getRecordStatus() const { return record; } bool getRecordStatus() const { return m_isRecord; }
// 设置保存路径 // 设置保存路径
void setSavePath(const QString& path); void setSavePath(const QString& path);
@ -49,7 +49,7 @@ public:
private: private:
cv::Mat frame; cv::Mat frame;
func m_func; func m_func;
bool record; bool m_isRecord;
// Canon EDSDK相关成员 // Canon EDSDK相关成员
EdsCameraRef m_camera; EdsCameraRef m_camera;
@ -90,6 +90,8 @@ private:
public slots: public slots:
void OpenSLRCamera(); void OpenSLRCamera();
void takePhoto();
void stopTakePhoto();
void OpenSLRCamera_callback(); void OpenSLRCamera_callback();
void CloseSLRCamera(); void CloseSLRCamera();
void onCaptureTimer(); void onCaptureTimer();
@ -111,6 +113,9 @@ signals:
void LiveViewImageReady(const QImage& image); void LiveViewImageReady(const QImage& image);
void LiveViewStarted(); void LiveViewStarted();
void LiveViewStopped(); void LiveViewStopped();
void CaptureStartedSignal();
void CaptureStoppedSignal();
}; };
class SingleLensReflexCameraWindow : public QDialog class SingleLensReflexCameraWindow : public QDialog
@ -127,6 +132,8 @@ public Q_SLOTS:
void onSelectDataFolder(); void onSelectDataFolder();
void openSLRCamera(); void openSLRCamera();
void takePhoto();
void stopTakePhoto();
void onCamOpened(); void onCamOpened();
void closeSLRCamera(); void closeSLRCamera();
void onCamClosed(); void onCamClosed();
@ -138,8 +145,13 @@ public Q_SLOTS:
void onStopCapture(); void onStopCapture();
void onCaptureOnce(); void onCaptureOnce();
void onCaptureStarted();
void onCaptureStopped();
signals: signals:
void openSLRCameraSignal(); void openSLRCameraSignal();
void takePhotoSignal();
void stopTakePhotoSignal();
void closeSLRCameraSignal(); void closeSLRCameraSignal();
void PlotSLRImageSignal(); void PlotSLRImageSignal();
void SLRCamClosedSignal(); void SLRCamClosedSignal();
@ -159,6 +171,8 @@ private:
// 用于显示实时取景的标签如果UI中没有可以动态创建 // 用于显示实时取景的标签如果UI中没有可以动态创建
QLabel* m_liveViewLabel; QLabel* m_liveViewLabel;
QString m_btnOldText; // 存储拍照按钮的原始文本
bool m_isCapturing; // 是否正在定时拍照 bool m_isCapturing; // 是否正在定时拍照
}; };