【opencv】示例-videocapture_obsensor.cpp 读取和处理通过OBSENSOR摄像头获取的视频流数据...

cpp 复制代码
/**
 * 注意: Astra2、Gemini2 和 Gemini2L 相机目前仅支持 Windows 以及 Linux 内核版本不高于4.15,更高版本的 Linux 内核可能会有异常。
*/


#include <opencv2/videoio.hpp>   // 包含为视频捕捉提供的功能
#include <opencv2/highgui.hpp>   // 包含高层GUI(图形用户界面)功能
#include <opencv2/imgproc.hpp>   // 包含图像处理功能
#include <iostream>              // 包含标准输入输出流库


using namespace cv;              // 使用cv命名空间
int main()
{
    // 尝试打开摄像头
    VideoCapture obsensorCapture(0, CAP_OBSENSOR);
    // 如果摄像头打开失败
    if(!obsensorCapture.isOpened()){
        std::cerr << "Failed to open obsensor capture! Index out of range or no response from device";
        return -1;
    }


    // 获取obsensor相机的内参
    double fx = obsensorCapture.get(CAP_PROP_OBSENSOR_INTRINSIC_FX);
    double fy = obsensorCapture.get(CAP_PROP_OBSENSOR_INTRINSIC_FY);
    double cx = obsensorCapture.get(CAP_PROP_OBSENSOR_INTRINSIC_CX);
    double cy = obsensorCapture.get(CAP_PROP_OBSENSOR_INTRINSIC_CY);
    std::cout << "obsensor camera intrinsic params: fx=" << fx << ", fy=" << fy << ", cx=" << cx << ", cy=" << cy << std::endl;


    Mat image;            // 创建用于存放图像的矩阵
    Mat depthMap;         // 创建用于存放深度图的矩阵
    Mat adjDepthMap;      // 创建用于存放调整后的深度图的矩阵


    // 设置深度值的最小和最大范围
    const double minVal = 300;    // 深度值的最小值
    const double maxVal = 5000;   // 深度值的最大值
    while (true)
    {
        // 注释代码:用于捕获深度图像
        // obsensorCapture >> depthMap;


        // 另一种方法捕获深度图(和bgr彩色图像)。
        if (obsensorCapture.grab())
        {
            if (obsensorCapture.retrieve(image, CAP_OBSENSOR_BGR_IMAGE))
            {
                // 显示RGB彩色图像
                imshow("RGB", image);
            }


            if (obsensorCapture.retrieve(depthMap, CAP_OBSENSOR_DEPTH_MAP))
            {
                // 转换深度图到CV_8U,并进行调整,以便进行可视化
                depthMap.convertTo(adjDepthMap, CV_8U, 255.0 / (maxVal - minVal), -minVal * 255.0 / (maxVal - minVal));
                // 应用颜色映射,使深度图可视化更直观
                applyColorMap(adjDepthMap, adjDepthMap, COLORMAP_JET);
                // 显示调整后的深度图
                imshow("DEPTH", adjDepthMap);
            }


            // 将深度图覆盖在bgr图像上
            static const float alpha = 0.6f;
            if (!image.empty() && !depthMap.empty())
            {
                // 再次调整并转换深度图
                depthMap.convertTo(adjDepthMap, CV_8U, 255.0 / (maxVal - minVal), -minVal * 255.0 / (maxVal - minVal));
                // 改变大小以与彩色图像相匹配
                cv::resize(adjDepthMap, adjDepthMap, cv::Size(image.cols, image.rows));
                for (int i = 0; i < image.rows; i++)
                {
                    for (int j = 0; j < image.cols; j++)
                    {
                        // 混合像素值以获得深度覆盖效果
                        cv::Vec3b& outRgb = image.at<cv::Vec3b>(i, j);
                        uint8_t depthValue = 255 - adjDepthMap.at<uint8_t>(i, j);
                        if (depthValue != 0 && depthValue != 255)
                        {
                            outRgb[0] = (uint8_t)(outRgb[0] * (1.0f - alpha) + depthValue * alpha);
                            outRgb[1] = (uint8_t)(outRgb[1] * (1.0f - alpha) + depthValue *  alpha);
                            outRgb[2] = (uint8_t)(outRgb[2] * (1.0f - alpha) + depthValue *  alpha);
                        }
                    }
                }
                // 显示深度信息叠加到彩色图上的图像
                imshow("DepthToColor", image);
            }
            // 释放图像矩阵占用的内存
            image.release();
            depthMap.release();
        }


        // 如果检测到按键,则退出循环
        if (pollKey() >= 0)
            break;
    }
    return 0;
}

