uppermachine-tobacco/camera.cpp
Chenglei98 8ccab171db
Add files via upload
淮安部署版本
2022-09-17 10:52:03 +08:00

1174 lines
38 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* @file camera.cpp
* @author DingKun & ChengLei
* @date 2022.3.8
* @brief The file contains detailed implementation of class Camera
* @details
* <pre>The file contains detailed implementation of class Camera.
* Such as initialize camera, enum camera, start capture, callback function, etc.
* which refers to the hyperspectral camera(FX10e).</pre>
*/
#include "camera.h"
#include "unistd.h"
float file_explosure;
vector<int> mroi;
vector<int> valid;
int R;
int G;
int B;
Camera* camera;
RGB_Camera* rgb_camera;
float* send_buf = nullptr;
float* send_temp_buf = nullptr;
float* send_valid_buf = nullptr;
float* save_valid_buf = nullptr;
QSemaphore ready_to_send(0); //光谱图像信号量
QSemaphore ready_to_send_rgb(0); //rgb图像信号量
uint8_t* send_rgb_buf = nullptr;
//uint8_t* send_temp_rgb_buf = nullptr;
uint8_t* channel_b = nullptr;
uint8_t* channel_g = nullptr;
uint8_t* channel_r = nullptr;
uint8_t* temp_rgb = nullptr;
uint16_t* lines_buf = nullptr;
std::vector<cv::Mat> channel_rgb;
/*test for callback function, not used
int on_data_callback(uint8_t* buffer, uint64_t frame_size, uint64_t frame_number)
{
cout << ">>> frame_number: " << frame_number << " " << "frame_size: " << frame_size << endl;
cv::Mat mat(1000, 3840, CV_8UC1, buffer);
//cv::imwrite("./a.png", mat);
return 0;
}
*/
Camera::Camera(QObject *parent) : QObject(parent)
{
}
Camera::~Camera()
{
free_stream_buffers();
if( lStream != nullptr )
{
lStream->Close();
PvStream::Free(lStream);
cout << ">>> close and free lstream >>>" << endl;
}
if( lDevice != nullptr )
{
lDevice->Disconnect();
PvDevice::Free(lDevice);
cout << ">>> disconnect and free camera device >>>" << endl;
}
if( capture_thread != nullptr)
delete capture_thread;
delete [] send_buf;
delete [] send_temp_buf;
delete [] white_buf;
delete [] black_buf;
cout << "dkkkkkkkkkkkkkkk" << endl;
}
/**
* @details <pre>Steps to initialize the hyperspectral camera:
* 1. Enumerate and connect to the camera
* 2. Configure the camera parameters
* 3. Creates stream object
* 4. Configure stream for GigE Vision devices
* 5. Create stream buffers
* 6. Map the GenICam AcquisitionStart and AcquisitionStop commands
* 7. New object capture_thread
* 8. Allocate memory for every buffers
*/
int Camera::init_camera()
{
// 1.Enumerate the camera
int status = enum_connect_camera();
if(status != 0)
return -1;
// 2.Configure the camera parameters
status = config_camera();
if(status != 0)
return -2;
// get_camera_parameters();
// 3.Creates stream object
status = open_stream();
if(status != 0)
return -3;
// 4.Configure stream for GigE Vision devices
status = configure_stream();
if(status != 0)
return -4;
// 5.Create stream buffers
create_stream_buffers();
// Get device parameters need to control streaming
PvGenParameterArray *lDeviceParams = lDevice->GetParameters();
// 6.Map the GenICam AcquisitionStart and AcquisitionStop commands
lStart = dynamic_cast<PvGenCommand *>( lDeviceParams->Get( "AcquisitionStart" ) );
lStop = dynamic_cast<PvGenCommand *>( lDeviceParams->Get( "AcquisitionStop" ) );
// 7.New object capture_thread
capture_thread = new CaptureThread();
//获取波段数
PvGenInteger* lheight = parameter_array->GetInteger("Height");
lheight->GetValue(m_height);
single_frame_size = SPEC_WIDTH * m_height;
multi_frame_size = single_frame_size * SPEC_HEIGHT;
// 8.Allocate memory for every buffers
white_buf = new float[single_frame_size];
black_buf = new float[single_frame_size];
send_buf = new float[multi_frame_size];
send_temp_buf = new float[multi_frame_size];
send_valid_buf = new float[SPEC_WIDTH * valid.size() * SPEC_HEIGHT]; //此处m_height要改成valid
sum_mat_for_calibration = cv::Mat(m_height, SPEC_WIDTH, CV_32F, cv::Scalar(0));
eps = cv::Mat(m_height, SPEC_WIDTH, CV_32F, cv::Scalar(0.00000001)); ///<eps is setted to prevent division by 0
white_mat = cv::Mat(m_height, SPEC_WIDTH, CV_32F, cv::Scalar(0)); ///<white frame for calibration
black_mat = cv::Mat(m_height, SPEC_WIDTH, CV_32F, cv::Scalar(0)); ///<black frame for calibration
channel_r = new uint8_t[SPEC_WIDTH * SPEC_HEIGHT * 2];
channel_g = new uint8_t[SPEC_WIDTH * SPEC_HEIGHT * 2];
channel_b = new uint8_t[SPEC_WIDTH * SPEC_HEIGHT * 2];
temp_rgb = new uint8_t[SPEC_WIDTH * SPEC_HEIGHT * 2 * 3];
// padding_frame = new uint8_t[single_frame_size * 2];
// memset(padding_frame, 0, single_frame_size * 2);
return 0;
}
int Camera::enum_connect_camera()
{
PvResult lResult;
// Find all devices on the network.
lResult = lSystem.Find();
if ( !lResult.IsOK() )
{
cout << "*** PvSystem::Find Error: " << lResult.GetCodeString().GetAscii();
return -1;
}
// Go through all interfaces
uint32_t lInterfaceCount = lSystem.GetInterfaceCount();
for ( uint32_t x = 0; x < lInterfaceCount; x++ )
{
if(lLastDeviceInfo != nullptr)
break;
// Go through all the devices attached to the interface
uint32_t lDeviceCount = lSystem.GetInterface(x)->GetDeviceCount();
for ( uint32_t y = 0; y < lDeviceCount ; y++ )
{
lDeviceInfo = lSystem.GetInterface(x)->GetDeviceInfo( y );
cout << " Display ID: " << lDeviceInfo->GetDisplayID().GetAscii() << endl;
const PvDeviceInfoGEV* lDeviceInfoGEV = dynamic_cast<const PvDeviceInfoGEV*>( lDeviceInfo );
if ( lDeviceInfoGEV != nullptr ) // Is it a GigE Vision device?
{
// cout << " MAC Address: " << lDeviceInfoGEV->GetMACAddress().GetAscii() << endl;
// cout << " IP Address: " << lDeviceInfoGEV->GetIPAddress().GetAscii() << endl;
// cout << " Serial number: " << lDeviceInfoGEV->GetSerialNumber().GetAscii() << endl << endl;
if(!strcmp("70:f8:e7:b0:07:c4", lDeviceInfoGEV->GetMACAddress().GetAscii()))
{
lResult = PvDeviceGEV::SetIPConfiguration("70:f8:e7:b0:07:c4", "192.168.123.3", "255.255.255.0", "192.168.123.1");
while( !lResult.IsOK() ){
// cout << "set ip again" << endl;
lResult = PvDeviceGEV::SetIPConfiguration("70:f8:e7:b0:07:c4", "192.168.123.3", "255.255.255.0", "192.168.123.1");
}
cout << "set ip success" << endl;
lDeviceInfo = lSystem.GetInterface(x)->GetDeviceInfo(y);
lLastDeviceInfo = lDeviceInfo;
break;
}
else
{
// cout << "not this!" << endl;
continue;
}
}
}
}
// Connect to the last device found
if ( lLastDeviceInfo != nullptr )
{
// Creates and connects the device controller based on the selected device.
lDevice = PvDevice::CreateAndConnect( lLastDeviceInfo, &lResult );
if ( !lResult.IsOK() )
{
cout << "*** Unable to connect to " << lLastDeviceInfo->GetDisplayID().GetAscii() << endl;
if(lDevice != nullptr){
PvDevice::Free(lDevice);
lDevice = nullptr;
}
lLastDeviceInfo = nullptr;
return -1;
}
else
{
cout << ">>> Successfully connected to " << lLastDeviceInfo->GetDisplayID().GetAscii() << endl;
cout << endl;
// Load parameters of the camera
parameter_array = lDevice->GetParameters();
return 0;
}
}
else
{
cout << "*** No device found! ***" << endl;
return -2;
}
}
int Camera::open_stream()
{
PvResult lResult;
// Open stream to the GigE Vision or USB3 Vision device
// cout << ">>> Opening stream to device." << endl;
lStream = PvStream::CreateAndOpen( lLastDeviceInfo->GetConnectionID(), &lResult);
if ( (lStream == nullptr) || !lResult.IsOK() )
{
cout << "*** Unable to stream from " << lLastDeviceInfo->GetDisplayID().GetAscii() << ". ***" << endl;
PvStream::Free(lStream);
PvDevice::Free(lDevice);
return -1;
}
return 0;
}
int Camera::configure_stream()
{
// If this is a GigE Vision device, configure GigE Vision specific streaming parameters
PvDeviceGEV* lDeviceGEV = dynamic_cast<PvDeviceGEV *>( lDevice );
if ( lDeviceGEV != nullptr )
{
PvStreamGEV *lStreamGEV = static_cast<PvStreamGEV *>( lStream );
// Negotiate packet size
lDeviceGEV->NegotiatePacketSize();
// Configure device streaming destination
lDeviceGEV->SetStreamDestination( lStreamGEV->GetLocalIPAddress(), lStreamGEV->GetLocalPort() );
// cout << ">>> configure stream successfully!" << endl;
return 0;
}
else
{
cout << "*** configure stream failed! ***" << endl;
return -1;
}
}
void Camera::create_stream_buffers()
{
// Reading payload size from device
uint32_t lSize = lDevice->GetPayloadSize();
// Use BUFFER_COUNT or the maximum number of buffers, whichever is smaller
uint32_t lBufferCount = ( lStream->GetQueuedBufferMaximum() < BUFFER_COUNT ) ? lStream->GetQueuedBufferMaximum() : BUFFER_COUNT;
// Allocate buffers
for( uint32_t i=0; i<lBufferCount; i++ )
{
// Create new buffer object
PvBuffer *lBuffer = new PvBuffer;
// Have the new buffer object allocate payload memory
lBuffer->Alloc( static_cast<uint32_t>( lSize ) );
// Add to external list - used to eventually release the buffers
lbufferlist.push_back(lBuffer);
}
// cout << ">>> create stream buffers successfully" << endl;
}
void Camera::free_stream_buffers()
{
bufferlist::iterator iter = lbufferlist.begin();
while( iter != lbufferlist.end() )
{
delete *iter;
iter++;
}
// Clear the buffer list
lbufferlist.clear();
}
void Camera::set_MROI(const vector<int> &vec)
{
bool mroi_status = false;
parameter_array->SetBooleanValue("MROI_Enable", mroi_status);
int n = vec.size() / 2;
parameter_array->SetIntegerValue("MROI_Index", n);
parameter_array->SetIntegerValue("MROI_Y", 1081);
parameter_array->SetIntegerValue("MROI_H", 0);
//{100, 5, 300, 5}
for( int i=0, j=0; i<n; i++,j+=2 )
{
parameter_array->SetIntegerValue("MROI_Index", i);
parameter_array->SetIntegerValue("MROI_Y", vec[j]);
parameter_array->SetIntegerValue("MROI_H", vec[j+1]);
}
mroi_status = true;
parameter_array->SetBooleanValue("MROI_Enable", mroi_status);
}
int Camera::config_camera()
{
PvResult lResult;
//实际测试发现快men有时无法自动打开需要使用以下代码人为打开
lResult = parameter_array->SetIntegerValue("MotorShutter_PulseFwd", 100);
::sleep(1);
lResult = parameter_array->SetIntegerValue("MotorShutter_PulseRev", 100);
::sleep(1);
lResult = parameter_array->SetIntegerValue("MotorShutter_PulseFwd", 200);
::sleep(1);
lResult = parameter_array->SetIntegerValue("MotorShutter_PulseRev", 200);
//设置触发模式为 外触发线路Line0上升沿触发
lResult = parameter_array->SetEnumValue("TriggerMode", "On");
lResult = parameter_array->SetEnumValue("TriggerSource", "Line0");
//Set BinningVertical
lResult = parameter_array->SetIntegerValue("BinningVertical", 1);
if ( !lResult.IsOK() )
{
cout << "*** Unable to set <BinningVertical> *** " << endl;
return -1;
}
//设置数据格式为12位
lResult = parameter_array->SetEnumValue("PixelFormat", "Mono12");
if ( !lResult.IsOK() )
{
cout << "*** Unable to set <PixelFormat> *** " << endl;
return -1;
}
//Set gain
lResult = parameter_array->SetFloatValue("Gain", m_gain);
if ( !lResult.IsOK() )
{
cout << "*** Unable to set <Gain> *** " << endl;
return -1;
}
//Set MROI
set_MROI(mroi);
//Set ExposureTime
lResult = parameter_array->SetFloatValue("ExposureTime", file_explosure);
if ( !lResult.IsOK() )
{
cout << "*** Unable to set <ExposureTime> *** " << endl;
return -1;
}
return 0;
}
void Camera::get_camera_parameters()
{
PvResult lResult;
//Get BinningVertical
PvGenInteger* lbinningvertical = parameter_array->GetInteger("BinningVertical");
int64_t binning = 0;
lResult = lbinningvertical->GetValue(binning);
if( !lResult.IsOK() )
cout << "*** Unable to get <BinningVertical> *** " << endl;
else
cout <<">>> BinningVertical: " << binning << endl;
//Get Gain
PvGenFloat* lgain = parameter_array->GetFloat("Gain");
double gain = 0.0f;
lResult = lgain->GetValue(gain);
if( !lResult.IsOK() )
cout << "*** Unable to get <Gain> *** " << endl;
else
cout <<">>> Gain: " << gain << endl;
//Get Height
PvGenInteger* lheight = parameter_array->GetInteger("Height");
int64_t height = 0;
lResult = lheight->GetValue(height);
if( !lResult.IsOK() )
cout << "*** Unable to get <Height> *** " << endl;
else
cout <<">>> Height: " << height << endl;
//Get Width
PvGenInteger* lwidth = parameter_array->GetInteger("Width");
int64_t width = 0;
lResult = lwidth->GetValue(width);
if( !lResult.IsOK() )
cout << "*** Unable to get <Width> *** " << endl;
else
cout <<">>> Width: " << width << endl;
//Get AcquisitionFrameRate
PvGenFloat* lframerate = parameter_array->GetFloat("AcquisitionFrameRate");
double framerate = 0.0f;
lResult = lframerate->GetValue(framerate);
if( !lResult.IsOK() )
cout << "*** Unable to get <AcquisitionFrameRate> *** " << endl;
else
cout <<">>> AcquisitionFrameRate: " << framerate << endl;
//Get ExposureTime
PvGenFloat* lexposuretime = parameter_array->GetFloat("ExposureTime");
double exposuretime = 0.0f;
lResult = lexposuretime->GetValue(exposuretime);
if( !lResult.IsOK() )
cout << "*** Unable to get <ExposureTime> *** " << endl;
else
cout << ">>> ExposureTime: " << exposuretime << endl;
//查看触发模式
PvString mode;
PvGenEnum* ltriggermode = parameter_array->GetEnum("TriggerMode");
ltriggermode->GetValue(mode);
cout << ">>> TriggerMode: " << mode.GetAscii() << endl;
ltriggermode = parameter_array->GetEnum("TriggerSource");
ltriggermode->GetValue(mode);
cout << ">>> TriggerSource: " << mode.GetAscii() << endl;
cout << endl;
}
void Camera::start_acquisition()
{
// Queue all buffers in the stream
bufferlist::iterator iter = lbufferlist.begin();
while( iter != lbufferlist.end() )
{
lStream->QueueBuffer(*iter);
iter++;
}
cout << "queue buffer successfully..." << endl;
// Enable streaming and send the AcquisitionStart command
// cout << "Enabling streaming and sending AcquisitionStart command." << endl;
lDevice->StreamEnable();
lStart->Execute();
// start a new thread CaptureThread
capture_thread->stop_mutex.lock();
capture_thread->m_stop = false;
capture_thread->stop_mutex.unlock();
capture_thread->start();
}
void Camera::stop_acquisition()
{
//线程停止!
capture_thread->exit_thread();
capture_thread->wait();
if(capture_thread->isFinished())
{
cout << ">>> capture thread stopped successfully" << endl;
}
}
void Camera::register_callback_calibration()
{
register_data_callback(onDataCallback_calibration);
}
void Camera::register_callback_acquisition()
{
register_data_callback(onDataCallback_acquisition);
}
int Camera::init_calibration_load()
{
FILE* fp = fopen("./white", "rb");
fread(white_buf, 4, single_frame_size, fp);
fclose(fp);
fp = fopen("./black", "rb");
fread(black_buf, 4, single_frame_size, fp);
fclose(fp);
white_mat = cv::Mat(m_height, SPEC_WIDTH, CV_32F, white_buf);
black_mat = cv::Mat(m_height, SPEC_WIDTH, CV_32F, black_buf);
cout << ">>> load calibration init success! >>> " << endl;
// emit camera->send_calibration_finished_message();
return 0;
}
void Camera::load_calibration()
{
cout << ">>> loading calibration file......" << endl;
FILE* fp = fopen("./white", "rb");
fread(white_buf, 4, single_frame_size, fp);
fclose(fp);
cout << ">>> white file loaded successfully! >>>" << endl;
fp = fopen("./black", "rb");
fread(black_buf, 4, single_frame_size, fp);
fclose(fp);
cout << ">>> black file loaded successfully! >>>" << endl;
white_mat = cv::Mat(m_height, SPEC_WIDTH, CV_32F, white_buf);
black_mat = cv::Mat(m_height, SPEC_WIDTH, CV_32F, black_buf);
cout << ">>> load calibration finished! >>> " << endl;
emit camera->send_calibration_finished_message();
}
//definition of calibration callback function 校正回调函数
static uint16_t calibration_frame_count = 0;
int onDataCallback_calibration(uint8_t *buffer, uint64_t frame_size, uint64_t frame_number)
{
//采集黑白帧
cout << ">>> acquisition number: " << calibration_frame_count << endl;
if( camera->capture_black_flag || camera->capture_white_flag )
{
if( calibration_frame_count != CALIBRATION_FRAMES )
{
cv::Mat temp = cv::Mat(camera->m_height, SPEC_WIDTH, CV_16U, buffer);
temp.convertTo(temp, CV_32F);
camera->sum_mat_for_calibration += temp;
calibration_frame_count++;
return 0;
}
else
{
camera->stop_acquisition();
if( camera->capture_black_flag )
{
camera->capture_black_flag = false;
camera->black_mat = camera->sum_mat_for_calibration / CALIBRATION_FRAMES;
FILE* fp = fopen("./black", "wb");
fwrite(camera->black_mat.data, camera->m_height*SPEC_WIDTH*4, 1, fp);
fclose(fp);
cout << ">>> black frame acquisition OK! >>>" << endl;
camera->sum_mat_for_calibration = cv::Mat(camera->m_height, SPEC_WIDTH, CV_32F, cv::Scalar(0)); //clear sum mat
}
else if( camera->capture_white_flag )
{
camera->capture_white_flag = false;
camera->white_mat = camera->sum_mat_for_calibration / CALIBRATION_FRAMES;
FILE* fp = fopen("./white", "wb");
fwrite(camera->white_mat.data, camera->m_height*SPEC_WIDTH*4, 1, fp);
fclose(fp);
cout << ">>> white frame acquisition OK! >>>" << endl;
camera->sum_mat_for_calibration = cv::Mat(camera->m_height, SPEC_WIDTH, CV_32F, cv::Scalar(0)); //clear sum mat
}
calibration_frame_count = 0;
camera->unregister_data_callback();
return 0;
}
}
return 0;
}
//definition of acquisition callback function 采集回调函数
static uint16_t send_show_frame_count = 0;
/**
* @brief Acquisition callback function
* @param buffer
* @param frame_size
* @param frame_number
* @return
* @details splice 256 buffers into a whole image,
*/
int onDataCallback_acquisition(uint8_t *buffer, uint64_t frame_size, uint64_t frame_number)
{
// if(frame_number % REALHEIGHT == 0)
// cout << ">>> " << frame_number << endl;
memcpy(channel_r + send_show_frame_count * SPEC_WIDTH * 2, buffer+2048 * R, SPEC_WIDTH * 2);
memcpy(channel_g + send_show_frame_count * SPEC_WIDTH * 2, buffer+2048 * G, SPEC_WIDTH * 2);
memcpy(channel_b + send_show_frame_count * SPEC_WIDTH * 2, buffer+2048 * B, SPEC_WIDTH * 2);
// 校正后图片拼接
cv::Mat img = cv::Mat(camera->m_height, SPEC_WIDTH, CV_16U, buffer);
img.convertTo(img, CV_32F);
// if(frame_size == 88)
// {
// img = camera->black_mat;
// }
// calibrate operation 校正操作
cv::Mat calibrated_img = (img - camera->black_mat) / (camera->white_mat - camera->black_mat + camera->eps);
memcpy( (send_temp_buf + send_show_frame_count * camera->single_frame_size), calibrated_img.data, camera->single_frame_size * 4);
send_show_frame_count++;
if( send_show_frame_count == SPEC_HEIGHT )
{
send_show_frame_count = 0;
channel_rgb.emplace_back(cv::Mat(SPEC_HEIGHT, SPEC_WIDTH, CV_16UC1, channel_r));
channel_rgb.emplace_back(cv::Mat(SPEC_HEIGHT, SPEC_WIDTH, CV_16UC1, channel_g));
channel_rgb.emplace_back(cv::Mat(SPEC_HEIGHT, SPEC_WIDTH, CV_16UC1, channel_b));
cv::Mat temp;
cv::merge(channel_rgb, temp);
memcpy(temp_rgb, temp.data, SPEC_HEIGHT * SPEC_WIDTH * 6);
channel_rgb.clear();
memcpy(send_buf, send_temp_buf, camera->multi_frame_size * 4);
//release semaphore
ready_to_send.release();
//emit to ui
camera->send_data_to_ui(temp_rgb);
}
return 0;
}
/*----------CaptureThread 采集线程----------*/
CaptureThread::CaptureThread(QObject *parent) : QThread(parent), m_stop(false)
{}
void CaptureThread::run()
{
/*----将线程绑定至8号cpu提高线程效率----*/
cpu_set_t get;
cpu_set_t mask;
int num = sysconf(_SC_NPROCESSORS_CONF);
// pthread_t thread_id = pthread_self();
// cout << thread_id << endl;
CPU_ZERO(&mask);
CPU_SET(0, &mask);
sched_setaffinity(0, sizeof(mask), &mask);
CPU_ZERO(&get);
sched_getaffinity(0, sizeof(get), &get);
for(int i=0; i<num; ++i)
{
if(CPU_ISSET(i, &get))
cout << "running on " << i << endl;
}
/*-----------------------------------*/
while(1)
{
stop_mutex.lock();
if(m_stop)
{
stop_mutex.unlock();
send_show_frame_count = 0;
// Tell the device to stop sending images.
camera->lStop->Execute();
// Disable streaming on the device
camera->lDevice->StreamDisable();
// Abort all buffers from the stream and dequeue
camera->lStream->AbortQueuedBuffers();
// Retrieve the buffers left in stream
while ( camera->lStream->GetQueuedBufferCount() > 0 )
{
PvBuffer *lBuffer = nullptr;
PvResult lOperationResult;
camera->lStream->RetrieveBuffer( &lBuffer, &lOperationResult, 1000 );
}
return;
}
stop_mutex.unlock();
PvBuffer *lBuffer = nullptr;
PvResult lOperationResult;
// Retrieve next buffer
PvResult lResult = camera->lStream->RetrieveBuffer( &lBuffer, &lOperationResult, 1000 );
if ( lResult.IsOK() )
{
if ( lOperationResult.IsOK() )
{
// We now have a valid buffer. This is where you would typically process the buffer.
// Get image data
// uint64_t frame_size = camera->lDevice->GetPayloadSize();
uint8_t* image = lBuffer->GetDataPointer();
//callback function
camera->data_callback(image, 0, lBuffer->GetBlockID());
}
else
{
// camera->data_callback(camera->padding_frame, 88, 0);
// cout << "spec error: "<< lOperationResult.GetCodeString().GetAscii() << endl; // Non OK operational result
}
// Re-queue the buffer in the stream object
camera->lStream->QueueBuffer( lBuffer );
}
// else
// cout << "*** spec Retrieve buffer failurer: " << lResult.GetCodeString().GetAscii() << endl; // Retrieve buffer failure
}
}
void CaptureThread::exit_thread()
{
stop_mutex.lock();
m_stop = true;
stop_mutex.unlock();
}
/*-------------RGB_CAMERA---------------------*/
RGB_Camera::RGB_Camera(QObject *parent) : QObject(parent)
{
}
RGB_Camera::~RGB_Camera()
{
free_stream_buffers();
if( lStream != nullptr )
{
lStream->Close();
PvStream::Free(lStream);
cout << ">>> rgb_camera: close and free lstream >>>" << endl;
}
if( lDevice != nullptr )
{
lDevice->Disconnect();
PvDevice::Free(lDevice);
cout << ">>> rgb_camera: disconnect and free camera device >>>" << endl;
}
if( rgb_capture_thread != nullptr)
delete rgb_capture_thread;
cout << "rgb_camera: dkkkkkkkkkkkkkkk" << endl;
}
int RGB_Camera::init_camera()
{
int status = enum_connect_camera();
if(status != 0)
return -1;
status = config_camera();
if(status != 0)
return -2;
// get_camera_parameters();
status = open_stream();
if(status != 0)
return -3;
status = configure_stream();
if(status != 0)
return -4;
create_stream_buffers();
rgb_capture_thread = new RGB_CaptureThread();
send_rgb_buf = new uint8_t[RGB_HEIGHT * RGB_WIDTH * 3];
return 0;
}
int RGB_Camera::enum_connect_camera()
{
PvResult lResult;
lResult = lSystem.Find();
if ( !lResult.IsOK() )
{
cout << "*** PvSystem::Find Error: " << lResult.GetCodeString().GetAscii();
return -1;
}
uint32_t lInterfaceCount = lSystem.GetInterfaceCount();
for ( uint32_t x = 0; x < lInterfaceCount; x++ )
{
if(lLastDeviceInfo != nullptr)
break;
uint32_t lDeviceCount = lSystem.GetInterface(x)->GetDeviceCount();
for ( uint32_t y = 0; y < lDeviceCount ; y++ )
{
lDeviceInfo = lSystem.GetInterface(x)->GetDeviceInfo( y );
const PvDeviceInfoGEV* lDeviceInfoGEV = dynamic_cast<const PvDeviceInfoGEV*>( lDeviceInfo );
if ( lDeviceInfoGEV != nullptr ) // Is it a GigE Vision device?
{
// cout << " MAC Address: " << lDeviceInfoGEV->GetMACAddress().GetAscii() << endl;
// cout << " IP Address: " << lDeviceInfoGEV->GetIPAddress().GetAscii() << endl;
// cout << " Serial number: " << lDeviceInfoGEV->GetSerialNumber().GetAscii() << endl << endl;
// lLastDeviceInfo = lDeviceInfo;
if(!strcmp("00:26:ac:a1:00:9d", lDeviceInfoGEV->GetMACAddress().GetAscii()))
{
PvDeviceGEV::SetIPConfiguration("00:26:ac:a1:00:9d", "192.168.15.105", "255.255.255.0", "192.168.15.1");
lLastDeviceInfo = lDeviceInfo;
break;
}
else
{
// cout << "rgb: not this!" << endl;
continue;
}
}
}
}
// Connect to the last device found
if ( lLastDeviceInfo != nullptr )
{
cout << ">>> Connecting to " << lLastDeviceInfo->GetDisplayID().GetAscii() << endl;
// Creates and connects the device controller based on the selected device.
lDevice = PvDevice::CreateAndConnect( lLastDeviceInfo, &lResult );
if ( !lResult.IsOK() )
{
cout << "*** Unable to connect to " << lLastDeviceInfo->GetDisplayID().GetAscii() << endl;
PvDevice::Free(lDevice);
return -1;
}
else
{
cout << ">>> Successfully connected to " << lLastDeviceInfo->GetDisplayID().GetAscii() << endl;
cout << endl;
// Load parameters of the camera
parameter_array = lDevice->GetParameters();
return 0;
}
}
else
{
cout << "*** No device found! ***" << endl;
return -2;
}
}
void RGB_Camera::get_camera_parameters()
{
PvResult lResult;
//Get Height
PvGenInteger* lheight = parameter_array->GetInteger("SensorHeight");
int64_t height = 0;
lResult = lheight->GetValue(height);
if( !lResult.IsOK() )
cout << "*** Unable to get <Height> *** " << endl;
else
cout <<">>> Height: " << height << endl;
//Get Width
PvGenInteger* lwidth = parameter_array->GetInteger("SensorWidth");
int64_t width = 0;
lResult = lwidth->GetValue(width);
if( !lResult.IsOK() )
cout << "*** Unable to get <Width> *** " << endl;
else
cout <<">>> Width: " << width << endl;
//Get AcquisitionFrameRate
PvGenFloat* lframerate = parameter_array->GetFloat("AcquisitionLineRate");
double framerate = 0.0f;
lResult = lframerate->GetValue(framerate);
if( !lResult.IsOK() )
cout << "*** Unable to get <AcquisitionLineRate> *** " << endl;
else
cout <<">>> AcquisitionLineRate: " << framerate << endl;
//Get ExposureTime
PvGenFloat* lexposuretime = parameter_array->GetFloat("CommonExposureTime");
double exposuretime = 0.0f;
lResult = lexposuretime->GetValue(exposuretime);
if( !lResult.IsOK() )
cout << "*** Unable to get <ExposureTime> *** " << endl;
else
cout << ">>> ExposureTime: " << exposuretime << endl;
//查看触发模式
PvString mode;
PvGenEnum* ltriggermode = parameter_array->GetEnum("LineTriggerMode");
ltriggermode->GetValue(mode);
cout << ">>> TriggerMode: " << mode.GetAscii() << endl;
ltriggermode = parameter_array->GetEnum("LineTriggerSource");
ltriggermode->GetValue(mode);
cout << ">>> TriggerSource: " << mode.GetAscii() << endl;
cout << endl;
}
int RGB_Camera::open_stream()
{
PvResult lResult;
// Open stream to the GigE Vision or USB3 Vision device
lStream = PvStream::CreateAndOpen( lLastDeviceInfo->GetConnectionID(), &lResult);
if ( (lStream == nullptr) || !lResult.IsOK() )
{
cout << "*** Unable to stream from " << lLastDeviceInfo->GetDisplayID().GetAscii() << ". ***" << endl;
PvStream::Free(lStream);
PvDevice::Free(lDevice);
return -1;
}
return 0;
}
int RGB_Camera::config_camera()
{
PvGenParameterArray *lDeviceParams = lDevice->GetParameters();
lStart = dynamic_cast<PvGenCommand *>( lDeviceParams->Get( "AcquisitionStart" ) );
lStop = dynamic_cast<PvGenCommand *>( lDeviceParams->Get( "AcquisitionStop" ) );
lUserSetLoad = dynamic_cast<PvGenCommand *>( lDeviceParams->Get( "UserSetLoad" ) );
Whitecal = dynamic_cast<PvGenCommand *>( lDeviceParams->Get( "FFCCalPRNU" ) );
Blackcal = dynamic_cast<PvGenCommand *>( lDeviceParams->Get( "FFCCalFPN" ) );
lUserSave = dynamic_cast<PvGenCommand *>( lDeviceParams->Get( "UserSetSave" ) );
lFFCUserSetSave = dynamic_cast<PvGenCommand *>( lDeviceParams->Get( "FFCUserSetSave" ) );
PvResult lResult = parameter_array->SetEnumValue("UserSetSelector", "UserSet3");
if(!lResult.IsOK()){
cout << "set userset3 failed" << endl;
return -1;
}
lResult = lUserSetLoad->Execute();
if(!lResult.IsOK()){
cout << "userset load failed" << endl;
return -1;
}
// //设置触发模式为 外触发线路Line0上升沿触发
lResult = parameter_array->SetEnumValue("LineTriggerMode", "On");
if(!lResult.IsOK()){
cout << "set triggermode failed" << endl;
return -1;
}
lResult = parameter_array->SetEnumValue("LineTriggerSource", "Line2");
if(!lResult.IsOK()){
cout << "set triggersource failed" << endl;
return -1;
}
return 0;
}
int RGB_Camera::configure_stream()
{
// If this is a GigE Vision device, configure GigE Vision specific streaming parameters
PvDeviceGEV* lDeviceGEV = dynamic_cast<PvDeviceGEV *>( lDevice );
if ( lDeviceGEV != nullptr )
{
PvStreamGEV *lStreamGEV = static_cast<PvStreamGEV *>( lStream );
// Negotiate packet size
PvResult lresult = lDeviceGEV->NegotiatePacketSize();
if( !lresult.IsOK() )
cout << "negotiate packet size failed" << endl;
// Configure device streaming destination
lresult = lDeviceGEV->SetStreamDestination( lStreamGEV->GetLocalIPAddress(), lStreamGEV->GetLocalPort() );
if( !lresult.IsOK() )
cout << "set stream destination failed" << endl;
// cout << ">>> configure stream successfully!" << endl;
return 0;
}
else
{
cout << "*** configure stream failed! ***" << endl;
return -1;
}
}
void RGB_Camera::create_stream_buffers()
{
// Reading payload size from device
uint32_t lSize = lDevice->GetPayloadSize();
// cout << "payloadsize = " << lSize << endl;
// cout << lStream->GetQueuedBufferMaximum() << endl;
// Use BUFFER_COUNT or the maximum number of buffers, whichever is smaller
uint32_t lBufferCount = ( lStream->GetQueuedBufferMaximum() < 16 ) ? lStream->GetQueuedBufferMaximum() : 16;
// cout << "lbuffercount = " << lBufferCount << endl;
// Allocate buffers
for( uint8_t i=0; i<lBufferCount; i++ )
{
// Create new buffer object
PvBuffer *lBuffer = new PvBuffer;
// Have the new buffer object allocate payload memory
PvResult lresult = lBuffer->Alloc( static_cast<uint32_t>( lSize + 500 ) );
if(!lresult.IsOK())
cout << "dk failed" << endl;
// Add to external list - used to eventually release the buffers
lbufferlist.push_back(lBuffer);
}
// cout << ">>> rgb: create stream buffers successfully" << endl;
}
void RGB_Camera::free_stream_buffers()
{
bufferlist::iterator iter = lbufferlist.begin();
while( iter != lbufferlist.end() )
{
delete *iter;
iter++;
}
// Clear the buffer list
lbufferlist.clear();
}
void RGB_Camera::start_acquisition()
{
// Queue all buffers in the stream
bufferlist::iterator iter = lbufferlist.begin();
while( iter != lbufferlist.end() )
{
lStream->QueueBuffer(*iter);
iter++;
}
cout << "queue buffer successfully..." << endl;
// Enable streaming and send the AcquisitionStart command
// cout << "Enabling streaming and sending AcquisitionStart command." << endl;
lDevice->StreamEnable();
lStart->Execute();
// start a new thread CaptureThread
rgb_capture_thread->stop_mutex.lock();
rgb_capture_thread->m_stop = false;
rgb_capture_thread->stop_mutex.unlock();
rgb_capture_thread->start();
}
void RGB_Camera::stop_acquisition()
{
//线程停止!
rgb_capture_thread->exit_thread();
rgb_capture_thread->wait();
if(rgb_capture_thread->isFinished())
{
cout << ">>>rgb capture thread stopped successfully" << endl;
}
}
/*--------rgb_capture thread---------------------*/
RGB_CaptureThread::RGB_CaptureThread(QObject *parent) : QThread(parent), m_stop(false)
{}
void RGB_CaptureThread::run()
{
/*----将线程绑定至6号cpu提高线程效率----*/
// cpu_set_t get;
// cpu_set_t mask;
// int num = sysconf(_SC_NPROCESSORS_CONF);
//// pthread_t thread_id = pthread_self();
//// cout << thread_id << endl;
// CPU_ZERO(&mask);
// CPU_SET(1, &mask);
// sched_setaffinity(1, sizeof(mask), &mask);
// CPU_ZERO(&get);
// sched_getaffinity(1, sizeof(get), &get);
// for(int i=0; i<num; ++i)
// {
// if(CPU_ISSET(i, &get))
// cout << "rgb running on " << i << endl;
// }
/*-----------------------------------*/
while(1)
{
stop_mutex.lock();
if(m_stop)
{
stop_mutex.unlock();
// Tell the device to stop sending images.
rgb_camera->lStop->Execute();
// Disable streaming on the device
rgb_camera->lDevice->StreamDisable();
// Abort all buffers from the stream and dequeue
rgb_camera->lStream->AbortQueuedBuffers();
// Retrieve the buffers left in stream
while ( rgb_camera->lStream->GetQueuedBufferCount() > 0 )
{
PvBuffer *lBuffer = nullptr;
PvResult lOperationResult;
rgb_camera->lStream->RetrieveBuffer( &lBuffer, &lOperationResult, 1000 );
}
return;
}
stop_mutex.unlock();
PvBuffer *lBuffer = nullptr;
PvResult lOperationResult;
// Retrieve next buffer
PvResult lResult = rgb_camera->lStream->RetrieveBuffer( &lBuffer, &lOperationResult, 1000 );
if ( lResult.IsOK() )
{
if ( lOperationResult.IsOK() )
{
// We now have a valid buffer. This is where you would typically process the buffer.
// Get image data
// uint64_t frame_size = camera->lDevice->GetPayloadSize();
uint8_t* image = lBuffer->GetDataPointer();
memcpy(send_rgb_buf, image, RGB_HEIGHT * RGB_WIDTH * 3);
rgb_camera->send_rgbdata_to_ui(send_rgb_buf);
ready_to_send_rgb.release();
}
else{
// memset(send_rgb_buf, 0, RGB_HEIGHT * RGB_WIDTH * 3);
// ready_to_send_rgb.release();
// cout << "rgb error: "<< lOperationResult.GetCodeString().GetAscii() << endl; // Non OK operational result
}
// Re-queue the buffer in the stream object
rgb_camera->lStream->QueueBuffer( lBuffer );
}
// else
// cout << "*** rgb Retrieve buffer failure: " << lResult.GetCodeString().GetAscii() << endl; // Retrieve buffer failure
}
}
void RGB_CaptureThread::exit_thread()
{
stop_mutex.lock();
m_stop = true;
stop_mutex.unlock();
}