如何解决OpenCV中的"Access violation reading location"错误?

How to solve "Access violation reading location" error in OpenCV?

本文关键字:violation Access reading location 错误 中的 何解决 解决 OpenCV      更新时间:2023-10-16

我在使用OpenCV进行grabcut时出现以下运行时错误。

"Access violation reading location"

我想做的是给种子从人脸检测器和背景减法器grabcut。
从我的人脸检测器的种子存储在PrFg_seed_FaceExtended(人脸检测矩形延伸到最后一行),Fg_seed_inside_face(一个较小的矩形内的人脸检测)countoursFrame中所有红色的像素都是我想添加到种子中的额外像素。知道怎么做吗?

有趣的是,这个运行时错误是在视频中处理了三帧之后出现的。

如果我排除for循环,我试图将contoursFrame的红色像素标记为GC_PR_FGD,代码似乎工作正常。

contoursFrame只是frame的克隆。我使用contoursFrame上的drawContours函数绘制轮廓。

代码片段:

cv::Mat1b markers(frame.rows,frame.cols);
        cv::Mat1b fg_seed_inside_face = markers(rectangle_inner);
        cv::Mat1b Prfg_seed_FaceExtended = markers(rectangle_outer);
        markers.setTo(cv::GC_PR_BGD);
        Prfg_seed_FaceExtended.setTo(cv::GC_PR_FGD);
        fg_seed_inside_face.setTo(cv::GC_FGD);


        for(i=0;i<frame.rows;i++){
            for(j=0;j<frame.cols;j++){
                if ((contoursFrame.at<Vec3b>(Point(i,j))[0]==0) && (contoursFrame.at<Vec3b>(Point(i,j))[1]==0) && (contoursFrame.at<Vec3b>(Point(i,j))[2]==255)){
                    //cout << "nFound a red pixel";
                    markers.at<uchar>(i,j) = cv::GC_PR_FGD;
                }
            }
        }
        waitKey(100);

        cv::Mat bgd, fgd;
        int iterations = 1;
        cv::grabCut(frame, markers, cv::Rect(), bgd, fgd, iterations, cv::GC_INIT_WITH_MASK);
        cout << "Grabcut Worked!";
        cv::Mat1b mask_fgpf = ( markers == cv::GC_FGD) | ( markers == cv::GC_PR_FGD);

您正在使用Point(int _x, int _y),但根据您的for循环提供(row,col)。除非你有一个方形帧,否则它会崩溃,但是如果列比行多,你将从帧的数据缓冲区中读取更多的数据,可能会更快崩溃。这是因为cv::Mat以行为主的顺序(一行接着另一行)存储数据。

注意at的文档声明了at(int i, int j)at(Point pt)的用法,并指定pt为:

pt – Element position specified as Point(j,i)

这意味着你需要交换ij或者在调用at时不使用Point

我不太确定@chappjc的评论是什么意思,但我认为他确实指出了问题的根源。

通过以下更改解决了这个问题:

if (
    (countoursFrame.at<Vec3b>(i,j).val[0]==0) && 
    (countoursFrame.at<Vec3b>(i,j).val[1]==0) && 
    (countoursFrame.at<Vec3b>(i,j).val[2]==255)
)

基本上,我认为点(I,j)将访问countoursFrame中的第I,j个像素。通过使用val访问像素,我的问题就解决了。