diff --git a/b b/b index a6d5b193aa6c6d525828e9de7677701f3e4b1252..aaaaf3faf667d2e3a66349bf1d6aa64321a6739b 160000 --- a/b +++ b/b @@ -1 +1 @@ -Subproject commit a6d5b193aa6c6d525828e9de7677701f3e4b1252 +Subproject commit aaaaf3faf667d2e3a66349bf1d6aa64321a6739b diff --git a/dox/00-overview-camtron.odt b/dox/00_overview_camtron.odt similarity index 100% rename from dox/00-overview-camtron.odt rename to dox/00_overview_camtron.odt diff --git a/dox/01-camera-tracking-method-englisch.odt b/dox/01_camera_tracking_method_englisch.odt similarity index 100% rename from dox/01-camera-tracking-method-englisch.odt rename to dox/01_camera_tracking_method_englisch.odt diff --git a/dox/notes_A b/dox/notes_a similarity index 100% rename from dox/notes_A rename to dox/notes_a diff --git a/dox/notes_B b/dox/notes_b similarity index 98% rename from dox/notes_B rename to dox/notes_b index f1074a5e4cd182c5e2b1f00626ee51d97c2d605c..a4baf0df92f6b29ec94ccde5c83720d8738bf998 100644 --- a/dox/notes_B +++ b/dox/notes_b @@ -9,6 +9,10 @@ Does use opencv to convert raw cam images into JPEG pixel format ############################### +VmbSystem::RegisterCameraListObserver + For being notified whenever a camera is detected, disconnected, or changes its open state, use + + map cam -> MAC -> IP -> name (contains ID) camtron1 000A4708ED3F 172.18.227.210 allied-alviumg1-240c-04ytr.idiv.de camtron2 000A471C0C9D 172.18.227.211 allied-alviumg1-240c-04ytp.idiv.de diff --git a/dox/notes_C b/dox/notes_c similarity index 100% rename from dox/notes_C rename to dox/notes_c diff --git a/dox/notes_D b/dox/notes_d similarity index 100% rename from dox/notes_D rename to dox/notes_d diff --git a/dox/notes_X b/dox/notes_x similarity index 100% rename from dox/notes_X rename to dox/notes_x diff --git a/dox/scrap b/dox/scrap index e6bb121c0589834bc1542f5f1c7db1434d39d88d..83d21848ed7777a9a62ac4de04a18d9bc549058e 100644 --- a/dox/scrap +++ b/dox/scrap @@ -1,5 +1,474 @@ +//############################### +// +// We create a FrameProcessor class that subclasses QObject and defines a slot processFrame() to handle frame processing. +// We create a FrameObserver class that subclasses IFrameObserver. In its constructor, we create an instance of FrameProcessor and move it to a worker thread. +// We connect the FrameObserver::frameReceived signal to the FrameProcessor::processFrame slot, so frame processing happens asynchronously in the worker thread. +// In the FrameObserver::FrameReceived function, we emit the frameReceived signal with the received frame, triggering asynchronous frame processing. +// +// This way, frame processing occurs asynchronously in another thread, separate from the GUI thread. Adjust the code as needed to fit your application's requirements. +// +//############################### +#include <QtCore> +#include <VimbaCPP/Include/VimbaCPP.h> +#include <opencv2/opencv.hpp> -# misc - abbrev -LUT - LookupTable +using namespace AVT::VmbAPI; +class FrameProcessor : public QObject +{ + Q_OBJECT + +public slots: + void processFrame(FramePtr pFrame) + { + VmbUint64_t timestamp; + if (VmbErrorSuccess == pFrame->GetTimestamp(timestamp)) + { + // Convert timestamp to QDateTime for better handling with Qt + QDateTime dateTime = QDateTime::fromMSecsSinceEpoch(timestamp / 1000); + + // Convert QDateTime to a string format + QString timestampStr = dateTime.toString("yyyy-MM-dd_HH-mm-ss"); + + // Process the frame + VmbUchar_t *buffer; + if (VmbErrorSuccess == pFrame->GetImage(buffer)) + { + int width, height; + VmbUint32_t imageSize; + pFrame->GetWidth(width); + pFrame->GetHeight(height); + pFrame->GetImageSize(imageSize); + + cv::Mat image(height, width, CV_8UC1, buffer); + + // Save the frame with timestamp using Qt functions + QString filename = "camera_image_" + timestampStr + ".jpg"; + cv::imwrite(filename.toStdString(), image); + } + } + } +}; + +class FrameObserver : public IFrameObserver +{ +public: + FrameObserver(CameraPtr pCamera, QObject *parent = nullptr) : IFrameObserver(pCamera), m_processor(new FrameProcessor), m_thread(new QThread(parent)) + { + m_processor->moveToThread(m_thread); + connect(this, &FrameObserver::frameReceived, m_processor, &FrameProcessor::processFrame); + m_thread->start(); + } + + ~FrameObserver() + { + m_thread->quit(); + m_thread->wait(); + delete m_thread; + } + + void FrameReceived(const FramePtr pFrame) override + { + emit frameReceived(pFrame); + } + +signals: + void frameReceived(FramePtr pFrame); + +private: + FrameProcessor *m_processor; + QThread *m_thread; +}; + +############################### +## FrameReceived with storing images along with timestamps +#include <QtCore> +#include <VimbaCPP/Include/VimbaCPP.h> +#include <opencv2/opencv.hpp> + +using namespace AVT::VmbAPI; + +void FrameObserver::FrameReceived(const FramePtr pFrame) +{ + VmbUint64_t timestamp; + if (VmbErrorSuccess == pFrame->GetTimestamp(timestamp)) + { + // Convert timestamp to QDateTime for better handling with Qt + QDateTime dateTime = QDateTime::fromMSecsSinceEpoch(timestamp / 1000); + + // Convert QDateTime to a string format + QString timestampStr = dateTime.toString("yyyy-MM-dd_HH-mm-ss"); + + // Process the frame + VmbUchar_t *buffer; + if (VmbErrorSuccess == pFrame->GetImage(buffer)) + { + int width, height; + VmbUint32_t imageSize; + pFrame->GetWidth(width); + pFrame->GetHeight(height); + pFrame->GetImageSize(imageSize); + + cv::Mat image(height, width, CV_8UC1, buffer); + + // Save the frame with timestamp using Qt functions + QString filename = "camera_image_" + timestampStr + ".jpg"; + cv::imwrite(filename.toStdString(), image); + } + } +} + +############################### +## IsCommandDone +err = feature->RunCommand(); + if (err == VmbErrorSuccess) + { + bool commandDone = false; + do + { + if (feature->IsCommandDone(commandDone) != VmbErrorSuccess) + { + break; + } + } while (commandDone == false); + } +############################### + +#include <VimbaC/Include/VimbaC.h> +#include <iostream> +#include <chrono> + +using namespace std; +using namespace chrono; + +class Camera { +public: + Camera(); + ~Camera(); + + bool initialize(); + bool open(); + void close(); + bool startCapture(); + void stopCapture(); + bool captureFrame(); + +private: + VmbHandle_t cameraHandle; +}; + +Camera::Camera() : cameraHandle(nullptr) {} + +Camera::~Camera() { + close(); +} + +bool Camera::initialize() { + return VmbErrorSuccess == VmbStartup(); +} + +bool Camera::open() { + VmbError_t err; + + VmbCameraInfo_t* pCameraList = nullptr; + VmbUint32_t nCount = 0; + + err = VmbCamerasList(nullptr, 0, &nCount, sizeof(VmbCameraInfo_t)); + if (err != VmbErrorSuccess || nCount == 0) { + cout << "No cameras found or error listing cameras" << endl; + return false; + } + + pCameraList = new VmbCameraInfo_t[nCount]; + err = VmbCamerasList(pCameraList, nCount, &nCount, sizeof(VmbCameraInfo_t)); + if (err != VmbErrorSuccess) { + cout << "Error retrieving camera list" << endl; + delete[] pCameraList; + return false; + } + + if (nCount == 0) { + cout << "No cameras found" << endl; + delete[] pCameraList; + return false; + } + + err = VmbCameraOpen(pCameraList[0].cameraIdString, VmbAccessModeFull, &cameraHandle); + delete[] pCameraList; + + return err == VmbErrorSuccess; +} + +void Camera::close() { + if (cameraHandle != nullptr) { + VmbCameraClose(cameraHandle); + cameraHandle = nullptr; + } +} + +bool Camera::startCapture() { + return VmbErrorSuccess == VmbCaptureStart(cameraHandle); +} + +void Camera::stopCapture() { + VmbCaptureEnd(cameraHandle); +} + +bool Camera::captureFrame() { + VmbError_t err; + + VmbFrame_t frame; + err = VmbFrameAnnounce(cameraHandle, &frame, sizeof(VmbFrame_t)); + if (err != VmbErrorSuccess) { + cout << "Error announcing frame" << endl; + return false; + } + + err = VmbCaptureFrameQueue(cameraHandle, &frame, nullptr); + if (err != VmbErrorSuccess) { + cout << "Error queuing frame" << endl; + return false; + } + + err = VmbCaptureFrameWait(cameraHandle, &frame, VMB_INFINITE); + if (err != VmbErrorSuccess) { + cout << "Error waiting for frame" << endl; + return false; + } + + // Get timestamp + VmbUint64_t timestamp; + err = VmbFrameGetTimestamp(cameraHandle, frame, ×tamp); + if (err == VmbErrorSuccess) { + auto duration = duration_cast<milliseconds>(nanoseconds(timestamp)); + cout << "Frame captured at timestamp: " << duration.count() << "ms" << endl; + } + + err = VmbFrameRevoke(cameraHandle, &frame); + if (err != VmbErrorSuccess) { + cout << "Error revoking frame" << endl; + return false; + } + + return true; +} + +int main() { + Camera camera; + + if (!camera.initialize()) { + cout << "Failed to initialize Vimba" << endl; + return -1; + } + + if (!camera.open()) { + cout << "Failed to open camera" << endl; + return -1; + } + + if (!camera.startCapture()) { + cout << "Failed to start capture" << endl; + return -1; + } + + // Capture frames and perform processing + + // For demonstration purposes, let's capture 10 frames + for (int i = 0; i < 10; ++i) { + if (!camera.captureFrame()) { + cout << "Error capturing frame" << endl; + break; + } + // Add your processing logic here + } + + camera.stopCapture(); + camera.close(); + + VmbShutdown(); + + return 0; +} + +############################### +#include <QCoreApplication> +#include <QDebug> +#include <QString> +#include <QDateTime> +#include <QThread> +#include <VimbaC/Include/VimbaC.h> +#include <opencv2/opencv.hpp> + +class VimbaCamera : public QObject { + Q_OBJECT + +public: + VimbaCamera(QObject *parent = nullptr); + ~VimbaCamera(); + + bool initialize(); + bool open(); + void close(); + bool startCapture(); + void stopCapture(); + bool captureFrame(); + +signals: + void frameCaptured(const QString ×tamp, const cv::Mat &image); + +private: + VmbHandle_t cameraHandle; + VmbFrame_t frame; + // Add other camera-related members here +}; + +VimbaCamera::VimbaCamera(QObject *parent) : QObject(parent), cameraHandle(nullptr) {} + +VimbaCamera::~VimbaCamera() { + close(); +} + +bool VimbaCamera::initialize() { + return VmbErrorSuccess == VmbStartup(); +} + +bool VimbaCamera::open() { + VmbError_t err; + + // Add code to list and open the Vimba camera + // ... + + return err == VmbErrorSuccess; +} + +void VimbaCamera::close() { + if (cameraHandle != nullptr) { + // Add code to close the Vimba camera + // ... + cameraHandle = nullptr; + } +} + +bool VimbaCamera::startCapture() { + VmbError_t err; + + // Add code to configure camera settings for capturing + // ... + + // Announce the frame + err = VmbFrameAnnounce(cameraHandle, &frame, sizeof(VmbFrame_t)); + if (err != VmbErrorSuccess) { + qDebug() << "Error announcing frame"; + return false; + } + + // Add code to start capturing frames using Vimba API + // ... + + return true; +} + +void VimbaCamera::stopCapture() { + // Add code to stop capturing frames using Vimba API + // ... + + // Revoke the frame + VmbError_t err = VmbFrameRevoke(cameraHandle, &frame); + if (err != VmbErrorSuccess) { + qDebug() << "Error revoking frame"; + } +} + +bool VimbaCamera::captureFrame() { + VmbError_t err; + + // Add code to capture a frame with timestamp using Vimba API + // ... + + err = VmbCaptureFrameWait(cameraHandle, &frame, VMB_INFINITE); + if (err != VmbErrorSuccess) { + qDebug() << "Error waiting for frame"; + return false; + } + + // Get timestamp + VmbUint64_t timestamp; + err = VmbFrameGetTimestamp(cameraHandle, frame, ×tamp); + if (err == VmbErrorSuccess) { + auto duration = QDateTime::fromMSecsSinceEpoch(timestamp / 1000000); // Convert microseconds to milliseconds + qDebug() << "Frame captured at timestamp:" << duration.toString("yyyy-MM-dd hh:mm:ss.zzz"); + + // Convert the frame to a QImage and emit the signal + cv::Mat image(frame.height, frame.width, CV_8UC1, frame.buffer); + emit frameCaptured(duration.toString("yyyy-MM-dd_hhmmsszzz"), image.clone()); + } + + // Revoke the frame + err = VmbFrameRevoke(cameraHandle, &frame); + if (err != VmbErrorSuccess) { + qDebug() << "Error revoking frame"; + return false; + } + + return true; +} + +class CameraThread : public QThread { + Q_OBJECT + +public: + CameraThread(int cameraIndex, QObject *parent = nullptr) : QThread(parent), cameraIndex(cameraIndex) {} + +protected: + void run() override { + VimbaCamera camera; + connect(&camera, &VimbaCamera::frameCaptured, this, &CameraThread::handleFrameCaptured); + + if (!camera.initialize()) { + qDebug() << "Camera" << cameraIndex << "Failed to initialize Vimba"; + return; + } + + if (!camera.open()) { + qDebug() << "Camera" << cameraIndex << "Failed to open Vimba camera"; + return; + } + + if (!camera.startCapture()) { + qDebug() << "Camera" << cameraIndex << "Failed to start capturing frames"; + return; + } + + exec(); // Start the thread event loop + } + +private: + int cameraIndex; + +private slots: + void handleFrameCaptured(const QString ×tamp, const cv::Mat &image) { + // Handle the captured frame (e.g., save as JPEG) + QString filename = "camera" + QString::number(cameraIndex) + "_" + timestamp + ".jpg"; + cv::imwrite(filename.toStdString(), image); + qDebug() << "Camera" << cameraIndex << "Frame saved as:" << filename; + } +}; + +int main(int argc, char *argv[]) { + QCoreApplication a(argc, argv); + + // For demonstration purposes, create two camera threads + CameraThread cameraThread1(1); + CameraThread cameraThread2(2); + + // Start the camera threads + cameraThread1.start(); + cameraThread2.start(); + + // Wait for the threads to finish (this won't block the main thread event loop) + cameraThread1.wait(); + cameraThread2.wait(); + + return a.exec(); +} diff --git a/dox/timeplan-milestones.ods b/dox/timeplan-milestones.ods deleted file mode 100644 index af243d44fd0f261616d34b706e7bf70aa9c71c3c..0000000000000000000000000000000000000000 Binary files a/dox/timeplan-milestones.ods and /dev/null differ diff --git a/dox/timeplan_milestones.ods b/dox/timeplan_milestones.ods new file mode 100644 index 0000000000000000000000000000000000000000..79c6e203e4c5bcd897cb17c9483ee24fba1b5326 Binary files /dev/null and b/dox/timeplan_milestones.ods differ diff --git a/dox/todo_ct b/dox/todo_ct index 2c62887235dce59e97a23e1a1d69a4bc2b8a2893..e4dd6d1286692374d49e9b27171158c23dd8f033 100644 --- a/dox/todo_ct +++ b/dox/todo_ct @@ -8,48 +8,24 @@ CAMTRON PROCESSING PIPELINE ########################### "tackle long-term complex projects from beginning to end" -- â²ï¸ -- ðŸ—£ï¸ sebastian hostname-fix IP -- â€¼ï¸ cam works with VM? - read docu, write alliedvision - -- if yes. - test (VV) - set hostname (for fixip) - -- if no - - communicate w sebastian 1rst. - - communicate w uli -- â€¼ï¸ HPC. store some data 2018/2019 + vids. delete rest. write HPC guy -- â€¼ï¸ mv big ct-data to hdd -- use copilot more efficiently - - read Tuts, configure - - - B) recorder - camera produces frames and timestamps ########################### - (depends on cam in A)!!! - - use new api VimbaX - - read manual (c++ / vimba) -============================ + - ðŸ—£ï¸ sebastian hostname-fix IP -> â€¼ï¸ cam works with VM? - wait and detect cams - - â€¼ï¸ produce frames & timestamps + - â€¼ï¸ produce frames & timestamps & save as jpg + - put cams in own thread ============================ CORE - list cameras - test: core::listCams worx with multiple cams? - - - store/load cam settings + - store/load cam and app settings (opencv or vimba or QT) + - cam mappings (IP/MAC/ID) + - out_dir - calibrate - - see ada - HPC - CALI SW + - see opencv tut + code/bash cali example + - ada-HPC-CALISW - record - stop recording - - consider using app settings in a json-file / QSettings - - cam mappings (IP/MAC/ID) - - out_dir - - CONSOLE - - print: convert '\n' to linebreaks - - =============================== - get pix, using VV and recorder @@ -70,13 +46,12 @@ B) recorder - camera produces frames and timestamps A) ########################### - test vm, else buy ws! - - !! light + - â€¼ï¸ light - 2*LEDs: 1*day + 1*night - find ecolux hw (Boxes, DMX per unit, DMX splitter/controller) - - !! arenas + - â€¼ï¸ ðŸ—£ï¸ arenas - @laura asks 3D-Printer - Acrylzylinder in 2 teile gesaegt. - - floor ? - - gips+color+lack.. + - floor: find big white paperrolle in BUG/Storage C) background subtraction @@ -142,6 +117,11 @@ ctb Done ####################### +- use new api VimbaX +- read manual (c++ / vimba) +- write alliedvision (MTU) +- HPC. store some data 2018/2019 + vids. delete rest. write HPC guy +- use copilot more efficiently -> read Tuts, configure -> see ai - print and printlist() - integrate versionstring in new arch - mark current cam [*] <-- selected. others []