随着人工智能的大火,计算机视觉(computer vision)技术也热了起来,在很多所谓的人工智能领域大放光彩,尤其是模式识别,图像分类,而这也少不了对USB摄像头的图像的获取操作,然而我在起初寻找usb摄像头图像的获取方法时竟费了一番周折,通常的做法实在是不方便。
一种常见的方法是用DirectShow, 这里有相关链接
https://github.com/5455945/VideoCapture
另一种是用opencv、openGL实现的,网上也有很多相关的代码示例。
但是上面这两种都需要额外安装库,有没有能直接引用lib或者dll就能工作的“绿色”方式,当然是有的:videoinput:
http://www.muonics.net/school/spring05/videoInput/
https://github.com/ofTheo/videoInput
不过github上的demo还是有点麻烦,其实我们想用的一般很简单,就是获取图片,并没有更多的要求,这里我给出一个demo,就是获取usb摄像头的图像字节信息并绘制在对话框上。
主要代码如下:
unsigned char *Scrbuffer;
int V_W = 640;
int V_H = 480;
bool m_bExit;
unsigned char *Buffer = new unsigned char[V_W*V_H * 3];
Scrbuffer = Buffer;
videoInput video;
int deviceID = 0;//the index of camera, if there is only one camera, deviceID is 0
if (!video.setupDevice(deviceID, V_W, V_H))
{
CString strMsg("无法打开摄像头!");
AfxMessageBox(strMsg);
}
while (true)
{
if (video.isFrameNew(deviceID))
{
video.getPixels(deviceID, Buffer, false, true);//get pixels of a frame
pDlg->VdoFrameData(0, Buffer, V_W*V_H * 3, param);
}
}
//you must stop device here before thread exit, otherwise it will cause some system problems
//and the thread will not release the camera resources
//which makes any other thread can't open the camera even untill the system restarts
video.stopDevice(deviceID);
delete[]Buffer;
为了实际可用,demo里另开了个线程完成上述功能,完善了线程同步,如退出通知,公共变量互斥,并完成了图像绘制。
图像绘制代码:
CPaintDC dc(this);
CDC m_dcMem;
CBitmap m_bmpMem;
CBitmap * m_pOldBmp;
CRect m_rtClient;
GetClientRect(&m_rtClient);
m_dcMem.CreateCompatibleDC(&dc);
Gdiplus::Graphics m_pGraph(m_dcMem.m_hDC);
m_bmpMem.CreateCompatibleBitmap(&dc, m_rtClient.Width(), m_rtClient.Height());
m_pOldBmp = m_dcMem.SelectObject(&m_bmpMem);
m_pGraph.SetSmoothingMode(Gdiplus::SmoothingModeHighQuality);//抗锯齿
EnterCriticalSection(&m_csBuffer);
DrawPixels(m_dcMem,Scrbuffer, V_W, V_H);
LeaveCriticalSection(&m_csBuffer);
dc.BitBlt(0, 0, m_rtClient.Width(), m_rtClient.Height(), &m_dcMem, 0, 0, SRCCOPY);//将内存DC上的图象拷贝到前台
m_pGraph.ReleaseHDC(dc.GetSafeHdc());
m_dcMem.SelectObject(m_pOldBmp);
m_bmpMem.DeleteObject();
m_dcMem.DeleteDC();
int CUSBCameraDemoDlg::DrawPixels(CDC& m_dcMem,unsigned char* pPixels,int nWidth,int nHeight , bool bMirror=false){
CDC memDC;
memDC.CreateCompatibleDC(&m_dcMem);
CRect m_rtClient;
GetClientRect(&m_rtClient);
CBitmap bmpMem;
bmpMem.CreateCompatibleBitmap(&m_dcMem, nWidth,nHeight);
BITMAP bmp;
bmpMem.GetBitmap(&bmp);
int pixelBits = bmp.bmBitsPixel;
int pixelBytes = pixelBits / 8;
DWORD dwSize = bmp.bmHeight * bmp.bmWidthBytes;
unsigned char* pBits = new unsigned char[dwSize];
int i, j;
for (i = 0; i < bmp.bmHeight; i++){
for (j = 0; j < bmp.bmWidth; j++){
//24bits format: BGR
//32bits format: BGRA
unsigned char * pPixelStart = pBits + i*bmp.bmWidthBytes + j* pixelBytes;
unsigned char * pSrcStart = pPixels + i* bmp.bmWidth*3 + (bMirror?(bmp.bmWidth - j):j)*3;
pPixelStart[0] = pSrcStart[0];
pPixelStart[1] = pSrcStart[1];
pPixelStart[2] = pSrcStart[2];
pPixelStart[3] = 0;
}
}
bmpMem.SetBitmapBits(dwSize,pBits);
CBitmap* pOldBmp = memDC.SelectObject(&bmpMem);
m_dcMem.StretchBlt(0, 0, m_rtClient.Width(), m_rtClient.Height(), &memDC,0,0,nWidth ,nHeight,SRCCOPY);
memDC.SelectObject(pOldBmp);
delete[] pBits;
bmpMem.DeleteObject();
memDC.DeleteDC();
//DrawImage("Capture1.jpg", m_rtClient);
//m_dcMem.SetBkColor(RGB(0, 255, 255));
return 0;
}
demo示意图:
demo下载:
https://download.csdn.net/download/atp1992/10518895
原博客:
http://www.straka.cn/blog/capture-image-through-usb-camera/