类中调用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; }
问题分析与解决
这个断言错误的核心原因是输入阈值函数的图像数据无效,结合代码细节,主要问题点及修复方案如下:
硬编码路径未使用函数参数
原代码直接写死了图片路径,完全忽略传入的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; }
- 修复:替换硬编码路径为函数参数,并添加加载校验:
未校验图像尺寸一致性
若两张图片宽高不一致,absdiff生成的矩阵数据结构异常,也会触发后续阈值操作的断言。- 修复:添加尺寸校验:
if (img0.size() != img1.size()) { return FALSE; }
- 修复:添加尺寸校验:
变量名与函数名冲突
代码中定义了cv::Mat threshold;,与OpenCV的cv::threshold函数同名,可能导致编译器解析歧义。- 修复:重命名变量,比如改为
cv::Mat thresh;
- 修复:重命名变量,比如改为
膨胀操作迭代次数错误
原代码中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
相关产品推荐
相关产品推荐

