求助,C语言控制自己的摄像头,使其只输出一张图片。

Johnny14117 2020-02-20 11:11:30
能实现题目功能,能在windows10下能运行即可,没什么别的要求,最好用C或C++,别的语言也可接受。
...全文
189 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
liups 2020-02-23
  • 打赏
  • 举报
回复
引用 3 楼 Johnny14117 的回复:
@liups,是的呢,你怎么知道
想过这种方式。 那么楼主是应该研究一下驱动的编写,最后给假的摄像头编写一个驱动就行了
Johnny14117 2020-02-23
  • 打赏
  • 举报
回复
@liups,是的呢,你怎么知道
liups 2020-02-21
  • 打赏
  • 举报
回复
可能楼主需要的是一个虚假的摄像头,提供一个假的画面吧?
apkipa1 2020-02-21
  • 打赏
  • 举报
回复
网上凑了些代码,你可以参考一下:(效果:打开一个控制台和窗口,控制台显示摄像头名称,窗口显示摄像头参数及预览图像。程序会在打开摄像头一秒后将下一帧保存在同目录 output.bmp 中)

// gcc WinMain.c -o WinMain -luser32 -lgdi32 -lvfw32

#include <stdio.h>
#include <Windows.h>
#include <vfw.h>

// 转载来源: https://github.com/godspeed1989/Win32CameraCapture

#define MAX_CAMERA_INDEX 10

static HWND m_hCapWnd[MAX_CAMERA_INDEX];
static CAPDRIVERCAPS m_CapDrvCap[MAX_CAMERA_INDEX];
static CAPSTATUS m_CapStatus[MAX_CAMERA_INDEX];
static CAPTUREPARMS m_Parms[MAX_CAMERA_INDEX];

UINT cm_print_driver_list()
{
	UINT wIndex, wCameraCnt;
	WCHAR szDriverName[80];
	WCHAR szDriverVersion[80];
	wCameraCnt = 0;
	for (wIndex = 0; wIndex < MAX_CAMERA_INDEX; wIndex++)
	{
		if( TRUE == capGetDriverDescriptionW (wIndex,
					szDriverName, sizeof(szDriverName),
					szDriverVersion, sizeof(szDriverVersion)) )
		{
			wprintf(L"[%d] %s - %s\n", wIndex, szDriverName, szDriverVersion);
			wCameraCnt++;
		}
	}
	return wCameraCnt;
}

static BOOL cm_open_internal(UINT idx, HWND hwParent)
{
	// 创建窗口句柄
	m_hCapWnd[idx] = capCreateCaptureWindow("Camera Preview Window", WS_CHILD | WS_VISIBLE, 0, 0, 20000, 20000, hwParent, 0);
	if (!m_hCapWnd)
	{
		printf("m_hCapWnd failed !!!\n");
		return FALSE;
	}
	// 连接第idx号驱动器
	else if (TRUE == capDriverConnect(m_hCapWnd[idx], idx))
	{
		capOverlay(m_hCapWnd[idx], FALSE);
		capPreview(m_hCapWnd[idx], FALSE);
		// 得到驱动器的性能
		memset(&m_CapDrvCap[idx], 0, sizeof(CAPDRIVERCAPS));
		if (FALSE == capDriverGetCaps(m_hCapWnd[idx], &m_CapDrvCap[idx], sizeof(CAPDRIVERCAPS)))
		{
			printf("capDriverGetCaps failed !!!\n");
		}
		else if (m_CapDrvCap[idx].fCaptureInitialized)
		{
			// 初始化成功
			return TRUE;
		}
		else
		{
			printf("fCaptureInitialized failed !!!\n");
		}
	}
	else
	{
		printf("connect failed !!!\n");
	}
	//capCaptureStop(m_hCapWnd[idx]); // 停止捕捉
	//capDriverDisconnect(m_hCapWnd[idx]);
	//DestroyWindow(m_hCapWnd[idx]);
	return FALSE;
}

void cm_close(UINT idx)
{
	capCaptureStop(m_hCapWnd[idx]);
	capCaptureAbort(m_hCapWnd[idx]); // 停止捕获
	capDriverDisconnect(m_hCapWnd[idx]); // 断开捕捉器与驱动器的连接
	DestroyWindow(m_hCapWnd[idx]);
}

BOOL cm_open(UINT idx, HWND hwParent)
{
	BOOL ret = TRUE;
	int n = 0;
	do
	{
		printf("%d try to open %d\n", n, idx);
		Sleep(500);
		ret = cm_open_internal(idx, hwParent);
		n++;
	} while(FALSE == ret && n < 5);
	if (FALSE == ret)
	{
		printf("open failed !!!\n");
	}
	return ret;
}

BOOL cm_get_param(UINT idx, int *width, int *height, int *frame_rate)
{
	BOOL ret = TRUE;
	// 得到设置参数
	ret = capCaptureGetSetup(m_hCapWnd[idx], &m_Parms[idx], sizeof(CAPTUREPARMS));
	if (FALSE == ret)
	{
		printf("capCaptureGetSetup failed !!!\n");
		return ret;
	}
	// 得到驱动器状态
	ret = capGetStatus(m_hCapWnd[idx], &m_CapStatus[idx], sizeof(CAPSTATUS));
	if (FALSE == ret)
	{
		printf("capGetStatus failed !!!\n");
		return ret;
	}
	*width = (int)m_CapStatus[idx].uiImageWidth;
	*height = (int)m_CapStatus[idx].uiImageHeight;
	*frame_rate = (int)1000000 / (int)m_Parms[idx].dwRequestMicroSecPerFrame;

	return ret;
}