这段代码实现的功能是使用opencv库来读取和处理通过OBSENSOR摄像头获取的视频流数据。它会尝试打开摄像头,读取摄像头的内参,并不断地捕获视频帧和深度信息。视频帧将以RGB的形式显示,深度信息将会通过调整转换成为可视化的彩色深度图,并显示出来。此外,它还提供了将深度图与RGB图像相结合显示的功能,这通过混合两个图像的像素值实现。整个过程将持续进行,直到检测到按键操作为止。

go 复制代码
depthMap.convertTo(adjDepthMap, CV_8U, 255.0 / (maxVal - minVal), -minVal * 255.0 / (maxVal - minVal));

混合像素值以获得深度覆盖效果

cpp 复制代码
// 设置混合的透明度值
static const float alpha = 0.6f; // 可以理解为深度信息在混合中的占比
if (!image.empty() && !depthMap.empty())
{
    // 对深度图进行调整和转换
    depthMap.convertTo(adjDepthMap, CV_8U, 255.0 / (maxVal - minVal), -minVal * 255.0 / (maxVal - minVal));
    // 改变深度图大小以匹配彩色图像的尺寸
    cv::resize(adjDepthMap, adjDepthMap, cv::Size(image.cols, image.rows));
    
    // 遍历图像的每个像素
    for (int i = 0; i < image.rows; i++)
    {
        for (int j = 0; j < image.cols; j++)
        {
            // 获取彩色图像中的像素值
            cv::Vec3b& outRgb = image.at<cv::Vec3b>(i, j);
            // 获取深度图中对应的深度值(通过255减去是为了反转深度值,让高值显得更亮)
            uint8_t depthValue = 255 - adjDepthMap.at<uint8_t>(i, j);
            // 如果深度值有效(非0且非满值)
            if (depthValue != 0 && depthValue != 255)
            {
                // 用alpha值混合原像素值和深度值,更新彩色图像的像素值
                outRgb[0] = (uint8_t)(outRgb[0] * (1.0f - alpha) + depthValue * alpha);
                outRgb[1] = (uint8_t)(outRgb[1] * (1.0f - alpha) + depthValue * alpha);
                outRgb[2] = (uint8_t)(outRgb[2] * (1.0f - alpha) + depthValue * alpha);
            }
        }
    }
    // 显示混合了深度信息的彩色图像
    imshow("DepthToColor", image);
}

在这个代码中,alpha决定了混合时原图像和深度图的占比,alpha越大,则深度图的信息占比越重,覆盖效果越明显;相反,如果alpha较小,则原图的颜色占比较重。通过这种方式,我们可以在彩色图像上"覆盖"深度信息,以视觉上的方式展示出物体的距离信息。

相关推荐
政安晨2 小时前
【嵌入式人工智能产品开发实战】(二十)—— 政安晨:小智AI嵌入式终端代码解读:【B】小智AI嵌入式终端OTA升级功能深度解析
c++·人工智能·嵌入式·ota·小智ai·代码解读·ai聊天助手
pzx_0012 小时前
【深度学习】自定义实现DataSet和DataLoader
开发语言·人工智能·python·深度学习·算法
努力向上的年轻人2 小时前
DeepSeek 与开源:肥沃土壤孕育 AI 硕果
人工智能·gitee·开源·deepseek·飞桨paddlepaddle·昇思mindspore
人工智能教学实践4 小时前
【深度学习】神经网络中,BatchNormalization(批量归一化)层
人工智能·深度学习·神经网络
起个破名想半天了8 小时前
Sklearn入门之datasets的基本用法
人工智能·python·机器学习·sklearn
微小冷8 小时前
微软出品的AI Toolkit,在VS Code中使用DeepSeek
人工智能·microsoft·插件·vs code·deepseek
IT古董8 小时前
【漫话机器学习系列】197.外核(Out of Core)
人工智能·机器学习
AIGC方案8 小时前
免费下载 | 2025天津大学:智能制造与数字孪生技术:面向可持续制造方向发展
人工智能·制造
訾博ZiBo8 小时前
AI日报 - 2025年4月15日
人工智能
yumuing8 小时前
AI 用电脑比你还溜?Agent S2 让复杂任务一键搞定
人工智能·gpt·llm