一种windows下简单的USB摄像头图像获取方式

  • Post author:
  • Post category:其他


随着人工智能的大火,计算机视觉(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/



版权声明:本文为atp1992原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。