change stiching method

add camera temperature readout
This commit is contained in:
2021-07-05 11:27:38 +02:00
parent ea3b870c0a
commit 48a04fdf79
10 changed files with 128 additions and 24 deletions

View File

@ -20,8 +20,8 @@ public:
{ {
public: public:
cv::Mat mat; cv::Mat mat;
size_t cameraId; uint64_t cameraId;
Image(cv::Mat mati, size_t cameraIdi): mat(mati), cameraId(cameraIdi){} Image(cv::Mat mati, uint64_t cameraIdi): mat(mati), cameraId(cameraIdi){}
Image() = default; Image() = default;
Image(const Image& img) = default; Image(const Image& img) = default;
}; };
@ -29,7 +29,7 @@ private:
cam::Camera* camera_ = nullptr; cam::Camera* camera_ = nullptr;
void callback(cv::Mat); void callback(cv::Mat);
size_t cameraId_; uint64_t cameraId_;
signals: signals:
void newImage(Image); void newImage(Image);
@ -38,7 +38,7 @@ public:
Camera(cam::Camera::Description); Camera(cam::Camera::Description);
~Camera(); ~Camera();
cam::Camera* cam(){return camera_;} cam::Camera* cam(){return camera_;}
size_t id() const {return cameraId_;} uint64_t id() const {return cameraId_;}
bool operator==(const Camera& cam){return cam.id() == id();} bool operator==(const Camera& cam){return cam.id() == id();}
bool operator!=(const Camera& cam){return !operator==(cam);} bool operator!=(const Camera& cam){return !operator==(cam);}
}; };

View File

