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:
cv::Mat mat;
size_t cameraId;
Image(cv::Mat mati, size_t cameraIdi): mat(mati), cameraId(cameraIdi){}
uint64_t cameraId;
Image(cv::Mat mati, uint64_t cameraIdi): mat(mati), cameraId(cameraIdi){}
Image() = default;
Image(const Image& img) = default;
};
@ -29,7 +29,7 @@ private:
cam::Camera* camera_ = nullptr;
void callback(cv::Mat);
size_t cameraId_;
uint64_t cameraId_;
signals:
void newImage(Image);
@ -38,7 +38,7 @@ public:
Camera(cam::Camera::Description);
~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 !operator==(cam);}
};

View File

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

View File

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

View File

@ -6,6 +6,7 @@
#include <QFuture>
#include <QDebug>
#include <algorithm>
#include <opencv2/highgui.hpp>
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)
{
qDebug()<<__FUNCTION__<<"got"<<images.size()<<"images";
qDebug()<<__func__<<"got"<<images.size()<<"images";
std::vector<RemapedImage> remapedImages;
remapedImages.reserve(images.size());
@ -80,7 +81,13 @@ cv::Mat ImagePipeline::process(const Profile profile, std::vector<Camera::Image>
if(remapedImages.size() > 0)
{
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);
if(profile.lightmap.data)

View File

@ -23,10 +23,10 @@ const char* organziation = "UVOS";
const char* application = "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;
CameraDialog diag(cam::Camera::getAvailableCameras());
CameraDialog diag(cam::Camera::getAvailableCameras(), w);
diag.show();
if(diag.exec() == QDialog::Accepted)
@ -42,13 +42,13 @@ std::vector<cam::Camera::Description> showCameraSelectionDialog(bool* accepted =
return ret;
}
void showProfileDialog(Cameras* cameras)
void showProfileDialog(Cameras* cameras, QWidget* w)
{
qDebug()<<__FUNCTION__;
cameras->stop();
cameras->disable(true);
std::vector<cam::Camera::Description> descs = cameras->getCameras();
ProfileDialog diag(cameras);
ProfileDialog diag(cameras, w);
diag.show();
diag.exec();
cameras->disable(false);
@ -56,7 +56,7 @@ void showProfileDialog(Cameras* cameras)
int main(int argc, char *argv[])
{
Log::level = Log::WARN;
Log::level = Log::DEBUG;
uvosled 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::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::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;
std::vector<cam::Camera::Description> descs = showCameraSelectionDialog(&accepted);
std::vector<cam::Camera::Description> descs = showCameraSelectionDialog(&accepted, &w);
if(accepted)
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](){w.statusMsg("idle");});
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();
setRowCount(static_cast<int>(desc_.size()));
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()));
}
}
std::vector<cam::Camera::Description> CameraListWidget::getSelectedDescriptions()

View File

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

View File

@ -12,7 +12,7 @@ MainWindow::MainWindow(QWidget *parent)
, ui(new Ui::MainWindow)
{
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->actionCameras, &QAction::triggered, [this](bool checked){(void)checked; sigChooseCameras();});
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);
}
void MainWindow::setTemperature(double temp)
{
ui->lcdNumber_temp->display(temp);
}
void MainWindow::saveImage()
{
if(!ui->mainViewer->getImage().data)
@ -59,7 +64,16 @@ void MainWindow::openImage()
{
cv::Mat image;
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))
{
@ -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)
{
viewers_.push_back(new CvImageViewer(this, camera->id()));

View File

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

View File

@ -42,7 +42,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>278</width>
<width>182</width>
<height>483</height>
</rect>
</property>
@ -74,8 +74,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>467</width>
<height>313</height>
<width>563</width>
<height>282</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_6">
@ -152,6 +152,9 @@
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QPushButton" name="pushButtonCapture">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Capture</string>
</property>
@ -180,6 +183,36 @@
</item>
</layout>
</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>
</widget>
</item>