性能:兩路2448*2048 basyer相機編碼,編碼後25fps,延遲200ms左右
編碼:調用nvidia底層的api, 參考tegra_multimedia_api下的cuda_encode例子。隻需要修改read_from_file()函數的資料為相機輸入資料即可
目前隻支援輸入I420格式,但是basyer相機沒有I420的格式,用cuda做轉換,代碼如下:
// Grab.cpp
/*
Note: Before getting started, Basler recommends reading the Programmer's Guide topic
in the pylon C++ API documentation that gets installed with pylon.
If you are upgrading to a higher major version of pylon, Basler also
strongly recommends reading the Migration topic in the pylon C++ API documentation.
This sample illustrates how to grab and process images using the CInstantCamera class.
The images are grabbed and processed asynchronously, i.e.,
while the application is processing a buffer, the acquisition of the next buffer is done
in parallel.
The CInstantCamera class uses a pool of buffers to retrieve image data
from the camera device. Once a buffer is filled and ready,
the buffer can be retrieved from the camera object for processing. The buffer
and additional image data are collected in a grab result. The grab result is
held by a smart pointer after retrieval. The buffer is automatically reused
when explicitly released or when the smart pointer object is destroyed.
*/
// Include files to use the PYLON API.
#include <pylon/PylonIncludes.h>
#ifdef PYLON_WIN_BUILD
# include <pylon/PylonGUI.h>
#endif
#include"opencv2/opencv.hpp"
#include"opencv2/highgui.hpp"
#include<sys/time.h>
#include"opencv2/core/core.hpp"
#include <pylon/gige/BaslerGigECamera.h>
#include <cuda_runtime.h>
#include "cudaYUV.h"
#include "cudaRGB.h"
//定義是否儲存圖檔 0-否 1-是
#define saveImages 0
//定義是否記錄視訊 0-否 1-是
#define recordVideo 0
// Namespace for using pylon objects.
using namespace Pylon;
// Namespace for using cout.
using namespace std;
#include "opencv2/gpu/gpu.hpp"
using namespace cv;
// Number of images to be grabbed.
static const uint32_t c_countOfImagesToGrab = ;
unsigned char *I420Buffer=NULL;
unsigned char *BGRABuffer=NULL;
unsigned char *RGBBuffer=NULL;
/*void BGR_YUV420(unsigned char*bsrc,unsigned char *bdst,int width,int height)
{
}*/
int main(int argc, char* argv[])
{
// The exit code of the sample application.
int exitCode = ;
// Before using any pylon methods, the pylon runtime must be initialized.
Pylon::PylonAutoInitTerm autoInitTerm;
try
{
//建立相機對象(以最先識别的相機)
CInstantCamera camera(CTlFactory::GetInstance().CreateFirstDevice());
// 列印相機的名稱
std::cout << "Using device " << camera.GetDeviceInfo().GetModelName() << endl;
//擷取相機節點映射以獲得相機參數
GenApi::INodeMap& nodemap = camera.GetNodeMap();
//打開相機
camera.Open();
//擷取相機成像寬度和高度
GenApi::CIntegerPtr width = nodemap.GetNode("Width");
GenApi::CIntegerPtr height = nodemap.GetNode("Height");
//設定相機最大緩沖區,預設為10
camera.MaxNumBuffer = ;
// 建立pylon ImageFormatConverter對象.
CImageFormatConverter formatConverter;
//确定輸出像素格式
formatConverter.OutputPixelFormat = PixelType_RGB8packed;
// 建立一個Pylonlmage後續将用來建立OpenCV images
CPylonImage pylonImage;
//聲明一個整形變量用來計數抓取的圖像,以及建立檔案名索引
int grabbedlmages = ;
// 建立一個OpenCV video creator對象.
VideoWriter cvVideoCreator;
//建立一個OpenCV image對象.
Mat openCvImage;
Mat dst_image;
// 視訊檔案名
std::string videoFileName = "openCvVideo.avi";
// 定義視訊幀大小
cv::Size frameSize = Size((int)width->GetValue(), (int)height->GetValue());
//設定視訊編碼類型和幀率,有三種選擇
// 幀率必須小于等于相機成像幀率
cvVideoCreator.open(videoFileName, CV_FOURCC('D', 'I', 'V','X'), , frameSize, true);
//cvVideoCreator.open(videoFileName, CV_F0URCC('M','P',,4','2’), 20, frameSize, true);
//cvVideoCreator.open(videoFileName, CV_FOURCC('M', '3', 'P', 'G'), 20, frameSize, true);
// 開始抓取c_countOfImagesToGrab images.
//相機預設設定連續抓取模式
camera.StartGrabbing(c_countOfImagesToGrab, GrabStrategy_LatestImageOnly);
//抓取結果資料指針
CGrabResultPtr ptrGrabResult;
// 當c_countOfImagesToGrab images擷取恢複成功時,Camera.StopGrabbing()
//被RetrieveResult()方法自動調用停止抓取
FILE *fp=fopen("1.yuv","w+");
struct timeval start,end;
while (camera.IsGrabbing())
{
// 等待接收和恢複圖像,逾時時間設定為5000 ms.
camera.RetrieveResult(, ptrGrabResult, TimeoutHandling_ThrowException);
//如果圖像抓取成功
if (ptrGrabResult->GrabSucceeded())
{
// 擷取圖像資料
int m_width=ptrGrabResult->GetWidth();
int m_height=ptrGrabResult->GetHeight();
cout <<"SizeX: "<<m_width<<endl;
cout <<"SizeY: "<<m_height<<endl;
//将抓取的緩沖資料轉化成pylon image.
formatConverter.Convert(pylonImage, ptrGrabResult);
// 将 pylon image轉成OpenCV image.
//openCvImage = cv::Mat(ptrGrabResult->GetHeight(), ptrGrabResult->GetWidth(), CV_8UC3, (uint8_t *) pylonImage.GetBuffer());
//cvtColor(openCvImage,dst_image,CV_RGB2RGBA);
#if 0
unsigned long long timeusd=;
gettimeofday(&start,NULL);
cvtColor(openCvImage,dst_image,CV_BGR2YUV_I420);
gettimeofday(&end,NULL);
//timeusd=end.tv_sec-start.tv_sec+(end.tv_usec-start.tv_usec)/1000000;
cout<<"convert cost "<<end.tv_sec-start.tv_sec+(end.tv_usec-start.tv_usec)/<< " sec"<<endl<<endl;
#endif
#if 1
if(!I420Buffer)
{
if(CUDA_FAILED(cudaMalloc((void**)&I420Buffer,m_height*m_width*/)))
{
cout<<"cudaMalloc For I420Buffer Error"<<endl;
}
}
#endif
#if 1
if(!RGBBuffer)
{
if(CUDA_FAILED(cudaMalloc((void**)&RGBBuffer,m_height*m_width*)))
{
cout<<"cudaMalloc For RGBBuffer Error"<<endl;
}
}
#endif
#if 1
if(!BGRABuffer)
{
if(CUDA_FAILED(cudaMalloc((void**)&BGRABuffer,m_height*m_width*)))
{
cout<<"cudaMalloc For BGRABuffer Error"<<endl;
}
}
#endif
cudaMemcpy(RGBBuffer,pylonImage.GetBuffer(),m_height*m_width*,cudaMemcpyHostToDevice);
#if 1
if(CUDA_FAILED(cudaRGBToRGBAf((uchar3 *)RGBBuffer,(float4 *)BGRABuffer, m_width,m_height)))
{
cout<<"Failed to Convert RGB2RGBA"<<endl;
}
#endif
#if 1
//cudaMemcpy(BGRABuffer,dst_image.data,m_height*m_width*4,cudaMemcpyHostToDevice);
if(CUDA_FAILED(cudaRGBAToI420((uchar4 *)BGRABuffer,I420Buffer,m_width,m_height)))
{
cout<<"Failed to Convert RGBAToI420"<<endl;
}
#endif
unsigned char g_buffer[m_height*m_width*/];
#if 1
cudaMemcpy(g_buffer,I420Buffer,m_width*m_height*/,cudaMemcpyDeviceToHost);
fwrite(g_buffer,**/,,fp);
#endif
//如果需要儲存圖檔
if (saveImages)
{
std::ostringstream s;
// 按索引定義檔案名存儲圖檔
s << "image_" << grabbedlmages << ".jpg";
std::string imageName(s.str());
//儲存OpenCV image.
cv::imwrite(imageName, openCvImage);
grabbedlmages++;
}
//如果需要記錄視訊
if (recordVideo)
{
cvVideoCreator.write(openCvImage);
}
//建立OpenCV display window.
//cv::namedWindow("OpenCV Display Window", CV_WINDOW_NORMAL); // other options: CV_AUTOSIZE, CV_FREERATIO
//顯示及時影像.
//cv::imshow("OpenCV Display Window", dst_image);
// Define a timeout for customer's input in
// '0' means indefinite, i.e. the next image will be displayed after closing the window.
// '1' means live stream
waitKey();
}
}
fclose(fp);
}
catch (GenICam::GenericException &e)
{
// Error handling.
cerr << "An exception occurred." << endl
<< e.GetDescription() << endl;
}
return exitCode;
}
轉換完成,加入編碼推流的代碼,推流是利用EasyDarwin做流媒體轉發伺服器:
// Grab.cpp
/*
Note: Before getting started, Basler recommends reading the Programmer's Guide topic
in the pylon C++ API documentation that gets installed with pylon.
If you are upgrading to a higher major version of pylon, Basler also
strongly recommends reading the Migration topic in the pylon C++ API documentation.
This sample illustrates how to grab and process images using the CInstantCamera class.
The images are grabbed and processed asynchronously, i.e.,
while the application is processing a buffer, the acquisition of the next buffer is done
in parallel.
The CInstantCamera class uses a pool of buffers to retrieve image data
from the camera device. Once a buffer is filled and ready,
the buffer can be retrieved from the camera object for processing. The buffer
and additional image data are collected in a grab result. The grab result is
held by a smart pointer after retrieval. The buffer is automatically reused
when explicitly released or when the smart pointer object is destroyed.
*/
// Include files to use the PYLON API.
//gst_rtsp
#include "stdio.h"
#include <unistd.h>
#include <stdlib.h>
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <signal.h>
#include <errno.h>
#include <ctype.h>
#include <time.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h> /* for TCP_NODELAY */
#include <arpa/inet.h>
#include <sys/uio.h>
#include <sys/time.h>
#include <pthread.h>
#include <sched.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <linux/fb.h>
#include <fcntl.h>
#include <semaphore.h>
#include <net/if.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/vfs.h>
#include <pthread.h>
#include "assert.h"
#include <netdb.h>
#include <malloc.h>
#include <deque>
#include <list>
#include <string>
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include "video_encode.h"
#include "libRtspPusherAPI.h"
#include <pylon/PylonIncludes.h>
#ifdef PYLON_WIN_BUILD
# include <pylon/PylonGUI.h>
#endif
#include"opencv2/opencv.hpp"
#include"opencv2/highgui.hpp"
#include<sys/time.h>
#include"opencv2/core/core.hpp"
#include <pylon/gige/BaslerGigECamera.h>
//定義是否儲存圖檔 0-否 1-是
#define saveImages 0
//定義是否記錄視訊 0-否 1-是
#define recordVideo 0
// Namespace for using pylon objects.
using namespace Pylon;
// Namespace for using cout.
using namespace std;
#include "opencv2/gpu/gpu.hpp"
using namespace cv;
// Number of images to be grabbed.
static const uint32_t c_countOfImagesToGrab = ;
bool signal_recieved = false;
static int m_Width=;
static int m_Height=;
void sig_handler(int signo)
{
if( signo == SIGINT )
{
printf("received SIGINT\n");
signal_recieved = true;
}
}
#define TEST_CHANNEL_NUM 5 // ����ͨ����
#define TEST_URL_MAX_LEN 128 // URL ��?�
#define TEST_LOOP_MAX_NUM 1000000 // ��������ѭ����
#define TEST_SINGLE_LOOP_TIME 30 // ����ѭ��ʱ��
typedef struct {
char pullStreamUrl[TEST_URL_MAX_LEN+];
char pushStreamRtspUrl[TEST_URL_MAX_LEN+];
int pullStreamSuccess;
void* rtspPushStreamHandle;
} TestChannelConfigure;
#define TEST_CHANNEL_MAX_NUM 1 // ֧��ͨ�������
TestChannelConfigure testChannelConfigure[TEST_CHANNEL_MAX_NUM] = {
{"admin:[email protected]://192.168.1.190","rtsp://192.168.5.43/110.sdp",,NULL}
};
#define ENC_MAX_BUFFER 5
sem_t sem_dec_output_read;
sem_t sem_dec_output_write;
pthread_mutex_t mutex;
void *g_buffer = NULL;
int g_iReadBufferPos = ;
int encInput(unsigned char *Y, unsigned char *U, unsigned char*V, int *width, int *height, NvBuffer *buffer, void *pUserData)
{
int i, j = ;
sem_wait(&sem_dec_output_read);
pthread_mutex_lock(&mutex);
for (i = ; i < buffer->n_planes; i++)
{
NvBuffer::NvBufferPlane &plane = buffer->planes[i];
//NvBuffer::NvBufferPlane &plane_dec = User->m_buffer->planes[i];
unsigned char *data = plane.data;
unsigned int bytes_to_read =
plane.fmt.bytesperpixel * plane.fmt.width;
/*
---DEBUG--[av_stream.cpp: encInput: 2089]--[2017-07-01 07:12:45]-- encInput() channid[0] dec_buffer[1920 * 1080]
buffer.n_planes[3]
plane.fmt.bytesperpixel[1]
plane.fmt.width[1920]
plane.fmt.height[1080]
plane.fmt.stride[2048]
plane.bytesused[0]
---DEBUG--[av_stream.cpp: encInput: 2089]--[2017-07-01 07:12:45]-- encInput() channid[0] dec_buffer[1920 * 1080]
buffer.n_planes[3]
plane.fmt.bytesperpixel[1]
plane.fmt.width[960]
plane.fmt.height[540]
plane.fmt.stride[1024]
plane.bytesused[0]
---DEBUG--[av_stream.cpp: encInput: 2089]--[2017-07-01 07:12:45]-- encInput() channid[0] dec_buffer[1920 * 1080]
buffer.n_planes[3]
plane.fmt.bytesperpixel[1]
plane.fmt.width[960]
plane.fmt.height[540]
plane.fmt.stride[1024]
plane.bytesused[0]
*/
plane.bytesused = ;
for (j = ; j < plane.fmt.height; j++)
{
memcpy(data, (g_buffer + g_iReadBufferPos), bytes_to_read);
data += plane.fmt.stride;
g_iReadBufferPos += bytes_to_read;
}
plane.bytesused = plane.fmt.stride * plane.fmt.height;
printf( "i = [%d] \nRes[%d*%d] \nbytesperpixel[%d] \nstride[%d] \nplane.bytesused[%d] \n",
i, plane.fmt.width, plane.fmt.height, plane.fmt.bytesperpixel, plane.fmt.stride, plane.bytesused);
}
g_buffer = NULL;
g_iReadBufferPos = ;
pthread_mutex_unlock(&mutex);
sem_post(&sem_dec_output_write);
return ;
}
FILE *fp4 = NULL;
int encOutput(char *pBuf, int iLen, void *pDataTypePara, void *pUserData)
{
printf("............func:%s Line:%d 0x%2x%2x%2x%2x%2x%2x %2x%2x%2x %2x%2x%2x iLen[%d] \n",
__func__, __LINE__, pBuf[], pBuf[], pBuf[], pBuf[], pBuf[], pBuf[], pBuf[], pBuf[], pBuf[], pBuf[], pBuf[], pBuf[],iLen);
#if 0
if (NULL == fp4)
{
fp4 = fopen("out.264", "wb");
int ret = fwrite(pBuf, , iLen, fp4);
}
else
{
int ret = fwrite(pBuf, , iLen, fp4);
}
#endif
#if 1
RTSP_Pusher_Handler rtspPushStreamHandle = testChannelConfigure[].rtspPushStreamHandle;
assert(testChannelConfigure != NULL);
TmAVFrame avFrame;
avFrame.frameType = VIDEO_FRAME_TYPE;
avFrame.frameLen = iLen;
avFrame.frameData = (unsigned char*)pBuf;
//memcpy(avFrame.frameData,_pinBuf,avFrame.frameLen);
int ret = RTSP_Pusher_PushFrame(rtspPushStreamHandle,&avFrame);
if( ret < ) {
#if 1
printf("------------channel_%d push stream failed.\n",);
#endif
}
#endif
}
int enc_StatueCallBack(int ichannle, int statue, int iNowStreamFlag, void *pUserData)
{
return ;
}
int RtspPushStreamLogCB(int logLevel,const char *logInfo,int len)
{
printf("RtspPushStreamLogCB[%s] \n", logInfo);
return ;
}
int RtspPushStreamStatueCB(RTSP_Pusher_Handler handler,RTSP_Pusher_State state, int statusCode, void *context)
{
printf("RtspPushStreamStatueCB() state[%d] statusCode[%d] \n", state, statusCode);
return ;
}
/*void BGR_YUV420(unsigned char*bsrc,unsigned char *bdst,int width,int height)
{
}*/
int main(int argc, char* argv[])
{
// The exit code of the sample application.
int exitCode = ;
if(argc!=)
{
std::cout<<"Usage: ./Grab0 rtsp://192.168.1.43(TX2_IP):554/110.sdp"<<endl;
return -;
}
#if 1
int ret;
/*rtsp puser*/
RTSP_Pusher_SetStartPort();
RTSP_Pusher_SetLogCallBack(RtspPushStreamLogCB);
RTSP_Pusher_SetStreamStatusCallback(RtspPushStreamStatueCB, NULL);
TmMediaInfo mediaInfo;
RTSP_Pusher_Handler rtspPusherHandler = RTSP_Pusher_Create();
assert(rtspPusherHandler != NULL);
memset(&mediaInfo,,sizeof(TmMediaInfo));
mediaInfo.videoCodec = VIDEO_CODEC_H264;
mediaInfo.videoFps = ;
#if 0
ret = RTSP_Pusher_StartStream(rtspPusherHandler,
testChannelConfigure[].pushStreamRtspUrl,
RTP_OVER_UDP,
NULL,
NULL,
,
&mediaInfo);
#endif
memset(testChannelConfigure[].pushStreamRtspUrl,,sizeof(testChannelConfigure[].pushStreamRtspUrl));
strcpy(testChannelConfigure[].pushStreamRtspUrl,argv[]);
ret = RTSP_Pusher_StartStream(rtspPusherHandler,
testChannelConfigure[].pushStreamRtspUrl,
RTP_OVER_UDP,
NULL,
NULL,
,
&mediaInfo);
if(ret < ) {
printf("fun[%s] Line[%d] chId%d start push stream failed ret[%d].\n",__func__, __LINE__, , ret);
return NULL;
}
testChannelConfigure[].rtspPushStreamHandle = rtspPusherHandler;
#endif
sem_init(&sem_dec_output_read, , );
sem_init(&sem_dec_output_write, , );
pthread_mutex_init(&mutex, NULL);
g_buffer = NULL;
g_iReadBufferPos = ;
TM_video_enc *enc_obj_merge;
enc_context_t enc_cfg;
//enc by TM
enc_obj_merge = new TM_video_enc();
if (NULL == enc_obj_merge)
{
return ;
}
enc_obj_merge->init(ENC_MAX_BUFFER);
memset(&enc_cfg, , sizeof(enc_context_t));
enc_cfg.ratecontrol = V4L2_MPEG_VIDEO_BITRATE_MODE_CBR;
enc_cfg.iframe_interval = ;
enc_cfg.idr_interval = ;
enc_cfg.level = V4L2_MPEG_VIDEO_H264_LEVEL_5_1;
enc_cfg.fps_n = ;
enc_cfg.fps_d = ;
enc_cfg.num_b_frames = (uint32_t) -;
enc_cfg.nMinQpI = (uint32_t)QP_RETAIN_VAL;
enc_cfg.nMaxQpI = (uint32_t)QP_RETAIN_VAL;
enc_cfg.nMinQpP = (uint32_t)QP_RETAIN_VAL;
enc_cfg.nMaxQpP = (uint32_t)QP_RETAIN_VAL;
enc_cfg.nMinQpB = (uint32_t)QP_RETAIN_VAL;
enc_cfg.nMaxQpB = (uint32_t)QP_RETAIN_VAL;
enc_cfg.in_file_path = "tmp.yuv";
enc_cfg.out_file_path = "tmp.h264";
if (/*VIDEO_CODEC_H265 == m_strChannelEncCfg.VideoEncodeType*/)
{
enc_cfg.profile = V4L2_MPEG_VIDEO_H265_PROFILE_MAIN10;
enc_cfg.encoder_pixfmt = V4L2_PIX_FMT_H265;
}
else
{
enc_cfg.level = V4L2_MPEG_VIDEO_H264_LEVEL_5_0;
/*����Dz������ѹ���������iframe_interval Ҫ50���ϣ�����profile �ij�HIGH*/
enc_cfg.profile = V4L2_MPEG_VIDEO_H264_PROFILE_MAIN;/*����ij�HIGH �?��¼��elecard ���Ų���*/
enc_cfg.encoder_pixfmt = V4L2_PIX_FMT_H264;
}
/*create v4l2 enc*/
//
Pylon::PylonAutoInitTerm autoInitTerm;
try
{
//建立相機對象(以最先識别的相機)
CTlFactory& tlFactory = CTlFactory::GetInstance();
// Get all attached devices and exit application if
// two cameras aren't found
DeviceInfoList_t devices;
CInstantCamera camera;
if( tlFactory.EnumerateDevices(devices) == )
{
cout << "Found " << devices.size() << " cameras." << endl;
camera.Attach(tlFactory.CreateDevice( devices[] ) );
if(camera.GetDeviceInfo().GetModelName()=="ML500-35C")
{
// 列印相機的名稱
std::cout << "Using device " << camera.GetDeviceInfo().GetModelName() << endl;
camera.Open();
}
else
{
// 列印相機的名稱
std::cout << "Using device " << camera.GetDeviceInfo().GetModelName() << endl;
camera.Open();
}
}
else
{
camera.Attach(tlFactory.CreateDevice( devices[]));
camera.Open();
}
GenApi::INodeMap& nodemap = camera.GetNodeMap();
//打開相機
//擷取相機成像寬度和高度
GenApi::CIntegerPtr width = nodemap.GetNode("Width");
GenApi::CIntegerPtr height = nodemap.GetNode("Height");
enc_cfg.width =(int)width->GetValue() /* * g_FaceScaleFactor*/;
enc_cfg.height =(int)height->GetValue() /* * g_FaceScaleFactor*/;
enc_cfg.insert_sps_pps_at_idr = true;/*ǿ��ÿһ��I֡ǰ����SPS PPS*/
enc_cfg.iframe_interval = ;
enc_cfg.idr_interval = ;
enc_cfg.fps_n = ;
enc_cfg.bitrate = * ;
void *pUser = (void *)"c++ duixiang ";
enc_obj_merge->set_config(&enc_cfg, encInput, encOutput, enc_StatueCallBack, (void *)pUser);
enc_obj_merge->start();
//設定相機最大緩沖區,預設為10
camera.MaxNumBuffer = ;
// 建立pylon ImageFormatConverter對象.
CImageFormatConverter formatConverter;
//确定輸出像素格式
formatConverter.OutputPixelFormat = PixelType_BGR8packed;
// 建立一個Pylonlmage後續将用來建立OpenCV images
CPylonImage pylonImage;
//聲明一個整形變量用來計數抓取的圖像,以及建立檔案名索引
int grabbedlmages = ;
// 建立一個OpenCV video creator對象.
VideoWriter cvVideoCreator;
//建立一個OpenCV image對象.
Mat openCvImage;
Mat dst_image;
// 視訊檔案名
std::string videoFileName = "openCvVideo.avi";
// 定義視訊幀大小
cv::Size frameSize = Size((int)width->GetValue(), (int)height->GetValue());
//設定視訊編碼類型和幀率,有三種選擇
// 幀率必須小于等于相機成像幀率
cvVideoCreator.open(videoFileName, CV_FOURCC('D', 'I', 'V','X'), , frameSize, true);
//cvVideoCreator.open(videoFileName, CV_F0URCC('M','P',,4','2’), 20, frameSize, true);
//cvVideoCreator.open(videoFileName, CV_FOURCC('M', '3', 'P', 'G'), 20, frameSize, true);
// 開始抓取c_countOfImagesToGrab images.
//相機預設設定連續抓取模式
camera.StartGrabbing(c_countOfImagesToGrab, GrabStrategy_LatestImageOnly);
//抓取結果資料指針
CGrabResultPtr ptrGrabResult;
// 當c_countOfImagesToGrab images擷取恢複成功時,Camera.StopGrabbing()
//被RetrieveResult()方法自動調用停止抓取
unsigned long timeusd=;
FILE *fp=fopen("1.yuv","w+");
struct timeval start,end;
while (camera.IsGrabbing())
{
// 等待接收和恢複圖像,逾時時間設定為5000 ms.
camera.RetrieveResult(, ptrGrabResult, TimeoutHandling_ThrowException);
//如果圖像抓取成功
if (ptrGrabResult->GrabSucceeded())
{
// 擷取圖像資料
cout <<"SizeX: "<<ptrGrabResult->GetWidth()<<endl;
cout <<"SizeY: "<<ptrGrabResult->GetHeight()<<endl;
//将抓取的緩沖資料轉化成pylon image.
formatConverter.Convert(pylonImage, ptrGrabResult);
// 将 pylon image轉成OpenCV image.
openCvImage = cv::Mat(ptrGrabResult->GetHeight(), ptrGrabResult->GetWidth(), CV_8UC3, (uint8_t *) pylonImage.GetBuffer());
gettimeofday(&start,NULL);
cvtColor(openCvImage,dst_image,CV_BGR2YUV_I420);
gettimeofday(&end,NULL);
pthread_mutex_lock(&mutex);
g_buffer = dst_image.data;
g_iReadBufferPos = ;
pthread_mutex_unlock(&mutex);
sem_post(&sem_dec_output_read);
sem_wait(&sem_dec_output_write);
timeusd=start.tv_sec-end.tv_sec+(start.tv_usec-end.tv_usec)/;
//imshow("test",dst_image);
//如果需要儲存圖檔
if (saveImages)
{
std::ostringstream s;
// 按索引定義檔案名存儲圖檔
s << "image_" << grabbedlmages << ".jpg";
std::string imageName(s.str());
//儲存OpenCV image.
cv::imwrite(imageName, openCvImage);
grabbedlmages++;
}
//如果需要記錄視訊
if (recordVideo)
{
cvVideoCreator.write(openCvImage);
}
//建立OpenCV display window.
//cv::namedWindow("OpenCV Display Window", CV_WINDOW_NORMAL); // other options: CV_AUTOSIZE, CV_FREERATIO
//顯示及時影像.
//cv::imshow("OpenCV Display Window", dst_image);
// Define a timeout for customer's input in
// '0' means indefinite, i.e. the next image will be displayed after closing the window.
// '1' means live stream
waitKey();
}
}
}
catch (GenICam::GenericException &e)
{
// Error handling.
cerr << "An exception occurred." << endl
<< e.GetDescription() << endl;
}
return exitCode;
}