网络摄像头图像以C++内存
Webcam images to memory in C++
我需要一种方法来从网络摄像头捕获图像并将其存储在内存中。我正在尝试对象跟踪。(想写我自己,我不想要一个用于跟踪的库。
我不想保存到.bmp然后重新加载到内存中。
我想要一些快速的东西,因为我需要每秒从相机拍摄几次图像。
我真的不想使用像OpenCV这样的东西,因为它对于我的使用来说可能太慢了,并且有许多我并不真正需要的功能。(虽然如果我错了它很慢,我可能会尝试一下。
提前谢谢。
看这里: https://web.archive.org/web/20171127023449/http://www.dreamincode.net/forums/topic/193519-win32-webcam-program/
这应该可以帮助您从网络摄像头获取图像。获得网络摄像头图像后,您可以对其进行任何操作。将其保存到文件或保留缓冲区。轮到你了。
您也可以尝试DirectShow或VLC。
编辑:由于网站链接现已更改
Microsoft捕获视频和音频的文档:https://learn.microsoft.com/en-us/windows/win32/multimedia/using-video-capture
https://github.com/MicrosoftDocs/win32/blob/docs/desktop-src/Multimedia/using-video-capture.md
原始网站的代码是:
// WM_CAP_SET_SCALE is set to true to enable the webcam picture to be resized to the dimensions of our camera window.
// WM_CAP_SET_PREVIEWRATE is set to 66 frames per second.
// To provide a reasonable moving picture without too much demand on resources.
// WM_CAP_SET_PREVIEW is set to true so a picture will be drawn on the camera window camhwnd.
// Calls WM_CAP_DRIVER_DISCONNECT to disconnect the webcam.
// WM_CAP_GRAB_FRAME to capture the Camera frame.
// WM_CAP_EDIT_COPY copies the grabbed frame to the clipboard. Then we copy the clipboard image data to a HBITMAP object called "hbm".
// WM_DESTROY
// Its important we disconnect the webcam if the user closes the window.
// Setup some defines you need to connect to a webcam
// You can put these in a header
// If you are using Microsoft Visual Studio you wont need them as they
// Are included in Microsoft's version of vfw.h
#define WM_CAP_START 0x0400
#define WM_CAP_DRIVER_CONNECT (WM_CAP_START + 10)
#define WM_CAP_DRIVER_DISCONNECT (WM_CAP_START + 11)
#define WM_CAP_EDIT_COPY (WM_CAP_START + 30)
#define WM_CAP_GRAB_FRAME (WM_CAP_START + 60)
#define WM_CAP_SET_SCALE (WM_CAP_START + 53)
#define WM_CAP_SET_PREVIEWRATE (WM_CAP_START + 52)
#define WM_CAP_SET_PREVIEW (WM_CAP_START + 50)
#define WM_CAP_DLG_VIDEOSOURCE (WM_CAP_START + 42)
#define WM_CAP_STOP (WM_CAP_START+ 68)
// End of defines
#include <windows.h>
#include <vfw.h>
// Remember to Link to vfw32 Library, gdi32 Library
LRESULT CALLBACK WindowProc (HWND, UINT, WPARAM, LPARAM);
PBITMAPINFO CreateBitmapInfoStruct(HWND hwnd, HBITMAP hBmp);
void CreateBMPFile(HWND hwnd, LPTSTR pszFile, PBITMAPINFO pbi, HBITMAP hBMP, HDC hDC);
char szAppName [] = TEXT("WebCam");
HWND camhwnd;
HDC hdc ;
HDC hdcMem;
PAINTSTRUCT ps;
HBITMAP hbm;
RECT rc;
//WinMain -- Main Window
int WINAPI WinMain ( HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow )
{
HWND hwnd;
MSG msg;
WNDCLASS wc;
wc.style = CS_HREDRAW|CS_VREDRAW;
wc.lpfnWndProc = WindowProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(GetModuleHandle(NULL), IDI_APPLICATION);
wc.hCursor = LoadCursor (NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH) (COLOR_WINDOW+1);
wc.lpszMenuName = NULL;
wc.lpszClassName = szAppName;
RegisterClass (&wc);
// Create the window
hwnd = CreateWindow (szAppName,szAppName,WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX,CW_USEDEFAULT,CW_USEDEFAULT,300,600,0,0,hInstance,0);
ShowWindow (hwnd,SW_SHOW);
UpdateWindow (hwnd);
while (GetMessage(&msg,0,0,0))
{
if (!IsDialogMessage(hwnd, &msg))
{
TranslateMessage (&msg);
DispatchMessage (&msg);
}
}
return msg.wParam;
}
//Main Window Procedure WindowProc
LRESULT CALLBACK WindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HINSTANCE hInstance = GetModuleHandle(NULL);
//some buttons
HWND hButtStartCam;
HWND hButtStopCam;
HWND hButtGrabFrame;
switch (message) /* handle the messages */
{
case WM_CTLCOLORSTATIC:
SetBkMode(hdc,TRANSPARENT);
return (LRESULT)CreateSolidBrush(0xFFFFFF);
case WM_CREATE:
{
hButtStartCam = CreateWindowEx(0,"BUTTON","Start Camera",WS_CHILD | WS_VISIBLE,
0,0,100,20,hwnd,(HMENU)1,hInstance, 0);
hButtStopCam = CreateWindowEx(0,"BUTTON","Stop Camera",WS_CHILD | WS_VISIBLE,
0,25,100,20,hwnd,(HMENU)2,hInstance, 0);
hButtGrabFrame = CreateWindowEx(0,"BUTTON","Grab Frame",WS_CHILD | WS_VISIBLE,
0,50,100,20,hwnd,(HMENU)3,hInstance, 0);
camhwnd = capCreateCaptureWindow ("camera window", WS_CHILD , 0, 100, 300, 300, hwnd, 0);
SendMessage(camhwnd,WM_CAP_DRIVER_CONNECT,0,0);
SendMessage(camhwnd,WM_CAP_DLG_VIDEOSOURCE,0,0);
break;
}
case WM_COMMAND:
{
switch (LOWORD(wParam))
{
case 1:
{
ShowWindow(camhwnd,SW_SHOW);
SendMessage(camhwnd,WM_CAP_DRIVER_CONNECT,0,0);
SendMessage(camhwnd, WM_CAP_SET_SCALE, true , 0);
SendMessage(camhwnd, WM_CAP_SET_PREVIEWRATE, 66, 0);
SendMessage(camhwnd, WM_CAP_SET_PREVIEW, true , 0);
break;
}
case 2:
{
ShowWindow(camhwnd,SW_HIDE);
SendMessage(camhwnd, WM_CAP_DRIVER_DISCONNECT, 0, 0);
break;
}
case 3:
{
//Grab a Frame
SendMessage(camhwnd, WM_CAP_GRAB_FRAME, 0, 0);
//Copy the frame we have just grabbed to the clipboard
SendMessage(camhwnd, WM_CAP_EDIT_COPY,0,0);
//Copy the clipboard image data to a HBITMAP object called hbm
hdc = BeginPaint(camhwnd, &ps);
hdcMem = CreateCompatibleDC(hdc);
if (hdcMem != NULL)
{
if (OpenClipboard(camhwnd))
{
hbm = (HBITMAP) GetClipboardData(CF_BITMAP);
SelectObject(hdcMem, hbm);
GetClientRect(camhwnd, &rc);
CloseClipboard();
}
}
//Save hbm to a .bmp file called Frame.bmp
PBITMAPINFO pbi = CreateBitmapInfoStruct(hwnd, hbm);
CreateBMPFile(hwnd, "Frame.bmp", pbi, hbm, hdcMem);
SendMessage(camhwnd,WM_CAP_DRIVER_CONNECT,0,0);
SendMessage(camhwnd, WM_CAP_SET_SCALE, true , 0);
SendMessage(camhwnd, WM_CAP_SET_PREVIEWRATE, 66, 0);
SendMessage(camhwnd, WM_CAP_SET_PREVIEW, true , 0);
break;
}
}
break;
}
case WM_DESTROY:
{
SendMessage(camhwnd, WM_CAP_DRIVER_DISCONNECT, 0, 0);
PostQuitMessage(0); /* send a WM_QUIT to the message queue */
break;
}
default: /* for messages that we don't deal with */
return DefWindowProc(hwnd, message, wParam, lParam);
}
return 0;
}
void CreateBMPFile(HWND hwnd, LPTSTR pszFile, PBITMAPINFO pbi, HBITMAP hBMP, HDC hDC)
{
HANDLE hf; // file handle
BITMAPFILEHEADER hdr; // bitmap file-header
PBITMAPINFOHEADER pbih; // bitmap info-header
LPBYTE lpBits; // memory pointer
DWORD dwTotal; // total count of bytes
DWORD cb; // incremental count of bytes
BYTE *hp; // byte pointer
DWORD dwTmp;
pbih = (PBITMAPINFOHEADER) pbi;
lpBits = (LPBYTE) GlobalAlloc(GMEM_FIXED, pbih->biSizeImage);
if (!lpBits)
{
MessageBox(hwnd,"GlobalAlloc","Error", MB_OK );
}
// Retrieve the color table (RGBQUAD array) and the bits
// (array of palette indices) from the DIB.
if (!GetDIBits(hDC, hBMP, 0, (WORD) pbih->biHeight, lpBits, pbi,DIB_RGB_COLORS))
{
MessageBox(hwnd,"GetDIBits","Error",MB_OK );
}
// Create the .BMP file.
hf = CreateFile(pszFile,GENERIC_READ | GENERIC_WRITE,(DWORD) 0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,(HANDLE) NULL);
if (hf == INVALID_HANDLE_VALUE)
{
MessageBox( hwnd,"CreateFile","Error", MB_OK);
}
hdr.bfType = 0x4d42; // File type designator "BM" 0x42 = "B" 0x4d = "M"
// Compute the size of the entire file.
hdr.bfSize = (DWORD) (sizeof(BITMAPFILEHEADER) + pbih->biSize + pbih->biClrUsed * sizeof(RGBQUAD) + pbih->biSizeImage);
hdr.bfReserved1 = 0;
hdr.bfReserved2 = 0;
// Compute the offset to the array of color indices.
hdr.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) + pbih->biSize + pbih->biClrUsed * sizeof (RGBQUAD);
// Copy the BITMAPFILEHEADER into the .BMP file.
if (!WriteFile(hf, (LPVOID) &hdr, sizeof(BITMAPFILEHEADER), (LPDWORD) &dwTmp, NULL) )
{
MessageBox(hwnd,"WriteFileHeader","Error",MB_OK );
}
// Copy the BITMAPINFOHEADER and RGBQUAD array into the file.
if (!WriteFile(hf, (LPVOID) pbih, sizeof(BITMAPINFOHEADER) + pbih->biClrUsed * sizeof (RGBQUAD), (LPDWORD) &dwTmp, NULL))
{
MessageBox(hwnd,"WriteInfoHeader","Error",MB_OK );
}
// Copy the array of color indices into the .BMP file.
dwTotal = cb = pbih->biSizeImage;
hp = lpBits;
if (!WriteFile(hf, (LPSTR) hp, (int) cb, (LPDWORD) &dwTmp,NULL))
{
MessageBox(hwnd,"WriteFile","Error",MB_OK );
}
// Close the .BMP file.
if (!CloseHandle(hf))
{
MessageBox(hwnd,"CloseHandle","Error",MB_OK );
}
// Free memory.
GlobalFree((HGLOBAL)lpBits);
}
PBITMAPINFO CreateBitmapInfoStruct(HWND hwnd, HBITMAP hBmp)
{
BITMAP bmp;
PBITMAPINFO pbmi;
WORD cClrBits;
// Retrieve the bitmap color format, width, and height.
if (!GetObject(hBmp, sizeof(BITMAP), (LPSTR)&bmp))
{
MessageBox(hwnd,"GetObject","Error",MB_OK );
}
// Convert the color format to a count of bits.
cClrBits = (WORD)(bmp.bmPlanes * bmp.bmBitsPixel);
if (cClrBits == 1)
cClrBits = 1;
else if (cClrBits <= 4)
cClrBits = 4;
else if (cClrBits <= 8)
cClrBits = 8;
else if (cClrBits <= 16)
cClrBits = 16;
else if (cClrBits <= 24)
cClrBits = 24;
else cClrBits = 32;
// Allocate memory for the BITMAPINFO structure. (This structure
// contains a BITMAPINFOHEADER structure and an array of RGBQUAD
// data structures.)
if (cClrBits != 24)
{
pbmi = (PBITMAPINFO) LocalAlloc(LPTR,sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * (1<< cClrBits));
}
// There is no RGBQUAD array for the 24-bit-per-pixel format.
else
pbmi = (PBITMAPINFO) LocalAlloc(LPTR, sizeof(BITMAPINFOHEADER));
// Initialize the fields in the BITMAPINFO structure.
pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
pbmi->bmiHeader.biWidth = bmp.bmWidth;
pbmi->bmiHeader.biHeight = bmp.bmHeight;
pbmi->bmiHeader.biPlanes = bmp.bmPlanes;
pbmi->bmiHeader.biBitCount = bmp.bmBitsPixel;
if (cClrBits < 24)
{
pbmi->bmiHeader.biClrUsed = (1<<cClrBits);
}
// If the bitmap is not compressed, set the BI_RGB flag.
pbmi->bmiHeader.biCompression = BI_RGB;
// Compute the number of bytes in the array of color
// indices and store the result in biSizeImage.
// For Windows NT, the width must be DWORD aligned unless
// the bitmap is RLE compressed. This example shows this.
// For Windows 95/98/Me, the width must be WORD aligned unless the
// bitmap is RLE compressed.
pbmi->bmiHeader.biSizeImage = ((pbmi->bmiHeader.biWidth * cClrBits +31) & ~31) /8 * pbmi->bmiHeader.biHeight;
// Set biClrImportant to 0, indicating that all of the
// device colors are important.
pbmi->bmiHeader.biClrImportant = 0;
return pbmi; //return BITMAPINFO
}
相关文章:
- 将字符串存储在c++中的稳定内存中
- C++ 指针的内存地址和指向数组的内存地址如何相同?
- Win32编译器选项和内存分配
- 当vector是tje全局变量时,c++中vector的内存管理
- 带内存和隔离功能的SQLite
- 是否可以通过C++扩展强制多个python进程共享同一内存
- 迭代时从向量和内存中删除对象
- 在C++中打印指向不同基元数据类型的指针的内存地址
- 这个指针和内存代码打印是什么?我不知道是打印垃圾还是如何打印我需要的值
- 多个文件的内存分配错误"在抛出 'std :: bad_alloc' what (): std :: bad_alloc 的实例后终止调用" [C++]
- 为什么示例代码访问IUnknown中已删除的内存
- 如何在C++类内存结构中创建"spacer"?
- 从构造函数抛出异常时如何克服内存泄漏
- malloc() 可能出现内存泄漏
- 如何理解将半精度指针转换为无符号长指针和相关的内存对齐
- 在调用FreeLibrary后,释放动态链接到具有相同版本的CRT堆的DLL的内存
- 如何针对特定情况调试和修复此双自由内存损坏问题
- 类型总是使用其大小存储在内存中吗
- 有没有一种方法可以测量c++程序的运行时内存使用情况
- 有没有一种方法可以使用placement new将堆叠对象分配给分配的内存