OpenCV C++调用CornerHarris访问Mat对象时出现段错误
问题分析与解决:OpenCV CornerHarris C++版本段错误
核心问题定位
段错误触发于dst.at<double>(i,j)的内存访问,关键原因有两个:
1. 整数除法导致阈值逻辑失效
corners_perc是int类型(值为1),C++中1/100属于整数除法,结果为0,导致corners_perc/100*maxVal始终等于0,会误判大量像素为角点,虽不是段错误直接原因,但会引发后续逻辑异常。
2. 矩阵类型不匹配引发内存越界
cornerHarris函数的输出矩阵dst默认是**CV_32F(32位浮点数)**类型,你使用dst.at<double>(i,j)访问时,因类型不匹配直接越界访问内存,触发段错误。
修复后的完整代码
#include <opencv2/opencv.hpp> #include <opencv2/highgui.hpp> #include <opencv2/imgproc.hpp> #include <stdio.h> #include <iostream> using namespace cv; using namespace std; string type2str(int type) { string r; uchar depth = type & CV_MAT_DEPTH_MASK; uchar chans = 1 + (type >> CV_CN_SHIFT); switch ( depth ) { case CV_8U: r = "8U"; break; case CV_8S: r = "8S"; break; case CV_16U: r = "16U"; break; case CV_16S: r = "16S"; break; case CV_32S: r = "32S"; break; case CV_32F: r = "32F"; break; case CV_64F: r = "64F"; break; default: r = "User"; break; } r += "C"; r += (chans+'0'); return r; } Mat getcorners(Mat image){ Mat dst, image_gray; Mat imcopy = image.clone(); cvtColor(image, image_gray, COLOR_BGR2GRAY); cornerHarris(image_gray, dst, 3, 3, 0.01); Point minLoc, maxLoc; double minVal, maxVal; minMaxLoc(dst, &minVal, &maxVal, &minLoc, &maxLoc); std::cout<<"Max value in dst mat ="<<maxVal<<std::endl; // 修复1:用浮点数除法计算阈值,避免整数截断 double corners_perc = 1.0; double threshold = (corners_perc / 100.0) * maxVal; // 修复2:用CV_32F对应的float类型访问dst矩阵 for(int i = 0; i<image.rows; i++){ for(int j = 0; j<image.cols; j++){ if(dst.at<float>(i,j) > threshold){ imcopy.at<Vec3b>(i,j)[0] = 0; imcopy.at<Vec3b>(i,j)[1] = 0; imcopy.at<Vec3b>(i,j)[2] = 255; if(i>290){ std::cout<<"values = "<<dst.at<float>(i,j)<<", i = "<<i<<", j = "<<j<<"\n"; } } } } std::cout<<dst.at<float>(1,10)<<std::endl; if(dst.at<float>(1,10) > threshold){ // 修复:imcopy是CV_8UC3类型,需用Vec3b访问 Vec3b pixel = imcopy.at<Vec3b>(1,10); std::cout<<"values = "<<(int)pixel[0]<<", "<<(int)pixel[1]<<", "<<(int)pixel[2]<<"\n"; } std::cout<<"Image values = "<<imcopy.at<Vec3b>(200,450)<<"\n"; std::cout<<"Image cols = "<<imcopy.cols<<"x"<<imcopy.rows<<"\n"<<"Color: "<<imcopy.at<Vec3b>(imcopy.rows-1, imcopy.cols-1)<<"\n"; std::cout<<"Dst vals = "<<type2str(dst.type())<<"\n"<<type2str(imcopy.type())<<"\n"; // 修复:移除错误的int类型访问,改用float std::cout<<"Sample dst value: "<<dst.at<float>(449,460)<<"\n"; return imcopy; } int main(int argc, char** argv) { if (argc != 2) { printf("usage: DisplayImage.out <Image_Path>\n"); return -1; } Mat image, image_gray, image_corners; image = imread(argv[1], 1); if (!image.data) {printf("No image data \n"); return -1;} std::cout<<"Image size = "<<image.size()<<", test = "<<image.size[0]<<"X"<<image.size[1]<<std::endl; image_corners = getcorners(image); namedWindow("Display Image", WINDOW_AUTOSIZE); imshow("Display Image", image_corners); waitKey(0); return 0; }
额外注意事项
cornerHarris的输出类型默认是CV_32F,如需64位浮点数需手动指定,但32位精度已足够应对角点检测场景。- 访问
Mat元素时,at<T>中的T必须与矩阵的深度类型严格匹配,否则必然引发内存访问错误。 - 涉及比例、小数计算时,务必使用浮点数类型(如将
1改为1.0),避免整数除法的截断行为。
内容的提问来源于stack exchange,提问作者Dushyant Patil
相关产品推荐
相关产品推荐

