Files

112 lines
3.7 KiB
C++

//=============================================================================
// fc2view — minimal live viewer for Point Grey / FLIR FlyCapture2 cameras.
//
// The vendor GUI (FlyCap2) can't run on Ubuntu 24.04 (dead GTK2 deps), so
// this is a small native replacement built on OpenCV. It connects to the
// first camera on the bus, streams frames into a window, and lets you save
// snapshots.
//
// Keys: q or Esc quit
// s save a snapshot (PNG, native bit depth) to $PWD
//
// Build: g++ fc2view.cpp -I/usr/include/flycapture \
// $(pkg-config --cflags --libs opencv4) -lflycapture -o fc2view
//=============================================================================
#include "FlyCapture2.h"
#include <opencv2/opencv.hpp>
#include <ctime>
#include <iomanip>
#include <iostream>
#include <sstream>
using namespace FlyCapture2;
static void printError(const Error &e) { e.PrintErrorTrace(); }
// Timestamped filename like fc2-<serial>-20260929-142530.png
static std::string snapshotName(unsigned int serial)
{
std::time_t t = std::time(nullptr);
std::tm tm = *std::localtime(&t);
std::ostringstream s;
s << "fc2-" << serial << "-"
<< std::put_time(&tm, "%Y%m%d-%H%M%S") << ".png";
return s.str();
}
int main()
{
BusManager busMgr;
unsigned int numCameras = 0;
Error error = busMgr.GetNumOfCameras(&numCameras);
if (error != PGRERROR_OK) { printError(error); return 1; }
if (numCameras == 0)
{
std::cerr << "No FlyCapture2 cameras detected. Check `lsusb` for "
"1e10:xxxx and your 'flirimaging' group membership.\n";
return 1;
}
PGRGuid guid;
error = busMgr.GetCameraFromIndex(0, &guid);
if (error != PGRERROR_OK) { printError(error); return 1; }
Camera cam;
error = cam.Connect(&guid);
if (error != PGRERROR_OK) { printError(error); return 1; }
CameraInfo camInfo;
if (cam.GetCameraInfo(&camInfo) == PGRERROR_OK)
{
std::cout << "Connected: " << camInfo.modelName
<< " serial " << camInfo.serialNumber
<< " (" << camInfo.sensorResolution << ")\n";
}
error = cam.StartCapture();
if (error != PGRERROR_OK) { printError(error); cam.Disconnect(); return 1; }
const std::string win = "fc2view";
cv::namedWindow(win, cv::WINDOW_NORMAL);
std::cout << "Streaming. Keys: 'q'/Esc quit, 's' save snapshot.\n";
Image rawImage, bgrImage;
while (true)
{
error = cam.RetrieveBuffer(&rawImage);
if (error != PGRERROR_OK) { printError(error); continue; }
// Convert whatever the sensor delivers (mono, Bayer, ...) to 8-bit BGR
// so it maps straight onto an OpenCV CV_8UC3 Mat with no reordering.
error = rawImage.Convert(PIXEL_FORMAT_BGR, &bgrImage);
if (error != PGRERROR_OK) { printError(error); continue; }
cv::Mat frame(bgrImage.GetRows(), bgrImage.GetCols(), CV_8UC3,
bgrImage.GetData(), bgrImage.GetStride());
if (frame.empty()) continue;
cv::imshow(win, frame);
int key = cv::waitKey(1) & 0xFF;
if (key == 'q' || key == 27) break; // q or Esc
if (key == 's')
{
// Save the raw frame so native bit depth (e.g. Mono16 on a SWIR
// sensor) is preserved, not the 8-bit display copy.
std::string name = snapshotName(camInfo.serialNumber);
PNGOption png;
if (rawImage.Save(name.c_str(), &png) == PGRERROR_OK)
std::cout << "Saved " << name << "\n";
else
std::cerr << "Failed to save " << name << "\n";
}
}
cam.StopCapture();
cam.Disconnect();
cv::destroyAllWindows();
return 0;
}