上一个博客讲到如何安装pylon以及他们的一些例程,这一章讲如何用opencv打开basler的gige相机。
虽然用常规的方法打开工业相机是没有问题的,但是这种方法不好设置相机的参数。
1. 新建一个控制台程序的工程,设置属性管理器。
添加i包含目录
C:\Program Files\Basler\pylon 5\Development\include\pylon
C:\Program Files\Basler\pylon 5\Development\include
和库目录
C:\Program Files\Basler\pylon 5\Development\lib\x64
如果安装目录不同,读者根据自己的电脑安装路径修改这两个目录。
2.配置opencv
3.代码
我用到的最重要的几个参数是 图像的长宽,offset,曝光时间。读者可根据自己的相机和需要设置这几个参数
int64_t newWidth = 1626;
int64_t newHeight = 196;
int64_t exposuretime = 1000;
int64_t Yoffset=450;
函数
extern bool imageProcessmain(Mat &frame);
是图像处理函数,内容写在其他cpp文件里。如果返回值是0则下面的主函数的死循环会退出。返回值为1时会继续获取新的图像。
// 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/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include "opencv2/objdetect/objdetect.hpp"
#include <opencv2/imgproc/imgproc.hpp>
#include <highgui.h>
#define USE_GIGE 1
using namespace Pylon;
using namespace GenApi;
using namespace cv;
using namespace std;
//通过修改这部分来改变延时//开始和停止抓取会影响帧率
static const uint32_t c_countOfImagesToGrab = 10000;
uint32_t c_count = c_countOfImagesToGrab;
/
重要参数设置
int64_t newWidth = 1626;
int64_t newHeight = 196;
int64_t exposuretime = 1000;
int64_t Yoffset=450;
///
#include <pylon/PylonIncludes.h>
// Namespace for using pylon objects.
using namespace Pylon;
#if defined( USE_1394 )
// Setting for using Basler IEEE 1394 cameras.
#include <pylon/1394/Basler1394InstantCamera.h>
typedef Pylon::CBasler1394InstantCamera Camera_t;
using namespace Basler_IIDC1394CameraParams;
#elif defined ( USE_GIGE )
// Setting for using Basler GigE cameras.
#include <pylon/gige/BaslerGigEInstantCamera.h>
typedef Pylon::CBaslerGigEInstantCamera Camera_t;
using namespace Basler_GigECameraParams;
#elif defined ( USE_CAMERALINK )
// Setting for using Basler Camera Link cameras.
#include <pylon/cameralink/BaslerCameraLinkInstantCamera.h>
typedef Pylon::CBaslerCameraLinkInstantCamera Camera_t;
using namespace Basler_CLCameraParams;
#elif defined ( USE_USB )
// Setting for using Basler USB cameras.
#include <pylon/usb/BaslerUsbInstantCamera.h>
typedef Pylon::CBaslerUsbInstantCamera Camera_t;
using namespace Basler_UsbCameraParams;
#else
#error Camera type is not specified. For example, define USE_GIGE for using GigE cameras.
#endif
//
int64_t Adjust(int64_t val, int64_t minimum, int64_t maximum, int64_t inc)
{
// Check the input parameters.
if (inc <= 0)
{
// Negative increments are invalid.
throw LOGICAL_ERROR_EXCEPTION("Unexpected increment %d", inc);
}
if (minimum > maximum)
{
// Minimum must not be bigger than or equal to the maximum.
throw LOGICAL_ERROR_EXCEPTION("minimum bigger than maximum.");
}
// Check the lower bound.
if (val < minimum)
{
return minimum;
}
// Check the upper bound.
if (val > maximum)
{
return maximum;
}
// Check the increment.
if (inc == 1)
{
// Special case: all values are valid.
return val;
}
else
{
// The value must be min + (n * inc).
// Due to the integer division, the value will be rounded down.
return minimum + (((val - minimum) / inc) * inc);
}
}
extern bool imageProcessmain(Mat &frame);
///
int main(int argc, char* argv[])
{
cv::CommandLineParser parser(argc, argv,
"{h||}"
"{w||}"
"{t||}"
"{o||}"
);
if (parser.has("h"))
{
newHeight=parser.get<double>("h");
}
if (parser.has("w"))
{
newWidth = parser.get<double>("w");
}
if (parser.has("t"))
{
exposuretime = parser.get<double>("t");
}
if (parser.has("o"))
{
Yoffset = parser.get<double>("o");
}
// The exit code of the sample application.
int exitCode = 0;
// Before using any pylon methods, the pylon runtime must be initialized.
PylonInitialize();
try
{
// Create an instant camera object with the camera device found first.
// CInstantCamera camera(CTlFactory::GetInstance().CreateFirstDevice());
///
CDeviceInfo info;
info.SetDeviceClass(Camera_t::DeviceClass());
// Create an instant camera object with the first found camera device matching the specified device class.
Camera_t camera(CTlFactory::GetInstance().CreateFirstDevice(info));
// Print the model name of the camera.
cout << "Using device " << camera.GetDeviceInfo().GetModelName() << endl;
// Open the camera.
camera.Open();
///
// Print the model name of the camera.
cout << "Using device " << camera.GetDeviceInfo().GetModelName() << endl;
/
camera.PixelFormat.SetValue(PixelFormat_Mono8);
// Some properties have restrictions. Use GetInc/GetMin/GetMax to make sure you set a valid value.
newWidth = Adjust(newWidth, camera.Width.GetMin(), camera.Width.GetMax(), camera.Width.GetInc());
newHeight = Adjust(newHeight, camera.Height.GetMin(), camera.Height.GetMax(), camera.Height.GetInc());
camera.Width.SetValue(newWidth);
camera.Height.SetValue(newHeight);
if (IsWritable(camera.OffsetX))
{
camera.OffsetX.SetValue(camera.OffsetX.GetMin());
}
if (IsWritable(camera.OffsetY))
{
camera.OffsetY.SetValue(Yoffset);
}
cout << "OffsetX : " << camera.OffsetX.GetValue() << endl;
cout << "OffsetY : " << camera.OffsetY.GetValue() << endl;
cout << "Width : " << camera.Width.GetValue() << endl;
cout << "Height : " << camera.Height.GetValue() << endl;
//Disable acquisition start trigger if available
{
GenApi::IEnumEntry* acquisitionStart = camera.TriggerSelector.GetEntry(TriggerSelector_AcquisitionStart);
if (acquisitionStart && GenApi::IsAvailable(acquisitionStart))
{
camera.TriggerSelector.SetValue(TriggerSelector_AcquisitionStart);
camera.TriggerMode.SetValue(TriggerMode_Off);
}
}
//Disable frame start trigger if available
{
GenApi::IEnumEntry* frameStart = camera.TriggerSelector.GetEntry(TriggerSelector_FrameStart);
if (frameStart && GenApi::IsAvailable(frameStart))
{
camera.TriggerSelector.SetValue(TriggerSelector_FrameStart);
camera.TriggerMode.SetValue(TriggerMode_Off);
}
}
// camera.AcquisitionMode.SetValue(AcquisitionMode_SingleFrame);
/
// The parameter MaxNumBuffer can be used to control the count of buffers
// allocated for grabbing. The default value of this parameter is 10.
camera.MaxNumBuffer = 5;
// Start the grabbing of c_countOfImagesToGrab images.
// The camera device is parameterized with a default configuration which
// sets up free-running continuous acquisition.
camera.StartGrabbing(c_countOfImagesToGrab);
// This smart pointer will receive the grab result data.
CGrabResultPtr ptrGrabResult;
CImageFormatConverter formatConverter;
formatConverter.OutputPixelFormat = PixelType_BGR8packed;
Mat openCvImage;
CPylonImage pylonImage;
/ 设置曝光时间部分
camera.GainAuto.SetValue(GainAuto_Off);
camera.GainRaw.SetValue(camera.GainRaw.GetMin());
camera.ExposureAuto.SetValue(ExposureAuto_Off);
camera.ExposureTimeRaw.SetValue(exposuretime);
// Camera.StopGrabbing() is called automatically by the RetrieveResult() method
// when c_countOfImagesToGrab images have been retrieved.
while (camera.IsGrabbing())
{
c_count--;
// Wait for an image and then retrieve it. A timeout of 5000 ms is used.
camera.RetrieveResult(5000, ptrGrabResult, TimeoutHandling_ThrowException);
// Image grabbed successfully?
if (ptrGrabResult->GrabSucceeded())
{
// Access the image data.
//cout << "SizeX: " << ptrGrabResult->GetWidth() << endl;
//cout << "SizeY: " << ptrGrabResult->GetHeight() << endl;
const uint8_t *pImageBuffer = (uint8_t *)ptrGrabResult->GetBuffer();
//cout << "Gray value of first pixel: " << (uint32_t)pImageBuffer[0] << endl << endl;
formatConverter.Convert(pylonImage, ptrGrabResult);
// Create an OpenCV image out of pylon image
openCvImage = cv::Mat(ptrGrabResult->GetHeight(), ptrGrabResult->GetWidth(), CV_8UC3, (uint8_t *)pylonImage.GetBuffer());
bool ProcessResult;
ProcessResult= imageProcessmain(openCvImage);
if (ProcessResult )
{
if (c_count == 0)
{
c_count = c_countOfImagesToGrab;
camera.StartGrabbing(c_countOfImagesToGrab);
}
}
else
{
camera.StopGrabbing();
}
#ifdef PYLON_WIN_BUILD
// Display the grabbed image.
//Pylon::DisplayImage(1, ptrGrabResult);
#endif
}
else
{
cout << "Error: " << ptrGrabResult->GetErrorCode() << " " << ptrGrabResult->GetErrorDescription() << endl;
}
}
}
catch (const GenericException &e)
{
// Error handling.
cerr << "An exception occurred." << endl
<< e.GetDescription() << endl;
exitCode = 1;
}
// Comment the following two lines to disable waiting on exit.
//cerr << endl << "Press Enter to exit." << endl;
//while (cin.get() != '\n');
// Releases all pylon resources.
PylonTerminate();
return exitCode;
}