Inital commit
This commit is contained in:
33
CMakeLists.txt
Normal file
33
CMakeLists.txt
Normal file
@ -0,0 +1,33 @@
|
||||
cmake_minimum_required(VERSION 3.6)
|
||||
|
||||
project(uvoscam)
|
||||
|
||||
set(SRC_FILES uvoscam.cpp)
|
||||
|
||||
find_package(PkgConfig REQUIRED)
|
||||
find_package(OpenCV REQUIRED)
|
||||
pkg_check_modules(GLIB REQUIRED glib-2.0)
|
||||
pkg_check_modules(ARAVIS REQUIRED aravis-0.8)
|
||||
|
||||
add_library(${PROJECT_NAME} SHARED ${SRC_FILES})
|
||||
target_link_libraries( ${PROJECT_NAME} ${GLIB_LDFLAGS} ${ARAVIS_LDFLAGS} ${OpenCV_LIBS} -pthread)
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE ${GLIB_INCLUDE_DIRS} ${ARAVIS_INCLUDE_DIRS} ${OpenCV_INCLUDE_DIRS})
|
||||
add_definitions("-std=c++17 -Wall -O2")
|
||||
install(TARGETS ${PROJECT_NAME} DESTINATION lib)
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -s")
|
||||
|
||||
link_directories(${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
add_executable(${PROJECT_NAME}_cli main.cpp)
|
||||
add_dependencies(${PROJECT_NAME}_cli ${PROJECT_NAME})
|
||||
target_include_directories(${PROJECT_NAME}_cli PRIVATE ${ARAVIS_INCLUDE_DIRS} ${OpenCV_INCLUDE_DIRS})
|
||||
target_link_libraries( ${PROJECT_NAME}_cli -l${PROJECT_NAME} ${OpenCV_LIBS})
|
||||
target_link_libraries( ${PROJECT_NAME}_cli)
|
||||
add_definitions("-std=c++17 -Wall -O2")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -s")
|
||||
|
||||
|
||||
set(CMAKE_INSTALL_PREFIX "/usr")
|
||||
install(TARGETS ${PROJECT_NAME}_cli RUNTIME DESTINATION bin)
|
||||
install(TARGETS ${PROJECT_NAME} DESTINATION lib)
|
||||
install(FILES ./uvoscam.h DESTINATION include)
|
95
log.h
Normal file
95
log.h
Normal file
@ -0,0 +1,95 @@
|
||||
/**
|
||||
* Lubricant Detecter
|
||||
* Copyright (C) 2021 Carl Klemm
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 3 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
class Log
|
||||
{
|
||||
public:
|
||||
|
||||
enum Level
|
||||
{
|
||||
DEBUG,
|
||||
INFO,
|
||||
WARN,
|
||||
ERROR
|
||||
};
|
||||
|
||||
private:
|
||||
bool opened = false;
|
||||
Level msglevel = DEBUG;
|
||||
|
||||
inline std::string getLabel(Level level)
|
||||
{
|
||||
std::string label;
|
||||
switch(level)
|
||||
{
|
||||
case DEBUG:
|
||||
label = "DEBUG";
|
||||
break;
|
||||
case INFO:
|
||||
label = "INFO ";
|
||||
break;
|
||||
case WARN:
|
||||
label = "WARN ";
|
||||
break;
|
||||
case ERROR:
|
||||
label = "ERROR";
|
||||
break;
|
||||
}
|
||||
return label;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
|
||||
inline static bool headers = false;
|
||||
inline static Level level = WARN;
|
||||
|
||||
Log() {}
|
||||
Log(Level type)
|
||||
{
|
||||
msglevel = type;
|
||||
if(headers)
|
||||
{
|
||||
operator << ("["+getLabel(type)+"]");
|
||||
}
|
||||
}
|
||||
|
||||
~Log()
|
||||
{
|
||||
if(opened)
|
||||
{
|
||||
std::cout<<'\n';
|
||||
}
|
||||
opened = false;
|
||||
}
|
||||
|
||||
template<class T> Log &operator<<(const T &msg)
|
||||
{
|
||||
if(msglevel >= level)
|
||||
{
|
||||
std::cout<<msg;
|
||||
opened = true;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
};
|
140
main.cpp
Normal file
140
main.cpp
Normal file
@ -0,0 +1,140 @@
|
||||
/**
|
||||
* Cam
|
||||
* Copyright (C) 2021 Carl Klemm
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 3 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <math.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <opencv2/imgcodecs.hpp>
|
||||
|
||||
#include "log.h"
|
||||
#include "uvoscam.h"
|
||||
|
||||
#define VERSION "0.1"
|
||||
|
||||
using namespace cam;
|
||||
|
||||
static std::string filename;
|
||||
|
||||
void listDevices()
|
||||
{
|
||||
std::vector<Camera::Description> cameras = Camera::getAvailableCameras();
|
||||
size_t i = 0;
|
||||
for(auto camera : cameras)
|
||||
std::cout<<i++<<": "<<camera.id<<' '<<camera.model<<' '<<camera.vendor<<'\n';
|
||||
}
|
||||
|
||||
void help()
|
||||
{
|
||||
std::cout<<"Avaiable commands:\n"
|
||||
<<"help Displays this message\n"
|
||||
<<"list Lists cameras found\n"
|
||||
<<"open [name] Open camera with string name\n"
|
||||
<<"close Close camera \n"
|
||||
<<"capture [file] Take an image and save it to file\n"
|
||||
<<"exit Quit program\n";
|
||||
}
|
||||
|
||||
void callback(cv::Mat data)
|
||||
{
|
||||
Log(Log::INFO)<<"Saveing image";
|
||||
cv::imwrite("./testimg.png", data);
|
||||
}
|
||||
|
||||
std::vector<std::string> tokenize(const std::string& in, char delim = ' ')
|
||||
{
|
||||
std::vector<std::string> vect;
|
||||
std::stringstream ss(in);
|
||||
|
||||
for(std::string token; std::getline(ss, token, delim);)
|
||||
vect.push_back(token);
|
||||
return vect;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
Camera camera(callback);
|
||||
|
||||
Log::level = Log::DEBUG;
|
||||
|
||||
Log(Log::INFO)<<"UVOS Camera capture program "<<VERSION;
|
||||
|
||||
while(true)
|
||||
{
|
||||
std::cout<<"> ";
|
||||
std::string line;
|
||||
std::getline(std::cin, line);
|
||||
std::vector<std::string> tokens = tokenize(line);
|
||||
|
||||
int ret = -1;
|
||||
|
||||
if(!tokens.empty())
|
||||
{
|
||||
if(tokens[0].find("help") != std::string::npos)
|
||||
help();
|
||||
else if(tokens[0].find("exit") != std::string::npos || tokens[0].find("quit") != std::string::npos)
|
||||
break;
|
||||
else if(tokens[0].find("list") != std::string::npos)
|
||||
listDevices();
|
||||
else if(tokens[0].find("open") != std::string::npos)
|
||||
{
|
||||
if(tokens.size() > 1)
|
||||
{
|
||||
ret = -1;
|
||||
size_t index = std::stoul(tokens[1]);
|
||||
if(index < Camera::getAvailableCameras().size())
|
||||
{
|
||||
camera.openCamera(index);
|
||||
if(camera.isOpen())
|
||||
{
|
||||
ret = 0;
|
||||
camera.setAcquisitionMode(Camera::MODE_SINGLE);
|
||||
camera.setBayerMode(Camera::BAYER_GREEN);
|
||||
camera.setTriggerMode(Camera::TRIGGER_SOFTWARE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout<<"Index out of range\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(tokens[0].find("capture") != std::string::npos)
|
||||
{
|
||||
if(tokens.size() > 1)
|
||||
{
|
||||
ret = -1;
|
||||
if(camera.isOpen())
|
||||
{
|
||||
filename = tokens[1] + ".png";
|
||||
camera.startAcquisition();
|
||||
camera.trigger();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::cout<<(ret == 0 ? "SUCESS\n" : "FAILURE\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
453
uvoscam.cpp
Normal file
453
uvoscam.cpp
Normal file
@ -0,0 +1,453 @@
|
||||
/**
|
||||
* uvoscam
|
||||
* Copyright (C) 2021 Carl Klemm
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 3 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "uvoscam.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
#include <atomic>
|
||||
#include <opencv2/imgproc.hpp>
|
||||
#include <string.h>
|
||||
|
||||
#include"log.h"
|
||||
|
||||
using namespace cam;
|
||||
|
||||
cv::Mat Camera::debayer(ArvBuffer *buffer)
|
||||
{
|
||||
size_t bufferSize;
|
||||
const void* data = arv_buffer_get_data(buffer, &bufferSize);
|
||||
const cv::Mat cvBuffer(static_cast<int>(height_), static_cast<int>(width_), CV_8U, const_cast<void*>(data), bufferSize/width_);
|
||||
cv::Mat cvResult;
|
||||
if(bayerMode == BAYER_DEBAYER)
|
||||
{
|
||||
cv::cvtColor(cvBuffer, cvResult, cv::COLOR_BayerBG2BGR);
|
||||
}
|
||||
else if(bayerMode == BAYER_RED || bayerMode == BAYER_BLUE)
|
||||
{
|
||||
cvBuffer.copyTo(cvResult);
|
||||
for(int y = 0; y < cvResult.rows; y+=2)
|
||||
{
|
||||
uint8_t* colH = cvResult.ptr<uint8_t>(y);
|
||||
uint8_t* colL = cvResult.ptr<uint8_t>(y+1);
|
||||
for(int x = 0; x < cvResult.cols; x+=2)
|
||||
{
|
||||
if(bayerMode == BAYER_BLUE)
|
||||
{
|
||||
colH[x+1] = colH[x];
|
||||
colL[x] = colH[x];
|
||||
colL[x+1] = colH[x];
|
||||
} else
|
||||
{
|
||||
colH[x] = colL[x+1];
|
||||
colH[x+1] = colL[x+1];
|
||||
colL[x] = colL[x+1];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(bayerMode == BAYER_GREEN)
|
||||
{
|
||||
cvBuffer.copyTo(cvResult);
|
||||
for(int y = 0; y < cvResult.rows; ++y)
|
||||
{
|
||||
uint8_t* col = cvResult.ptr<uint8_t>(y);
|
||||
for(int x = 0; x < cvResult.cols; x+=2)
|
||||
col[x+(y & 1)] = col[x+!(y & 1)];
|
||||
}
|
||||
}
|
||||
return cvResult;
|
||||
}
|
||||
|
||||
cv::Mat Camera::pack8(ArvBuffer *buffer, bool color)
|
||||
{
|
||||
size_t bufferSize;
|
||||
const void* data = arv_buffer_get_data(buffer, &bufferSize);
|
||||
Log(Log::DEBUG)<<"bufferSize "<<bufferSize;
|
||||
const cv::Mat cvBuffer(static_cast<int>(height_), static_cast<int>(width_), color ? CV_8UC3 : CV_8U,
|
||||
const_cast<void*>(data));
|
||||
cv::Mat cvResult;
|
||||
cvBuffer.copyTo(cvResult);
|
||||
return cvResult;
|
||||
}
|
||||
|
||||
cv::Mat Camera::pack16(ArvBuffer *buffer)
|
||||
{
|
||||
/*size_t bufferSize;
|
||||
void* data = arv_buffer_get_data(buffer, &bufferSize);
|
||||
cv::Mat cvBuffer(static_cast<int>(height_), static_cast<int>(width_), color ? CV_8SC3 : CV_8SC1, data, bufferSize/width_);*/
|
||||
cv::Mat cvResult;
|
||||
//cvBuffer.copyTo(cvResult);
|
||||
return cvResult;
|
||||
}
|
||||
|
||||
void Camera::decoderThreadFunc()
|
||||
{
|
||||
while(true)
|
||||
{
|
||||
std::unique_lock<std::mutex> bufferConditionMutexLock(bufferConditionMutex);
|
||||
bufferCondition.wait(bufferConditionMutexLock);
|
||||
if(join)
|
||||
return;
|
||||
decodeBufferMutex.lock();
|
||||
if(decodeBuffer != nullptr)
|
||||
{
|
||||
Log(Log::DEBUG)<<"decoderThreadFunc";
|
||||
if(format == ARV_PIXEL_FORMAT_BAYER_BG_8)
|
||||
{
|
||||
if(bayerMode != BAYER_PASSTHOUGH)
|
||||
callback_(debayer(decodeBuffer));
|
||||
else
|
||||
callback_(pack8(decodeBuffer, false));
|
||||
}
|
||||
else if(format == ARV_PIXEL_FORMAT_MONO_8)
|
||||
{
|
||||
callback_(pack8(decodeBuffer, false));
|
||||
}
|
||||
arv_stream_push_buffer(aStream_, decodeBuffer);
|
||||
}
|
||||
decodeBufferMutex.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
void Camera::aCallback(void* instance, ArvStreamCallbackType type, ArvBuffer *buffer)
|
||||
{
|
||||
Camera* instance_ = reinterpret_cast<Camera*>(instance);
|
||||
if(type == ARV_STREAM_CALLBACK_TYPE_BUFFER_DONE)
|
||||
{
|
||||
if(instance_->run)
|
||||
{
|
||||
gint inBuffers;
|
||||
gint outBuffers;
|
||||
arv_stream_get_n_buffers(instance_->aStream_, &inBuffers, &outBuffers);
|
||||
Log(Log::DEBUG)<<"ARV_STREAM_CALLBACK_TYPE_BUFFER_DONE in "<<inBuffers<<" out "<<outBuffers;
|
||||
std::unique_lock<std::mutex> decodeBufferMutexLock(instance_->decodeBufferMutex);
|
||||
instance_->decodeBuffer = arv_stream_pop_buffer(instance_->aStream_);
|
||||
instance_->bufferCondition.notify_all();
|
||||
if(instance_->aqmode == MODE_SINGLE)
|
||||
instance_->run = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
arv_stream_push_buffer(instance_->aStream_, arv_stream_pop_buffer(instance_->aStream_));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Camera::getSize(unsigned int* width, unsigned int* height)
|
||||
{
|
||||
*width = width_;
|
||||
*height = height_;
|
||||
}
|
||||
|
||||
bool Camera::chooseFormat()
|
||||
{
|
||||
guint count = 0;
|
||||
GError* error = nullptr;
|
||||
gint64* formats = arv_camera_dup_available_pixel_formats(aCamera_, &count, &error);
|
||||
if(error)
|
||||
return false;
|
||||
for(guint i = 0; i < count && format < 0; ++i)
|
||||
{
|
||||
switch(formats[i])
|
||||
{
|
||||
case ARV_PIXEL_FORMAT_MONO_8:
|
||||
case ARV_PIXEL_FORMAT_MONO_10:
|
||||
case ARV_PIXEL_FORMAT_MONO_12:
|
||||
case ARV_PIXEL_FORMAT_RGB_8_PLANAR:
|
||||
case ARV_PIXEL_FORMAT_BAYER_BG_8:
|
||||
format = formats[i];
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
arv_camera_set_pixel_format(aCamera_, format, &error);
|
||||
if(error)
|
||||
return false;
|
||||
|
||||
return format >= 0;
|
||||
}
|
||||
|
||||
bool Camera::setupCamera()
|
||||
{
|
||||
if(!chooseFormat())
|
||||
{
|
||||
Log(Log::ERROR)<<"Camera provides no supported pixel format";
|
||||
return false;
|
||||
}
|
||||
|
||||
GError* error = nullptr;
|
||||
gint ymin, ymax;
|
||||
arv_camera_get_height_bounds(aCamera_, &ymin, &ymax, &error);
|
||||
if(error)
|
||||
{
|
||||
Log(Log::ERROR)<<"Can not get hight bounds";
|
||||
return false;
|
||||
}
|
||||
|
||||
Log(Log::DEBUG)<<"Height bounds min: "<<ymin<<" max: "<<ymax;
|
||||
|
||||
gint xmin, xmax;
|
||||
arv_camera_get_width_bounds(aCamera_, &xmin, &xmax, &error);
|
||||
if(error)
|
||||
{
|
||||
Log(Log::ERROR)<<"Can not get width bounds";
|
||||
return false;
|
||||
}
|
||||
|
||||
Log(Log::DEBUG)<<"Width bounds min: "<<xmin<<" max: "<<xmax;
|
||||
|
||||
arv_camera_set_region(aCamera_, 0, 0, xmax, ymax, nullptr);
|
||||
|
||||
gint x, y, w, h;
|
||||
arv_camera_get_region(aCamera_, &x, &y, &w, &h, &error);
|
||||
if(error)
|
||||
{
|
||||
Log(Log::ERROR)<<"Can not get camera roi";
|
||||
return false;
|
||||
}
|
||||
|
||||
width_ = w;
|
||||
height_= h;
|
||||
|
||||
Log(Log::DEBUG)<<"Wdith "<<width_<<" Heigt "<<height_;
|
||||
|
||||
bool binning = arv_camera_is_binning_available(aCamera_, &error);
|
||||
if(error)
|
||||
{
|
||||
Log(Log::ERROR)<<"Can not get camera binning";
|
||||
return false;
|
||||
}
|
||||
if(binning)
|
||||
{
|
||||
arv_camera_set_binning(aCamera_, 1, 1, &error);
|
||||
if(error)
|
||||
{
|
||||
Log(Log::ERROR)<<"failed to set binning";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Log(Log::DEBUG)<<"Binning: "<<(binning ? "yes" : "no");
|
||||
|
||||
decoderThread = new std::thread([this](){decoderThreadFunc();});
|
||||
|
||||
Log(Log::DEBUG)<<"Using "<<arv_camera_get_pixel_format_as_string(aCamera_, nullptr)<<" as pixel format";
|
||||
|
||||
aStream_ = arv_camera_create_stream(aCamera_, aCallback, this, nullptr);
|
||||
if(!ARV_IS_STREAM(aStream_))
|
||||
{
|
||||
Log(Log::ERROR)<<"Can not create stream";
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t frameSize = arv_camera_get_payload(aCamera_, nullptr);
|
||||
for(size_t i = 0; i < BUFFER_DEPTH; ++i)
|
||||
{
|
||||
imageBuffers[i] = arv_buffer_new(frameSize, nullptr);
|
||||
arv_stream_push_buffer(aStream_, imageBuffers[i]);
|
||||
}
|
||||
setExposureAuto(false);
|
||||
setTriggerMode(TRIGGER_FREE);
|
||||
setAcquisitionMode(ARV_ACQUISITION_MODE_CONTINUOUS);
|
||||
setFrameRate(10);
|
||||
setExposureTime(100000);
|
||||
arv_camera_stop_acquisition(aCamera_, nullptr);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<Camera::Description> Camera::getAvailableCameras(bool update)
|
||||
{
|
||||
if(!scanned_ || update)
|
||||
{
|
||||
arv_update_device_list();
|
||||
scanned_ = true;
|
||||
}
|
||||
std::vector<Description> cameras;
|
||||
for(size_t i = 0; i < arv_get_n_devices(); ++i)
|
||||
{
|
||||
Description camera;
|
||||
camera.vendor = arv_get_device_vendor(i);
|
||||
camera.serial = arv_get_device_serial_nbr(i);
|
||||
camera.id = arv_get_device_id(i);
|
||||
camera.model = arv_get_device_model(i);
|
||||
cameras.push_back(camera);
|
||||
}
|
||||
return cameras;
|
||||
}
|
||||
|
||||
Camera::Camera(std::function<void(cv::Mat)> callback): join(false), run(false), callback_(callback)
|
||||
{
|
||||
arv_enable_interface("Fake");
|
||||
}
|
||||
|
||||
bool Camera::openCamera(const std::string& name)
|
||||
{
|
||||
aCamera_ = arv_camera_new(name.c_str(), nullptr);
|
||||
if(ARV_IS_CAMERA(aCamera_))
|
||||
setupCamera();
|
||||
else
|
||||
Log(Log::ERROR)<<"Can not create camera from name "<<name;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Camera::openCamera(const Camera::Description& camera)
|
||||
{
|
||||
aCamera_ = arv_camera_new(camera.id.c_str(), nullptr);
|
||||
if(ARV_IS_CAMERA(aCamera_))
|
||||
setupCamera();
|
||||
else
|
||||
Log(Log::ERROR)<<"Can not create camera";
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Camera::openCamera(const size_t index)
|
||||
{
|
||||
Description camera = getAvailableCameras().at(index);
|
||||
aCamera_ = arv_camera_new(camera.id.c_str(), nullptr);
|
||||
if(ARV_IS_CAMERA(aCamera_))
|
||||
setupCamera();
|
||||
else
|
||||
Log(Log::ERROR)<<"Can not create camera from index "<<index<<" name "<<camera.model;
|
||||
return true;
|
||||
}
|
||||
|
||||
Camera::~Camera()
|
||||
{
|
||||
join = true;
|
||||
if(decoderThread)
|
||||
{
|
||||
bufferCondition.notify_all();
|
||||
decoderThread->join();
|
||||
}
|
||||
if(ARV_IS_STREAM(aStream_))
|
||||
{
|
||||
stopAcquisition();
|
||||
g_object_unref(aStream_);
|
||||
}
|
||||
if(ARV_IS_CAMERA(aCamera_))
|
||||
g_object_unref(aCamera_);
|
||||
}
|
||||
|
||||
bool Camera::isOpen()
|
||||
{
|
||||
return ARV_IS_STREAM(aStream_) && ARV_IS_CAMERA(aCamera_);
|
||||
}
|
||||
|
||||
bool Camera::setAcquisitionMode(AquisitionMode mode)
|
||||
{
|
||||
GError* error = nullptr;
|
||||
aqmode = mode;
|
||||
arv_camera_set_acquisition_mode(aCamera_, mode == MODE_FREE ?
|
||||
ARV_ACQUISITION_MODE_CONTINUOUS : ARV_ACQUISITION_MODE_SINGLE_FRAME, &error);
|
||||
return !error;
|
||||
}
|
||||
|
||||
bool Camera::setExposureTime(uint64_t us)
|
||||
{
|
||||
GError* error = nullptr;
|
||||
arv_camera_set_exposure_time(aCamera_, static_cast<double>(us), &error);
|
||||
return !error;
|
||||
}
|
||||
|
||||
uint64_t Camera::getExposureTime()
|
||||
{
|
||||
GError* error = nullptr;
|
||||
double ret = arv_camera_get_exposure_time(aCamera_, &error);
|
||||
return !error ? static_cast<uint64_t>(ret) : 0;
|
||||
}
|
||||
|
||||
double Camera::getFrameRate()
|
||||
{
|
||||
GError* error = nullptr;
|
||||
double ret = arv_camera_get_frame_rate(aCamera_, &error);
|
||||
return !error ? ret : -1;
|
||||
}
|
||||
|
||||
bool Camera::setFrameRate(double rate)
|
||||
{
|
||||
GError* error = nullptr;
|
||||
arv_camera_set_frame_rate(aCamera_, rate, &error);
|
||||
return !error;
|
||||
}
|
||||
|
||||
int64_t Camera::getPixelFormat()
|
||||
{
|
||||
return static_cast<ArvPixelFormat>(format);
|
||||
}
|
||||
|
||||
bool Camera::setExposureAuto(bool enable)
|
||||
{
|
||||
if(!arv_camera_is_exposure_auto_available(aCamera_, nullptr))
|
||||
return false;
|
||||
|
||||
GError* error = nullptr;
|
||||
arv_camera_set_exposure_time(aCamera_, enable ? ARV_AUTO_CONTINUOUS : ARV_AUTO_OFF, &error);
|
||||
return !error;
|
||||
}
|
||||
|
||||
bool Camera::startAcquisition()
|
||||
{
|
||||
GError* error = nullptr;
|
||||
arv_camera_start_acquisition(aCamera_, &error);
|
||||
if(!error)
|
||||
run = true;
|
||||
return !error;
|
||||
}
|
||||
|
||||
bool Camera::stopAcquisition()
|
||||
{
|
||||
GError* error = nullptr;
|
||||
arv_camera_stop_acquisition(aCamera_, &error);
|
||||
if(!error)
|
||||
run = false;
|
||||
return !error;
|
||||
}
|
||||
|
||||
void Camera::setBayerMode(Camera::BayerMode mode)
|
||||
{
|
||||
bayerMode = mode;
|
||||
}
|
||||
|
||||
Camera::BayerMode Camera::getBayerMode()
|
||||
{
|
||||
return bayerMode;
|
||||
}
|
||||
|
||||
void Camera::setTriggerMode(Camera::TriggerMode mode)
|
||||
{
|
||||
switch(mode)
|
||||
{
|
||||
case TRIGGER_FREE:
|
||||
arv_camera_clear_triggers(aCamera_, nullptr);
|
||||
break;
|
||||
case TRIGGER_SOFTWARE:
|
||||
arv_camera_set_trigger(aCamera_, "Software", nullptr);
|
||||
break;
|
||||
case TRIGGER_HARDWARE:
|
||||
arv_camera_set_trigger(aCamera_, "Line1", nullptr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Camera::trigger()
|
||||
{
|
||||
arv_camera_software_trigger(aCamera_, nullptr);
|
||||
}
|
129
uvoscam.h
Normal file
129
uvoscam.h
Normal file
@ -0,0 +1,129 @@
|
||||
/**
|
||||
* uvoscam
|
||||
* Copyright (C) 2021 Carl Klemm
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 3 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <functional>
|
||||
#include <condition_variable>
|
||||
#include <stdint.h>
|
||||
#include <thread>
|
||||
#include <atomic>
|
||||
#include <opencv2/core/mat.hpp>
|
||||
#include <arv.h>
|
||||
|
||||
namespace cam
|
||||
{
|
||||
|
||||
class Camera
|
||||
{
|
||||
public:
|
||||
|
||||
struct Description
|
||||
{
|
||||
std::string vendor;
|
||||
std::string serial;
|
||||
std::string id;
|
||||
std::string model;
|
||||
};
|
||||
|
||||
static constexpr size_t BUFFER_DEPTH = 8;
|
||||
|
||||
typedef int TriggerMode;
|
||||
static constexpr TriggerMode TRIGGER_FREE = 0;
|
||||
static constexpr TriggerMode TRIGGER_SOFTWARE = 1;
|
||||
static constexpr TriggerMode TRIGGER_HARDWARE = 2;
|
||||
|
||||
typedef int BayerMode;
|
||||
static constexpr BayerMode BAYER_RED = 0;
|
||||
static constexpr BayerMode BAYER_GREEN = 1;
|
||||
static constexpr BayerMode BAYER_BLUE = 2;
|
||||
static constexpr BayerMode BAYER_PASSTHOUGH = 3;
|
||||
static constexpr BayerMode BAYER_DEBAYER = 4;
|
||||
|
||||
|
||||
typedef int AquisitionMode;
|
||||
static constexpr AquisitionMode MODE_FREE = 0;
|
||||
static constexpr AquisitionMode MODE_SINGLE = 1;
|
||||
|
||||
private:
|
||||
ArvStream* aStream_ = nullptr;
|
||||
ArvCamera* aCamera_ = nullptr;
|
||||
ArvInterface interface;
|
||||
|
||||
unsigned int width_;
|
||||
unsigned int height_;
|
||||
int64_t format = -1;
|
||||
inline static bool scanned_ = false;
|
||||
|
||||
ArvBuffer* imageBuffers[BUFFER_DEPTH] = {0};
|
||||
|
||||
BayerMode bayerMode = BAYER_DEBAYER;
|
||||
|
||||
ArvBuffer* decodeBuffer = nullptr;
|
||||
std::mutex decodeBufferMutex;
|
||||
std::condition_variable bufferCondition;
|
||||
std::mutex bufferConditionMutex;
|
||||
std::thread* decoderThread = nullptr;
|
||||
std::atomic_bool join;
|
||||
|
||||
std::atomic_bool run;
|
||||
|
||||
AquisitionMode aqmode = MODE_FREE;
|
||||
|
||||
static void aCallback(void* instance, ArvStreamCallbackType type, ArvBuffer *buffer);
|
||||
|
||||
void decoderThreadFunc();
|
||||
|
||||
std::function<void(cv::Mat)> callback_;
|
||||
|
||||
bool setupCamera();
|
||||
|
||||
bool chooseFormat();
|
||||
|
||||
cv::Mat debayer(ArvBuffer *buffer);
|
||||
cv::Mat pack8(ArvBuffer *buffer, bool color);
|
||||
cv::Mat pack16(ArvBuffer *buffer);
|
||||
|
||||
public:
|
||||
|
||||
static std::vector<Camera::Description> getAvailableCameras(bool update = false);
|
||||
|
||||
Camera(std::function<void(cv::Mat)> callback);
|
||||
bool openCamera(const std::string& name);
|
||||
bool openCamera(const Camera::Description& camera);
|
||||
bool openCamera(const size_t index);
|
||||
~Camera();
|
||||
bool isOpen();
|
||||
bool setAcquisitionMode(AquisitionMode mode);
|
||||
bool setExposureTime(uint64_t us);
|
||||
uint64_t getExposureTime();
|
||||
double getFrameRate();
|
||||
bool setFrameRate(double rate);
|
||||
int64_t getPixelFormat();
|
||||
bool setExposureAuto(bool enable);
|
||||
bool startAcquisition();
|
||||
bool stopAcquisition();
|
||||
void getSize(unsigned int* x, unsigned int* y);
|
||||
void setBayerMode(Camera::BayerMode mode);
|
||||
Camera::BayerMode getBayerMode();
|
||||
void setTriggerMode(Camera::TriggerMode mode);
|
||||
void trigger();
|
||||
};
|
||||
|
||||
}
|
Reference in New Issue
Block a user