?【?聲明:版權所有,歡迎轉載,請勿用于商業用途。 聯系信箱:feixiaoxing @163.com】
? ? ? ? 關于linux camera,一般都是認為是mipi camera,或者是usb camera。當然不管是哪一種,底層的邏輯都是v4l2,這一點大家都一樣。只不過如果使用mipi camera,不僅要適配i2c驅動、mipi驅動、isp驅動,而且相關的協議手冊、驅動代碼,soc芯片廠家也未必提供的,這一點就比較麻煩。相比較而言,usb camera容易很多,sensor側的i2c、mipi已經不用自己處理,isp也是usb camera內部的mcu處理好了,所以剩下來的工作,就是usb uvc協議處理。這是一個標準協議。用起來比較方便,也不需要安裝額外的驅動,一般linux kernel都包含在內了。
? ? ? ? 在linux上面要獲取圖像有兩種軟件接口,一種就是借助于opencv來處理;另外一種就是自己編寫對應的v4l2接口。
1、opencv接口
? ? ? ? opencv是我們能夠想到的,最簡單、最直接的方法。不管是windows平臺,還是linux平臺,都可以通過opencv來獲取圖像。獲取視頻的流程基本就是三步。第一步,創建cv::VideoCapture對象。這個對象的輸入參數可以是阿拉伯數字,也可以是具體的文件名。如果是后一種情況,那么就變成從視頻讀取數據了。
? ? ? ? 第二步,確認設備是否打開。這一步就是調用一下isOpened()函數即可。第三步,就是直接從cv::VideoCapture導出圖像給cv::Mat,導出的方法使用的運算符>>,非常形象。
#include <opencv2/opencv.hpp>
#include <iostream>//#pragma comment(lib, "D:/software/opencv/build/x64/vc16/lib/opencv_world480d.lib")int main()
{cv::VideoCapture cap(0);if (!cap.isOpened()) {return -1;}cv::Mat frame; while (true) {cap >> frame;if (frame.empty()) {break;}cv::imshow("video", frame);if (cv::waitKey(30) == 27) {break;}}cap.release();cv::destroyAllWindows();return 0;
}
2、v4l2接口
? ? ? ? v4l2接口是另外一種用的比較多的方式。和opencv相比較,v4l2肯定處理流程上更加復雜一點,但是好處就是我們可以通過v4l2對攝像頭做更加精準的控制。一種比較通用的情況就是,我們在實際使用的時候,都會關閉自動曝光,然后通過外部補充光源的形式,實現對光源的精確控制,從而可以保證可以穩定輸出高質量的圖片。
? ? ? ? 另外,對于一些自定義的v4l2接口,也是沒有辦法通過opencv來實現的。所以,對于很多稍微有點規模的圖像處理公司來說,它們習慣于自己編寫統一的圖像接口,兼容windows的directshow和linux的v4l2,這樣就不會受到兩個平臺的約束,類似于這樣的api接口,
#ifndef _CAMERA_API_H
#define _CAMERA_API_H#ifdef EXPORTS
#define DLLAPI __declspec(dllexport)
#else
#define DLLAPI __declspec(dllimport)
#endifextern "C"
{
DLLAPI int CameraNumber();
DLLAPI int EnumCameraIndex(char* vid, char* pid, unsigned char CamIndex[32]);
DLLAPI void* CameraOpen(int index, int nWidth = 0, int nHeight = 0, const char* data_type = "");
DLLAPI int CameraClose(void* pCamDev);
DLLAPI int CameraWidth(void* pCamDev);
DLLAPI int CameraHeight(void* pCamDev);
DLLAPI char* CameraDataType(void* pCamDev);
DLLAPI char* CameraName(void* pCamDev);
DLLAPI int CameraQuery(void* pCamDev, unsigned char* szImageBuf);
}#endif