簡介
某些項目需求使用多臺相機同時拍攝某個場景不同角度的圖片,比如製作黑客帝國電影中的“子彈時間”那樣的視頻效果。或者需要拍攝一線產線完整的圖片,因爲一個相機的視角有限,拍攝不到完整的產線情況。這個時候我們可以使用多個相機來進行拍攝。
實現原理
工業相機一般帶有輸入輸出光耦IO,輸入光耦IO可以當成觸發進行觸發拍照,輸出光耦IO可以輸出我們需要的信號。我們把多臺相機的輸入IO連接到一起,就能起到同時觸發的作用。需要拍照的時候只需要有一個機械開關給相機發個光耦開關信號即可。如果需要軟件來控制是否拍照,則只需要將輸出光耦IO接到輸入光耦IO。需要拍照的時候,軟件控制輸出光耦IO信號。
簡單框架,畫冊得不好,光耦IO那部分也簡化了,大家莫怪。
代碼
下面使用3臺雲鑰科技的GigE網絡工業相機UGSMT500C和CKSDK來進行開發。相機像框圖中分別命名爲Camera0, Camera1, Camera2。
// MultiCameraSnapshot.cpp : 定義控制檯應用程序的入口點。
//
#include "stdafx.h"
#include <windows.h>
#include "CKCameraInterface.h"
#include "opencv2/opencv.hpp"
#ifdef _DEBUG
#pragma comment(lib, "opencv_world347d.lib")
#else
#pragma comment(lib, "opencv_world347d.lib")
#endif
#ifdef WIN32
#pragma comment(lib, "CKCameraDLL.lib")
#else
#pragma comment(lib, "CKCameraDLL_x64.lib")
#endif
int main()
{
int nCameraNum;
CameraSdkStatus status;
status = CameraEnumerateDevice(&nCameraNum);
if (status == CAMERA_STATUS_SUCCESS)
return -1;
if (nCameraNum != 3)
{
printf("Don't find 3 cameras");
return -1;
}
bool isSuccess = TRUE;
HANDLE hCamera[3] = { NULL, NULL, NULL };
for (int i = 0; i < 3; i++)
{
char cameraFriendlyName[32];
sprintf_s(cameraFriendlyName, "Camera%d", i);
status = CameraInitEx2(&hCamera[i], cameraFriendlyName);
if (status == CAMERA_STATUS_SUCCESS)
{
printf("Open camera %s failed.\n", cameraFriendlyName);
isSuccess = FALSE;
break;
}
//設置圖像輸出格式
status |= CameraSetIspOutFormat(hCamera[i], CAMERA_MEDIA_TYPE_RGB8);
//如果是網絡相機,設置網絡相機最大傳輸大小
unsigned long deviceID = 0;
CameraGetDeviceType(hCamera, &deviceID);
if (deviceID == DEVICE_TYPE_GIGE)
{
status |= CameraGigeSetTransPacketSize(hCamera[i], 9014);
}
//設置曝光和增益
status |= CameraSetAeState(hCamera[i], 0);
status |= CameraSetExposureTime(hCamera[i], 30'000);
status |= CameraSetAnalogGain(hCamera[i], 1'000);
//設置輸入IO爲觸發模式
status |= CameraSetInputIOMode(hCamera[i], 0, IOMODE_TRIG_INPUT);
status |= CameraSetTriggerJitterTime(hCamera[i], 0, 0);
status |= CameraSetTriggerSignalType(hCamera[i], 0, EXT_TRIG_LEADING_EDGE);
//如果是Camera0, 則設置輸出IO爲普通IO輸出
if (strcmp(cameraFriendlyName, "Camera0") == 0)
{
status |= CameraSetOutputIOMode(hCamera[i], 0, IOMODE_GP_OUTPUT);
status |= CameraSetOutputIOState(hCamera[i], 0, 0);
}
//設置硬件觸發模式
status |= CameraSetTriggerMode(hCamera[i], 2);
status |= CameraSetTriggerFrameCount(hCamera[i], 1);
status |= CameraSetTriggerDelayTime(hCamera[i], 0);
if (status != CAMERA_STATUS_SUCCESS)
{
isSuccess = FALSE;
break;
}
}
//判斷是不是某個相機初始化沒有成功,如果沒有成功,則將所有已經成功打開的相機反初始化
if (!isSuccess)
{
for (int i = 0; i < 3; i++)
{
if (hCamera[i] != NULL)
{
CameraUnInit(hCamera[i]);
}
}
return -1;
}
cv::namedWindow("Camera0");
cv::namedWindow("Camera1");
cv::namedWindow("Camera2");
while (1)
{
//Camera0相機輸出一個上升沿信號
CameraSetOutputIOState(hCamera[0], 0, 1);
CameraSetOutputIOState(hCamera[0], 0, 0);
for (int i = 0; i < 3; i++)
{
stImageInfo imgInfo;
BYTE *pImgData = CameraGetImageBufferEx(hCamera, &imgInfo, 1000);
if(pImgData == NULL)
continue;
//使用opencv將圖片顯示在三個窗口中,雖然三個相機是順序讀取的,但是他們是在同一時刻拍照的
cv::Mat image(imgInfo.iHeight, imgInfo.iWidth, CV_8UC3, pImgData);
if (i == 0)
{
cv::imshow("Camera0", image);
}
else if (i == 1)
{
cv::imshow("Camera1", image);
}
else
{
cv::imshow("Camera2", image);
}
//這裏只是將三個相機同的圖像同步顯示出來,大家也可以運用做其它的事情。。。。。
}
int key = cv::waitKey(0);
if (key == 27)
break;
}
cv::destroyAllWindows();
for (int i = 0; i < 3; i++)
{
CameraUnInit(hCamera[i]);
}
return 0;
}
歡迎大家使用雲鑰科技的相機,有USB2.0、USB3.0、GIGE網絡工 業相機,支持軟硬件定製開發