BOOL cm_grab_to_bmp(UINT idx, WCHAR *file)
{
	BOOL ret = TRUE;
	// 截获当前图像
	ret = capGrabFrame(m_hCapWnd[idx]);
	if (FALSE == ret)
	{
		printf("capGrabFrame failed !!!\n");
		return ret;
	}
	// 保存到文件
	ret = capFileSaveDIB(m_hCapWnd[idx], file);
	if (FALSE == ret)
	{
		printf("capFileSaveDIB failed !!!\n");
		return ret;
	}
	return ret;
}

BOOL cm_grab_to_clipboard(UINT idx)
{
	BOOL ret = TRUE;
	// 截获当前图像
	ret = capGrabFrame(m_hCapWnd[idx]);
	if (FALSE == ret)
	{
		printf("capGrabFrame failed !!!\n");
		return ret;
	}
	// 保存到剪贴板
	ret = capEditCopy(m_hCapWnd[idx]);
	if (FALSE == ret)
	{
		printf("capEditCopy failed !!!\n");
		return ret;
	}
	return ret;
}

//LRESULT CALLBACK StreamCallbackProc(HWND hCapWnd, LPVIDEOHDR lphdr)
//{
//	return (LRESULT)TRUE;
//}

BOOL cm_start_record(UINT idx, WCHAR *file)
{
	BOOL ret = TRUE;
	// 视频流回调函数
	//ret = capSetCallbackOnVideoStream(m_hCapWnd[idx], StreamCallbackProc);
	//if (FALSE == ret)
	//{
	//	printf("capSetCallbackOnVideoStream failed !!!\n");
	//	return ret;
	//}
	// 设置捕获参数
	capCaptureGetSetup(m_hCapWnd[idx], &m_Parms[idx], sizeof(CAPTUREPARMS));
	m_Parms[idx].fYield = TRUE; // 后台运行
	m_Parms[idx].fCaptureAudio = FALSE; // 无声音
	m_Parms[idx].wTimeLimit = FALSE; // 无时间限制
	capCaptureSetSetup(m_hCapWnd[idx], &m_Parms[idx], sizeof(CAPTUREPARMS));
	// 设置捕获视频的文件
	capFileSetCaptureFile(m_hCapWnd[idx], file);
	// 开始录像线程
	ret = capCaptureSequence(m_hCapWnd[idx]);
	if (FALSE == ret)
	{
		printf("capCaptureSequence failed !!!\n");
		return ret;
	}
	return ret;
}

void cm_stop_record(UINT idx)
{
	//capSetCallbackOnVideoStream(m_hCapWnd[idx], NULL);
	capCaptureStop(m_hCapWnd[idx]);
	capCaptureAbort(m_hCapWnd[idx]);
}

// 转载部分结束

void cm_update_frame(UINT idx) {
	capGrabFrame(m_hCapWnd[idx]);
}

#define BASE_WINDOW_CLASS_NAME "CameraCaptureWindowClass"
#define BASE_WINDOW_NAME "Camera Capture Window"

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
	switch (msg) {
	case WM_DESTROY:
		PostQuitMessage(EXIT_SUCCESS);
		break;
	case WM_TIMER:
		cm_update_frame(0);
		break;
	}
	return DefWindowProc(hwnd, msg, wParam, lParam);
}

ATOM My_RegisterClass(HINSTANCE hInstance) {
	WNDCLASSA WndClass;
	WndClass.cbClsExtra = 0;
	WndClass.cbWndExtra = 0;
	WndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
	WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
	WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
	WndClass.hInstance = hInstance;
	WndClass.lpfnWndProc = WndProc;
	WndClass.lpszClassName = BASE_WINDOW_CLASS_NAME;
	WndClass.lpszMenuName = NULL;
	WndClass.style = 0;
	return RegisterClassA(&WndClass);
}

HWND My_CreateWindow(HINSTANCE hInstance) {
	return CreateWindowA(
		BASE_WINDOW_CLASS_NAME,
		BASE_WINDOW_NAME,
		WS_OVERLAPPEDWINDOW | WS_VISIBLE,
		CW_USEDEFAULT, CW_USEDEFAULT,
		CW_USEDEFAULT, CW_USEDEFAULT,
		NULL,
		NULL,
		hInstance,
		NULL
	);
}

int My_CycleMessage(void) {
	MSG msg;
	while (GetMessageA(&msg, NULL, 0, 0)) {
		TranslateMessage(&msg);
		DispatchMessageA(&msg);
	}
	return (int)msg.wParam;
}

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
	HWND hwnd;
	int nRet;
	
	My_RegisterClass(hInstance);
	hwnd = My_CreateWindow(hInstance);
	UpdateWindow(hwnd);
	{
		cm_print_driver_list();
		cm_open(0, hwnd);
		{
			char str[128];
			int nWidth, nHeight, nFramerate;
			cm_get_param(0, &nWidth, &nHeight, &nFramerate);
			sprintf(str, BASE_WINDOW_NAME " - (%d x %d) %d Hz", nWidth, nHeight, nFramerate);
			SetWindowTextA(hwnd, str);
		}
		UpdateWindow(hwnd);
		Sleep(1000);
		cm_grab_to_bmp(0, "output.bmp");
		SetTimer(hwnd, 123, 200, NULL);
		//cm_close(0);
	}
	
	nRet = My_CycleMessage();
	
	cm_close(0);
	
	return nRet;
}

69,369

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