You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++安防监控系统中shared_ptr传参后图像栈无数据问题求助

问题分析与解决思路

核心问题定位

你的代码存在多个致命逻辑错误,导致Save函数无法正常读取vector内的帧数据:


1. 多线程资源竞争与未同步

  • 全局Cap_Foscam摄像头对象被Get_New_frame、Display_Images_Real_Time和主线程同时操作,grab()与retrieve()混用会导致帧数据错乱。
  • 全局Image变量被多线程读写,无任何同步机制,会引发内存访问错误,导致存入vector的帧数据损坏。

2. VideoWriter实例冲突

你同时定义了全局和main函数局部两个Output变量:

  • 全局Output初始化时用的是固定的300x300分辨率,和摄像头实际分辨率不匹配。
  • Save函数调用的是全局Output,写入时因尺寸不匹配失败,看起来像vector内无数据。

3. 循环边界逻辑错误

Save函数内的循环条件y <= (size-1)存在风险:当vector为空时,size-1会变成-1,直接跳过循环,无任何输出。

4. 摄像头初始化无效

主线程内的重初始化代码定义了局部Cap_Foscam,对全局摄像头对象无任何影响,若初始摄像头未打开,会陷入死循环。


修复步骤

步骤1:解决多线程同步

使用std::mutex保护摄像头和帧数据的访问,确保同一时间只有一个线程操作:

std::mutex cam_mutex;
// 访问摄像头/Image时加锁
std::lock_guard<std::mutex> lock(cam_mutex);

步骤2:统一VideoWriter实例

删除全局VideoWriter,在main中创建正确分辨率的实例,通过参数传递给Save函数:

// main函数内创建
VideoWriter Output("Output.avi", VideoWriter::fourcc('M', 'J', 'P', 'G'), 10, Size(width, height), true);
// Save函数参数改为引用传递
int Save(std::shared_ptr<Temporary_Stacks> stacks_ptr, bool which_stack, VideoWriter& output)

步骤3:修正循环边界

将Save内的循环条件改为更安全的写法:

for (int y = 0; y < stacks_ptr->Temp_Stack0.size(); y++)

步骤4:修复摄像头初始化

直接操作全局摄像头对象,避免局部变量覆盖:

while (!Cap_Foscam.isOpened())
{
    Cap_Foscam.open(0);
    std::cout << "Connecting..." << std::endl;
    std::this_thread::sleep_for(std::chrono::seconds(1)); // 避免频繁重试
}

步骤5:实现异步保存(按原计划)

若要让Save在独立线程运行,需:

  • 用互斥锁保护vector的读写,避免主线程与保存线程冲突。
  • 用std::thread启动保存线程,注意参数传递需用std::ref传递VideoWriter引用:
std::thread save_thread(Save, Temporary_Stacks_ptr, which_Temp_Stack, std::ref(Output));
save_thread.detach(); // 或用join管理线程生命周期

修复后核心代码片段

#include <thread>
#include <iostream>
#include <vector>
#include <opencv2/videoio/videoio.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/opencv.hpp>
#include <memory>
#include <mutex>
#include <chrono>

using namespace std;
using namespace cv;

std::mutex cam_mutex;
int img_ctr = 0;
const int Temp_Stack_Size = 15;
bool which_Temp_Stack = 0;
Mat Image;

class Temporary_Stacks
{
public:
    std::vector<cv::Mat> Temp_Stack0;
    std::vector<cv::Mat> Temp_Stack1;
};

std::shared_ptr<Temporary_Stacks> Temporary_Stacks_ptr = std::make_shared<Temporary_Stacks>();
cv::VideoCapture Cap_Foscam(0);

int Save(std::shared_ptr<Temporary_Stacks> stacks_ptr, bool which_stack, VideoWriter& output)
{
    std::lock_guard<std::mutex> lock(cam_mutex);
    if (!which_stack)
    {
        for (int y = 0; y < stacks_ptr->Temp_Stack0.size(); y++)
        {
            cout << "HOPES0" << endl;
            output.write(stacks_ptr->Temp_Stack0[y]);
        }
        stacks_ptr->Temp_Stack0.clear();
    }
    else
    {
        for (int y = 0; y < stacks_ptr->Temp_Stack1.size(); y++)
        {
            cout << "HOPES1" << endl;
            output.write(stacks_ptr->Temp_Stack1[y]);
        }
        stacks_ptr->Temp_Stack1.clear();
    }
    return which_stack ? 0 : 1;
}

void Display_Images_Real_Time()
{
    while (1)
    {
        std::lock_guard<std::mutex> lock(cam_mutex);
        if (Cap_Foscam.isOpened() && !Image.empty())
        {
            imshow("Foscam Real Time Feed", Image);
        }
        waitKey(1);
    }
}

int main()
{
    while (!Cap_Foscam.isOpened())
    {
        Cap_Foscam.open(0);
        std::cout << "Connecting..." << std::endl;
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }

    int width = Cap_Foscam.get(CAP_PROP_FRAME_WIDTH);
    int height = Cap_Foscam.get(CAP_PROP_FRAME_HEIGHT);
    Temporary_Stacks_ptr->Temp_Stack0.reserve(Temp_Stack_Size);
    Temporary_Stacks_ptr->Temp_Stack1.reserve(Temp_Stack_Size);

    VideoWriter Output("Output.avi", VideoWriter::fourcc('M', 'J', 'P', 'G'), 10, Size(width, height), true);
    if (!Output.isOpened())
    {
        cout << "Failed to create VideoWriter!" << endl;
        return -1;
    }

    std::thread Real_Time_Video(Display_Images_Real_Time);

    while (1)
    {
        std::lock_guard<std::mutex> lock(cam_mutex);
        if (!Cap_Foscam.grab())
        {
            cout << "Grab failed!" << endl;
            std::this_thread::sleep_for(std::chrono::milliseconds(50));
            continue;
        }

        if (Cap_Foscam.retrieve(Image))
        {
            img_ctr++;
            cout << img_ctr << endl;

            if (img_ctr >= Temp_Stack_Size)
            {
                which_Temp_Stack = Save(Temporary_Stacks_ptr, which_Temp_Stack, Output);
                cout << "Saved" << endl;
                img_ctr = 0;
            }

            if (!which_Temp_Stack)
            {
                Temporary_Stacks_ptr->Temp_Stack0.push_back(Image.clone());
            }
            else
            {
                Temporary_Stacks_ptr->Temp_Stack1.push_back(Image.clone());
            }
        }
        std::this_thread::sleep_for(std::chrono::milliseconds(50));
    }

    Real_Time_Video.join();
    Output.release();
    Cap_Foscam.release();
    return 0;
}

内容的提问来源于stack exchange,提问作者Johnson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 13:24:46