@ -9,7 +9,9 @@
Cameras::Cameras(uvosled* led): led_(led) Cameras::Cameras(uvosled* led): led_(led)
{ {
ledTimer.setSingleShot(true); ledTimer.setSingleShot(true);
cameraFailureTimer.setSingleShot(true);
connect(&ledTimer, &QTimer::timeout, this, &Cameras::lightOff); connect(&ledTimer, &QTimer::timeout, this, &Cameras::lightOff);
connect(&cameraFailureTimer, &QTimer::timeout, this, &Cameras::reloadCameras);
} }
Cameras::~Cameras() Cameras::~Cameras()
@ -29,6 +31,11 @@ bool Cameras::setCameras(const std::vector<cam::Camera::Description>& descriptio
return ret; return ret;
} }
void Cameras::reloadCameras()
{
setCameras(getCameras());
}
void Cameras::clear() void Cameras::clear()
{ {
@ -70,6 +77,9 @@ bool Cameras::addCamera(const cam::Camera::Description& desc)
return false; return false;
} }
enableCapture(false);
blockCaptureId_ = cameras_.back()->id();
cameras_.back()->cam()->setExposureTime(exposrueTime_); cameras_.back()->cam()->setExposureTime(exposrueTime_);
if(desc.getVendor().find("Photonfocus") != std::string::npos) if(desc.getVendor().find("Photonfocus") != std::string::npos)
@ -80,11 +90,11 @@ bool Cameras::addCamera(const cam::Camera::Description& desc)
camera->cam()->setAcquisitionMode(cam::Camera::MODE_FREE); camera->cam()->setAcquisitionMode(cam::Camera::MODE_FREE);
camera->cam()->setFrameRate(10); camera->cam()->setFrameRate(10);
camera->cam()->startAcquisition(); camera->cam()->startAcquisition();
struct timespec tv = {0, 200000000}; std::this_thread::sleep_for (std::chrono::milliseconds(200));
nanosleep(&tv, nullptr);
camera->cam()->stopAcquisition(); camera->cam()->stopAcquisition();
cameras_.pop_back(); cameras_.pop_back();
camera = nullptr; camera = nullptr;
std::this_thread::sleep_for (std::chrono::milliseconds(200));
cameras_.push_back(std::shared_ptr<Camera>(new Camera(desc))); cameras_.push_back(std::shared_ptr<Camera>(new Camera(desc)));
if(!cameras_.back()->cam()->isOpen()) if(!cameras_.back()->cam()->isOpen())
{ {
@ -112,6 +122,8 @@ void Cameras::finishAddCamera(std::shared_ptr<Camera> camera)
camera->cam()->setTriggerMode(cam::Camera::TRIGGER_SOFTWARE); camera->cam()->setTriggerMode(cam::Camera::TRIGGER_SOFTWARE);
setFree(free_); setFree(free_);
connect(camera.get(), &Camera::newImage, this, &Cameras::imageRecived); connect(camera.get(), &Camera::newImage, this, &Cameras::imageRecived);
if(blockCaptureId_ == camera->id())
enableCapture(true);
qDebug()<<"Using camera"<<camera->id(); qDebug()<<"Using camera"<<camera->id();
} }
@ -229,8 +241,12 @@ void Cameras::imageRecived(Camera::Image img)
qDebug()<<"Recived"<<images_.size()<<"of"<<cameras_.size()<<"images"; qDebug()<<"Recived"<<images_.size()<<"of"<<cameras_.size()<<"images";
if(images_.size() == 1)
cameraFailureTimer.start(exposrueTime_*1000+1000);
if(images_.size() == cameras_.size()) if(images_.size() == cameras_.size())
{ {
cameraFailureTimer.stop();
newImages(images_); newImages(images_);
images_.clear(); images_.clear();
} }
@ -238,6 +254,24 @@ void Cameras::imageRecived(Camera::Image img)
} }
} }
double Cameras::getMeanTemp()
{
double mean = 0;
bool failure = false;
for(auto& camera : cameras_)
{
double temp;
if(camera->cam()->getTemperature(temp))
mean+=temp;
else
failure = true;
}
if(!failure)
return mean/cameras_.size();
else
return NAN;
}
void Cameras::setSetup(const std::vector<CameraSetup>& setups) void Cameras::setSetup(const std::vector<CameraSetup>& setups)
{ {
for(auto& camera : cameras_) for(auto& camera : cameras_)

View File

@ -26,10 +26,12 @@ private:
bool free_ = false; bool free_ = false;
bool disable_ = false; bool disable_ = false;
double exposrueTime_ = 1.0/60.0; double exposrueTime_ = 1.0/60.0;
uint64_t blockCaptureId_ = 0;
LightingSetup lighting_; LightingSetup lighting_;
std::vector<std::shared_ptr<Camera>> cameras_; std::vector<std::shared_ptr<Camera>> cameras_;
std::vector<Camera::Image> images_; std::vector<Camera::Image> images_;
QTimer ledTimer; QTimer ledTimer;
QTimer cameraFailureTimer;
bool lightFor(const LightingSetup& lighting, double time); bool lightFor(const LightingSetup& lighting, double time);
@ -42,6 +44,7 @@ signals:
void cameraRemoved(std::shared_ptr<Camera> camera); void cameraRemoved(std::shared_ptr<Camera> camera);
void cameraAdded(std::shared_ptr<Camera> camera); void cameraAdded(std::shared_ptr<Camera> camera);
void newImages(std::vector<Camera::Image> images); void newImages(std::vector<Camera::Image> images);
void enableCapture(bool enable);
public slots: public slots:
@ -51,6 +54,7 @@ public slots:
bool stop(); bool stop();
bool setFree(bool free); bool setFree(bool free);
void setLighting(const LightingSetup& lighting) {lighting_ = lighting;} void setLighting(const LightingSetup& lighting) {lighting_ = lighting;}
void reloadCameras();
public: public:
Cameras(uvosled* led = nullptr); Cameras(uvosled* led = nullptr);
@ -62,6 +66,7 @@ public:
std::shared_ptr<Camera> getCamera(size_t id); std::shared_ptr<Camera> getCamera(size_t id);
size_t numCameras(){return cameras_.size();} size_t numCameras(){return cameras_.size();}
void clear(); void clear();
double getMeanTemp();
void load(QSettings& settings); void load(QSettings& settings);
void store(QSettings& settings); void store(QSettings& settings);
void disable(bool disable); void disable(bool disable);

View File

@ -6,6 +6,7 @@
#include <QFuture> #include <QFuture>
#include <QDebug> #include <QDebug>
#include <algorithm> #include <algorithm>
#include <opencv2/highgui.hpp>
ImagePipeline::ImagePipeline(Cameras* cameras, QObject *parent): QObject(parent), cameras_(cameras) ImagePipeline::ImagePipeline(Cameras* cameras, QObject *parent): QObject(parent), cameras_(cameras)
{ {
@ -14,7 +15,7 @@ ImagePipeline::ImagePipeline(Cameras* cameras, QObject *parent): QObject(parent)
cv::Mat ImagePipeline::process(const Profile profile, std::vector<Camera::Image> images) cv::Mat ImagePipeline::process(const Profile profile, std::vector<Camera::Image> images)
{ {
qDebug()<<__FUNCTION__<<"got"<<images.size()<<"images"; qDebug()<<__func__<<"got"<<images.size()<<"images";
std::vector<RemapedImage> remapedImages; std::vector<RemapedImage> remapedImages;
remapedImages.reserve(images.size()); remapedImages.reserve(images.size());
@ -80,7 +81,13 @@ cv::Mat ImagePipeline::process(const Profile profile, std::vector<Camera::Image>
if(remapedImages.size() > 0) if(remapedImages.size() > 0)
{ {
std::sort(remapedImages.begin(), remapedImages.end(), [](const RemapedImage& imgA, const RemapedImage& imgB) -> bool {return imgA.origin.x < imgB.origin.x;}); std::sort(remapedImages.begin(), remapedImages.end(), [](const RemapedImage& imgA, const RemapedImage& imgB) -> bool {return imgA.origin.x < imgB.origin.x;});
cv::Mat output = simpleStich(remapedImages); cv::Mat output = stich(remapedImages);
if(output.depth() != CV_8U)
output.convertTo(output, CV_8U);
if(output.channels() == 3)
cv::cvtColor(output, output, cv::COLOR_BGR2GRAY);
output.convertTo(output, CV_32FC1, 1.0/255.0, 0); output.convertTo(output, CV_32FC1, 1.0/255.0, 0);
if(profile.lightmap.data) if(profile.lightmap.data)

View File

@ -23,10 +23,10 @@ const char* organziation = "UVOS";
const char* application = "UVOS"; const char* application = "UVOS";
const char* version = "UVOS"; const char* version = "UVOS";
std::vector<cam::Camera::Description> showCameraSelectionDialog(bool* accepted = nullptr) std::vector<cam::Camera::Description> showCameraSelectionDialog(bool* accepted = nullptr, QWidget* w = nullptr)
{ {
std::vector<cam::Camera::Description> ret; std::vector<cam::Camera::Description> ret;
CameraDialog diag(cam::Camera::getAvailableCameras()); CameraDialog diag(cam::Camera::getAvailableCameras(), w);
diag.show(); diag.show();
if(diag.exec() == QDialog::Accepted) if(diag.exec() == QDialog::Accepted)
@ -42,13 +42,13 @@ std::vector<cam::Camera::Description> showCameraSelectionDialog(bool* accepted =
return ret; return ret;
} }
void showProfileDialog(Cameras* cameras) void showProfileDialog(Cameras* cameras, QWidget* w)
{ {
qDebug()<<__FUNCTION__; qDebug()<<__FUNCTION__;
cameras->stop(); cameras->stop();
cameras->disable(true); cameras->disable(true);
std::vector<cam::Camera::Description> descs = cameras->getCameras(); std::vector<cam::Camera::Description> descs = cameras->getCameras();
ProfileDialog diag(cameras); ProfileDialog diag(cameras, w);
diag.show(); diag.show();
diag.exec(); diag.exec();
cameras->disable(false); cameras->disable(false);
@ -56,7 +56,7 @@ void showProfileDialog(Cameras* cameras)
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
Log::level = Log::WARN; Log::level = Log::DEBUG;
uvosled led; uvosled led;
int uvosledRet = uvosled_connect(&led); int uvosledRet = uvosled_connect(&led);
@ -99,17 +99,23 @@ int main(int argc, char *argv[])
QObject::connect(&cameras, &Cameras::cameraAdded, &w, &MainWindow::addCamera); QObject::connect(&cameras, &Cameras::cameraAdded, &w, &MainWindow::addCamera);
QObject::connect(&cameras, &Cameras::cameraRemoved, &w, &MainWindow::removeCamera); QObject::connect(&cameras, &Cameras::cameraRemoved, &w, &MainWindow::removeCamera);
QObject::connect(&cameras, &Cameras::enableCapture, &w, &MainWindow::enableCapture);
QObject::connect(&w, &MainWindow::sigCapture, [&cameras](){cameras.start(); cameras.trigger();}); QObject::connect(&w, &MainWindow::sigCapture, [&cameras](){cameras.start(); cameras.trigger();});
QObject::connect(&w, &MainWindow::sigChooseCameras, [&cameras]() QTimer temperatureTimer;
temperatureTimer.setSingleShot(false);
QObject::connect(&temperatureTimer, &QTimer::timeout, [&cameras, &w](){w.setTemperature(cameras.getMeanTemp());});
temperatureTimer.start(1000);
QObject::connect(&w, &MainWindow::sigChooseCameras, [&cameras, &w]()
{ {
bool accepted; bool accepted;
std::vector<cam::Camera::Description> descs = showCameraSelectionDialog(&accepted); std::vector<cam::Camera::Description> descs = showCameraSelectionDialog(&accepted, &w);
if(accepted) if(accepted)
cameras.setCameras(descs); cameras.setCameras(descs);
}); });
QObject::connect(&w, &MainWindow::sigEditProfiles, [&cameras, &w](){showProfileDialog(&cameras); w.refreshProfiles();}); QObject::connect(&w, &MainWindow::sigEditProfiles, [&cameras, &w](){showProfileDialog(&cameras, &w); w.refreshProfiles();});
QObject::connect(&pipe, &ImagePipeline::sigResult, w.mainImageViewer(), &CvImageViewer::setImage, Qt::QueuedConnection); QObject::connect(&pipe, &ImagePipeline::sigResult, w.mainImageViewer(), &CvImageViewer::setImage, Qt::QueuedConnection);
QObject::connect(&pipe, &ImagePipeline::sigResult, [&w](){w.statusMsg("idle");}); QObject::connect(&pipe, &ImagePipeline::sigResult, [&w](){w.statusMsg("idle");});
QObject::connect(&pipe, &ImagePipeline::sigInvalidProfile, &w, &MainWindow::profileInconpatible); QObject::connect(&pipe, &ImagePipeline::sigInvalidProfile, &w, &MainWindow::profileInconpatible);

View File

@ -31,9 +31,7 @@ void CameraListWidget::setCameras(const std::vector<cam::Camera::Description>& d
qDebug()<<"cameras: "<<desc_.size(); qDebug()<<"cameras: "<<desc_.size();
setRowCount(static_cast<int>(desc_.size())); setRowCount(static_cast<int>(desc_.size()));
for(size_t i = 0; i < desc_.size(); ++i) for(size_t i = 0; i < desc_.size(); ++i)
{
setItem(static_cast<int>(i), 0, new QTableWidgetItem((desc_[i].getVendor() + " " + desc_[i].getModel()).c_str())); setItem(static_cast<int>(i), 0, new QTableWidgetItem((desc_[i].getVendor() + " " + desc_[i].getModel()).c_str()));
}
} }
std::vector<cam::Camera::Description> CameraListWidget::getSelectedDescriptions() std::vector<cam::Camera::Description> CameraListWidget::getSelectedDescriptions()

View File

@ -100,7 +100,6 @@ void CvImageViewer::mousePressEvent(QMouseEvent *event)
} }
else else
{ {
sigValue(x, y, 0); sigValue(x, y, 0);
} }
} }

View File

@ -12,7 +12,7 @@ MainWindow::MainWindow(QWidget *parent)
, ui(new Ui::MainWindow) , ui(new Ui::MainWindow)
{ {
ui->setupUi(this); ui->setupUi(this);
ui->statusbar->showMessage("idle"); ui->statusbar->showMessage("no cameras");
connect(ui->actionQuit, &QAction::triggered, [this](bool checked){(void)checked; close();}); connect(ui->actionQuit, &QAction::triggered, [this](bool checked){(void)checked; close();});
connect(ui->actionCameras, &QAction::triggered, [this](bool checked){(void)checked; sigChooseCameras();}); connect(ui->actionCameras, &QAction::triggered, [this](bool checked){(void)checked; sigChooseCameras();});
connect(ui->actionProfile, &QAction::triggered, [this](bool checked){(void)checked; sigEditProfiles();}); connect(ui->actionProfile, &QAction::triggered, [this](bool checked){(void)checked; sigEditProfiles();});
@ -32,6 +32,11 @@ void MainWindow::setImageValue(size_t x, size_t y, double value)
ui->lcdNumber->display(value); ui->lcdNumber->display(value);
} }
void MainWindow::setTemperature(double temp)
{
ui->lcdNumber_temp->display(temp);
}
void MainWindow::saveImage() void MainWindow::saveImage()
{ {
if(!ui->mainViewer->getImage().data) if(!ui->mainViewer->getImage().data)
@ -59,7 +64,16 @@ void MainWindow::openImage()
{ {
cv::Mat image; cv::Mat image;
cv::FileStorage matf(fileName.toStdString(), cv::FileStorage::READ); cv::FileStorage matf(fileName.toStdString(), cv::FileStorage::READ);
matf["image"]>>image; try
{
matf["image"]>>image;
}
catch(const cv::Exception& ex)
{
qDebug()<<ex.what();
QMessageBox::warning(this, "Invalid file", "File selected dose not contain a valid image");
return;
}
if(matf.isOpened() && (!image.data || image.type() != CV_32FC1)) if(matf.isOpened() && (!image.data || image.type() != CV_32FC1))
{ {
@ -75,6 +89,12 @@ void MainWindow::openImage()
} }
} }
void MainWindow::enableCapture(bool enable)
{
ui->statusbar->showMessage(enable ? "idle" : "cameras not ready" );
ui->pushButtonCapture->setEnabled(enable);
}
void MainWindow::addCamera(std::shared_ptr<Camera> camera) void MainWindow::addCamera(std::shared_ptr<Camera> camera)
{ {
viewers_.push_back(new CvImageViewer(this, camera->id())); viewers_.push_back(new CvImageViewer(this, camera->id()));

View File

@ -36,6 +36,8 @@ public slots:
bool setProfile(const QString& profileName); bool setProfile(const QString& profileName);
QString getProfileName(); QString getProfileName();
void statusMsg(QString msg); void statusMsg(QString msg);
void enableCapture(bool capture);
void setTemperature(double temp);
public: public:
MainWindow(QWidget *parent = nullptr); MainWindow(QWidget *parent = nullptr);

View File

@ -42,7 +42,7 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>278</width> <width>182</width>
<height>483</height> <height>483</height>
</rect> </rect>
</property> </property>
@ -74,8 +74,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>467</width> <width>563</width>
<height>313</height> <height>282</height>
</rect> </rect>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_6"> <layout class="QVBoxLayout" name="verticalLayout_6">
@ -152,6 +152,9 @@
<layout class="QVBoxLayout" name="verticalLayout_2"> <layout class="QVBoxLayout" name="verticalLayout_2">
<item> <item>
<widget class="QPushButton" name="pushButtonCapture"> <widget class="QPushButton" name="pushButtonCapture">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text"> <property name="text">
<string>Capture</string> <string>Capture</string>
</property> </property>
@ -180,6 +183,36 @@
</item> </item>
</layout> </layout>
</item> </item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="topMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label_temp">
<property name="enabled">
<bool>true</bool>
</property>
<property name="text">
<string>Mean camera temperature [℃]</string>
</property>
</widget>
</item>
<item>
<widget class="QLCDNumber" name="lcdNumber_temp">
<property name="enabled">
<bool>true</bool>
</property>
<property name="value" stdset="0">
<double>0.000000000000000</double>
</property>
<property name="intValue" stdset="0">
<number>0</number>
</property>
</widget>
</item>
</layout>
</item>
</layout> </layout>
</widget> </widget>
</item> </item>