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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 14:37:05