开启辅助访问 切换到宽版

精易论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

用微信号发送消息登录论坛

新人指南 邀请好友注册 - 我关注人的新帖 教你赚取精币 - 每日签到


求职/招聘- 论坛接单- 开发者大厅

论坛版规 总版规 - 建议/投诉 - 应聘版主 - 精华帖总集 积分说明 - 禁言标准 - 有奖举报

查看: 200|回复: 6
收起左侧

[C#源码] C++纯API实现调用摄像头(可指定编号)

[复制链接]
结帖率:100% (1/1)
发表于 前天 03:13 | 显示全部楼层 |阅读模式   广东省东莞市
本帖最后由 精意源码 于 2025-8-8 18:24 编辑

不知道大家遇到需要调用摄像头的情况需要如何处理呢?
一般情况py/c++我会使用CV库,易语言只能上网找模块了,但是易语言的调用摄像头模块效率极低并且相关例子极少,十分不友好!

其次,用py使用cv库编译后文件>50mb,c++没试过但是也不会少到哪去,因为要内嵌CV的DLL库,而这个库是非常大的
c++的优势本身有速度快编译文件小,如果对图像处理需求不大,那么调用CV库就太麻烦且难受了!
所以我开发了这个C++纯API实现调用摄像头
多的不说,直接看编译后的使用例子,
编译器使用 VS2022 ,
1.载入sln文件进入IDE后按shuft+Alt+B即可直接编译(编译文件名以“摄像头C++”为例)
2.在x64\Release文件夹中找到编译后的exe文件
3.在当前文件使用cd导航终端到当前目录
4.输入“摄像头C++.exe”可查看具体命令格式
equipment # 输出摄像头设备数和名称
photograph [100|1-99] [cam_index] # 拍一张PNG(100)或JPG(1-99)照片 将在终端输出base64编码
photostreams [100|1-99] [cam_index] # 持续拍PNG(100)或JPG(1-99)照片 将在终端输出base64编码

使用示例1:
[Shell] 纯文本查看 复制代码
摄像头C++\x64\Release>摄像头C++ photograph 99 0

解释:用摄像头编号 0 拍摄一张清晰度为99 %的JPG照片
终端会直接拍照并且直接输出base64编码

使用示例2:
摄像头C++\x64\Release>摄像头C++ equipment
检测到摄像头数 :1
  摄像头[0]: HP Truevision HD


因为网络问题无法上传附件这边就用lanzy吧,拿了吱一声

代码已经采用模块化,可以通过自己引用函数自定义功能,需要定制私聊我(QQ2157660868),如果反响好我会继续优化,目前仅满足我自己的需求!


https://wwtw.lanzn.com/iBBwm32xqpdi



[md]# 摄像头API集成与使用说明

## 功能简介
本组件基于 DirectShow 封装,支持 Windows 下摄像头采集一帧并保存为 BMP 图片,或直接获取内存中的位图数据。

## 文件说明
- `capture_camera.h`:摄像头API头文件,声明初始化、拍照、释放、获取内存数据等接口。
- `capture_camera.cpp`:摄像头API实现文件。
- `main.cpp`:调用示例,演示如何拍照并保存为 bmp,或获取内存数据后自行保存。

## 集成步骤
1. 将 `capture_camera.h` 和 `capture_camera.cpp` 添加到你的 Visual Studio 项目中。
2. 在你的代码中 `#include "capture_camera.h"`。
3. 链接 `strmiids.lib`,项目属性->链接器->输入->附加依赖项,添加 `strmiids.lib`。
4. 确保项目字符集为“使用多字节字符集”。

## 接口说明
- `void* camera_init();`  
  初始化摄像头,返回句柄,失败返回 NULL。**只需初始化一次,可多次采集。**
- `int camera_capture(void* handle, const char* filename);`  
  拍照并保存为 bmp 文件,返回 0 成功,非 0 失败。**可多次调用,无需重复初始化。**
- `unsigned char* camera_capture_buffer(void* handle, int* width, int* height, int* stride);`  
  拍照并返回 BGR 格式位图数据(不带 BMP 头),成功返回数据指针,失败返回 NULL。宽、高、步长通过参数返回。数据需调用者用 delete[] 释放。**可多次调用。**
- `void camera_release(void* handle);`  
  释放摄像头资源。
- `int camera_enum_devices(char names[][256], int max_count);`  
  获取摄像头数量,并可选输出摄像头名称列表(names为char[256]数组,max_count为最大数量,传NULL仅返回数量)。

## 示例代码:获取内存位图数据并保存为 BMP
```cpp
#define _CRT_SECURE_NO_WARNINGS
#include "capture_camera.h"
#include <iostream>
#include <cstdio>

// 保存BGR数据为BMP文件
bool SaveBitmapToFile(unsigned char* pBuffer, int width, int height, int stride, const char* filename) {
    BITMAPFILEHEADER bfh = {0};
    BITMAPINFOHEADER bih = {0};
    bfh.bfType = 0x4d42; // 'BM'
    bfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
    bfh.bfSize = bfh.bfOffBits + stride * height;
    bih.biSize = sizeof(BITMAPINFOHEADER);
    bih.biWidth = width;
    bih.biHeight = -height; // 正向
    bih.biPlanes = 1;
    bih.biBitCount = 24;
    bih.biCompression = BI_RGB;
    bih.biSizeImage = stride * height;
    FILE* fp = fopen(filename, "wb");
    if (!fp) return false;
    fwrite(&bfh, sizeof(bfh), 1, fp);
    fwrite(&bih, sizeof(bih), 1, fp);
    fwrite(pBuffer, stride * height, 1, fp);
    fclose(fp);
    return true;
}

int main() {
    char names[16][256] = {0};
    int cam_count = camera_enum_devices(names, 16);
    std::cout << "检测到摄像头数量: " << cam_count << std::endl;
    for (int i = 0; i < cam_count; ++i) {
        std::cout << "  摄像头[" << i << "]: " << names << std::endl;
    }
    void* cam = camera_init();
    if (!cam) {
        std::cout << "摄像头初始化失败\n";
        return -1;
    }
    int w = 0, h = 0, stride = 0;
    // 连续采集3张图片
    for (int i = 0; i < 3; ++i) {
        unsigned char* data = camera_capture_buffer(cam, &w, &h, &stride);
        if (data) {
            char fname[32];
            sprintf(fname, "capture_%d.bmp", i+1);
            std::cout << "采集成功,宽:" << w << " 高:" << h << " 步长:" << stride << std::endl;
            if (SaveBitmapToFile(data, w, h, stride, fname)) {
                std::cout << "已保存为 " << fname << "\n";
            } else {
                std::cout << "保存文件失败\n";
            }
            delete[] data;
        } else {
            std::cout << "采集失败!\n";
        }
    }
    camera_release(cam);
    return 0;
}
```

## 常见问题
- **如何判断采集是否成功?**
  - camera_capture_buffer 返回非 NULL 即为成功。
- **如何连续采集多张图片?**
  - 只需初始化一次摄像头(camera_init),然后多次调用 camera_capture 或 camera_capture_buffer 即可,无需重复初始化和释放。
- **fopen 警告**:已在实现文件和示例顶部加 `#define _CRT_SECURE_NO_WARNINGS`,无需担心。
- **字符集问题**:建议保存所有源文件为 UTF-8 编码,避免中文乱码。
- **找不到 SampleGrabber/相关类型**:请确保 `capture_camera.h` 已包含所有相关声明。

## 依赖环境
- Windows 7/10/11
- Visual Studio 2013 及以上
- 需要安装 Windows SDK(DirectShow 组件)

拿了吱一声,反应好我会做成DLL版本
结帖率:38% (3/8)

签到天数: 5 天

发表于 前天 18:12 | 显示全部楼层   伊朗
感谢分享。做成DLL版本更好。
回复 支持 反对

使用道具 举报

结帖率:100% (1/1)

签到天数: 4 天

 楼主| 发表于 前天 18:09 | 显示全部楼层   广东省东莞市

可以用不?
回复 支持 反对

使用道具 举报

签到天数: 5 天

发表于 前天 17:55 | 显示全部楼层   山西省运城市
大佬66666666666666
回复 支持 反对

使用道具 举报

签到天数: 9 天

发表于 前天 10:44 | 显示全部楼层   河北省石家庄市
感谢分享
回复 支持 反对

使用道具 举报

结帖率:100% (1/1)

签到天数: 4 天

 楼主| 发表于 前天 03:18 | 显示全部楼层   广东省东莞市
反响好我会改为DLL版本
回复 支持 反对

使用道具 举报

结帖率:100% (1/1)

签到天数: 4 天

 楼主| 发表于 前天 03:16 | 显示全部楼层   广东省东莞市
需要二改请阅读capture_camera_usage.md开发文档
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 致发广告者

发布主题 收藏帖子 返回列表

sitemap| 易语言源码| 易语言教程| 易语言论坛| 易语言模块| 手机版| 广告投放| 精易论坛
拒绝任何人以任何形式在本论坛发表与中华人民共和国法律相抵触的言论,本站内容均为会员发表,并不代表精易立场!
论坛帖子内容仅用于技术交流学习和研究的目的,严禁用于非法目的,否则造成一切后果自负!如帖子内容侵害到你的权益,请联系我们!
防范网络诈骗,远离网络犯罪 违法和不良信息举报QQ: 793400750,邮箱:wp@125.la
网站简介:精易论坛成立于2009年,是一个程序设计学习交流技术论坛,隶属于揭阳市揭东区精易科技有限公司所有。
Powered by Discuz! X3.4 揭阳市揭东区精易科技有限公司 ( 粤ICP备2025452707号) 粤公网安备 44522102000125 增值电信业务经营许可证 粤B2-20192173

快速回复 返回顶部 返回列表