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

类中调用cv::threshold触发断言错误,主函数中运行正常

OpenCV threshold函数触发buffer_size % 2 == 0断言错误的解决

我实现了一个类成员函数,通过调用cv::threshold检测两张图片的差异,流程为:

  • 将图片加载为cv::Mat
  • 计算图像差异
  • 应用阈值操作
  • 应用膨胀操作
  • 查找轮廓
  • 将符合条件的轮廓存入映射表

但程序执行到cv::threshold函数时触发C断言错误,提示buffer_size % 2 == 0。

原代码

BOOL AI::detectDifferences(std::string firstFileName, std::string secondFileName)
{
    // MatrixImage is just typedef of cv::Mat
    MatrixImage img0 = cv::imread("Assets/Image/popcorn0.jpg", cv::IMREAD_GRAYSCALE);
    MatrixImage img1 = cv::imread("Assets/Image/popcorn1.jpg", cv::IMREAD_GRAYSCALE);

    MatrixImage destination;
    cv::absdiff(img0, img1, destination);

    cv::Mat threshold;
    //cv::threshold(destination, threshold, 0, 255, cv::THRESH_BINARY | cv::THRESH_OTSU);
    cv::threshold(destination, threshold, 0, 255, cv::THRESH_BINARY_INV | cv::THRESH_OTSU);
    
    MatrixImage dilate;
    MatrixImage kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(2, 2), cv::Point(-1, -1));
    cv::dilate(threshold, dilate, kernel, cv::Point(-1, -1), -1);

    std::vector<std::vector<cv::Point>> contours;
    std::vector<cv::Vec4i> hierarchy;

    cv::findContours(dilate, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);

    this->mapVecRect.insert(std::pair<std::string, OpenCVVectorRect*>(secondFileName, new OpenCVVectorRect()));
    for (auto& i : contours)
    {
        if (cv::contourArea(i) > 100)
        {
            cv::Rect rect = cv::boundingRect(i);
            mapVecRect[secondFileName]->push_back(rect);
        }
    }
    return TRUE;
}

问题分析与解决

这个断言错误的核心原因是输入阈值函数的图像数据无效,结合代码细节,主要问题点及修复方案如下:

  1. 硬编码路径未使用函数参数
    原代码直接写死了图片路径,完全忽略传入的firstFileName和secondFileName,如果实际运行时路径不正确,会导致img0或img1为空矩阵,后续absdiff生成的destination也无效,触发阈值函数的断言。

    • 修复:替换硬编码路径为函数参数,并添加加载校验:
      MatrixImage img0 = cv::imread(firstFileName, cv::IMREAD_GRAYSCALE);
      MatrixImage img1 = cv::imread(secondFileName, cv::IMREAD_GRAYSCALE);
      if (img0.empty() || img1.empty()) {
          return FALSE;
      }
      
  2. 未校验图像尺寸一致性
    若两张图片宽高不一致,absdiff生成的矩阵数据结构异常,也会触发后续阈值操作的断言。

    • 修复:添加尺寸校验:
      if (img0.size() != img1.size()) {
          return FALSE;
      }
      
  3. 变量名与函数名冲突
    代码中定义了cv::Mat threshold;,与OpenCV的cv::threshold函数同名,可能导致编译器解析歧义。

    • 修复:重命名变量,比如改为cv::Mat thresh;
  4. 膨胀操作迭代次数错误
    原代码中cv::dilate的最后一个参数为-1,这会导致无限次膨胀操作,必然引发崩溃。

    • 修复:设置合理的迭代次数,比如1

修复后的完整代码

BOOL AI::detectDifferences(std::string firstFileName, std::string secondFileName)
{
    // MatrixImage is just typedef of cv::Mat
    MatrixImage img0 = cv::imread(firstFileName, cv::IMREAD_GRAYSCALE);
    MatrixImage img1 = cv::imread(secondFileName, cv::IMREAD_GRAYSCALE);

    // 校验图像加载是否成功
    if (img0.empty() || img1.empty()) {
        return FALSE;
    }

    // 校验图像尺寸是否一致
    if (img0.size() != img1.size()) {
        return FALSE;
    }

    MatrixImage destination;
    cv::absdiff(img0, img1, destination);

    cv::Mat thresh; // 重命名避免与函数名冲突
    cv::threshold(destination, thresh, 0, 255, cv::THRESH_BINARY_INV | cv::THRESH_OTSU);
    
    MatrixImage dilate;
    MatrixImage kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(2, 2), cv::Point(-1, -1));
    cv::dilate(thresh, dilate, kernel, cv::Point(-1, -1), 1); // 设置合理的迭代次数

    std::vector<std::vector<cv::Point>> contours;
    std::vector<cv::Vec4i> hierarchy;

    cv::findContours(dilate, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);

    this->mapVecRect.insert(std::pair<std::string, OpenCVVectorRect*>(secondFileName, new OpenCVVectorRect()));
    for (auto& i : contours)
    {
        if (cv::contourArea(i) > 100)
        {
            cv::Rect rect = cv::boundingRect(i);
            mapVecRect[secondFileName]->push_back(rect);
        }
    }
    return TRUE;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 21:15:42