【问题标题】:Segmentation fault (core dumped) with OpenCVOpenCV 的分段错误(核心转储)
【发布时间】:2016-02-17 05:23:09
【问题描述】:

我正在尝试编写一个程序来消除一些连接的组件并保留其余部分。 但是,在代码中的某个位置,程序退出并显示错误消息“Segmentation fault (core dumped)”。

我已将错误范围缩小到以下语句:“destinationImage.at(row, column) = labelImage.at(row, column);”使用检查点你会发现下面的代码。

我已经尝试了所有找到的解决方案,尤其是this one,但没有成功。

请帮忙!

还有一件事,程序正确读取了图像,但没有按照代码显示原始图像。相反,它会打印一条消息“初始化完成 opengl support available”。这正常吗?imshow的实现是在程序结束时执行的,没有错误吗?

/* Goal is to find all related components, eliminate secondary objects*/

#include <opencv2/core/utility.hpp>
#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include <iostream>

using namespace cv;
using namespace std;

//Declaring variables
Mat originalImage;
int conComponentsCount;
int primaryComponents;

//Declaring constants
const char* keys =
{
    "{@image|../data/sample.jpg|image for converting to a grayscale}"  
};

//Functions prototypes, used to be able to define functions AFTER the "main" function
Mat BinarizeImage (Mat &, int thresh);
int AverageCCArea(Mat & CCLabelsStats,int numOfLabels, int minCCSize);
bool ComponentIsIncludedCheck (int ccArea, int referenceCCArea);

//Program mainstream============================================
int main (int argc, const char **argv)
{
    //Waiting for user to enter the required path, default path is defined in "keys" string
    CommandLineParser parser(argc, argv, keys);
    string inputImage = parser.get<string>(0);

    //Reading original image
    //NOTE: the program MUST terminate or loop back if the image was not loaded; functions below use reference to matrices and references CANNOT be null or empty.
    originalImage = imread(inputImage.c_str(), IMREAD_GRAYSCALE);// or: imread(argv[1], CV_LOAD_IMAGE_GRAYSCALE)
    cout << " 1) Loading image done!" << endl;//CHECKPOINT
    if (originalImage.empty())
    {
        cout << "Nothing was loaded!";
        return -1; //terminating program with error feedback
    }

    cout << " 2) Checking for null Image done!" << endl;//CHECKPOINT

    namedWindow("Original Image", 0);
    imshow("Original Image", originalImage);

    cout << " 3) Showing ORIGINAL image done!" << endl;//CHECKPOINT

    //Image Binarization; connectedcomponents function only accepts binary images.
    int threshold=100; //Value chosen empirically.
    Mat binImg = BinarizeImage(originalImage, threshold);

    cout << " 4) Binarizing image done!" << endl;//CHECKPOINT

    //Finding the number of connected components and generating the labeled image.
    Mat labeledImage; //Image with connected components labeled.
    Mat stats, centroids; //Statistics of connected image's components.
    conComponentsCount = connectedComponentsWithStats(binImg, labeledImage, stats, centroids, 4, CV_16U);

    cout << " 5) Connecting pixels done!" << endl;//CHECKPOINT

    //Creating a new matrix to include the final image (without secondary objects)
    Mat destinationImage(labeledImage.size(), CV_16U);
    //Calculating the average of the labeled image components areas
    int ccSizeIncluded = 1000;
    int avgComponentArea = AverageCCArea(stats, conComponentsCount, ccSizeIncluded);

    cout << " 6) Calculating components avg area done!" << endl;//CHECKPOINT

    //Criteria for component sizes
    for (int row = 0; row <= labeledImage.rows; row++)
    {
        cout << " 6a) Starting rows loop iteration # " << row+1 << " done!" << endl;//CHECKPOINT
        for (int column = 0; column <= labeledImage.cols; column++)
        {
            //Criteria for component sizes
            int labelValue = labeledImage.at<int>(row, column);
            if (ComponentIsIncludedCheck (stats.at<int>(labelValue, CC_STAT_AREA), avgComponentArea))
            {
                //Setting pixel value to the "destinationImage"
                destinationImage.at<int>(row, column) = labeledImage.at<int>(row, column);

                cout << " 6b) Setting pixel (" << row << "," << column << ") done!" << endl;//CHECKPOINT
            }
            else
                cout << " 6c) Pixel (" << row << "," << column << ") Skipped!" << endl;//CHECKPOINT
        }
        cout << " 6d) Row " << row << " done!" << endl;//CHECKPOINT
    }

    cout << " 7) Showing FINAL image done!" << endl;//CHECKPOINT

    namedWindow("Final Image", 0);
    imshow("Final Image", destinationImage);

    cout << " 8) Program done!" << endl;//CHECKPOINT

    waitKey (0);
}

//+++++++++++++++++++++++++++++++++++++++++++++++++++
Mat BinarizeImage (Mat & originalImg, int threshold=100) //default value of threshold of grey content.
{
    // Binarization of image to be used in connectedcomponents function. 
    Mat bw = threshold < 128 ? (originalImg < threshold) : (originalImg > threshold);
    return bw;
}

//+++++++++++++++++++++++++++++++++++++++++++++++++++
int AverageCCArea(Mat & CCLabelsStats,int numOfLabels, int minCCSize) //calculates the average area of connected components without components smaller than minCCSize pixels..... reference is used to improve performance, passing-by-reference does not require copying the matrix to this function.
{
    int average;

    for (int i=1; i<=numOfLabels; i++)
    {
        int sum = 0;
        int validComponentsCount = numOfLabels - 1;
        if (CCLabelsStats.at<int>(i, CC_STAT_AREA) >= minCCSize)
        {
            sum += CCLabelsStats.at<int>(i, CC_STAT_AREA);
        }
        else
        {
            validComponentsCount--;
        }
        average = sum / (validComponentsCount);
    }
    return average;
}

//+++++++++++++++++++++++++++++++++++++++++++++++++++
bool ComponentIsIncludedCheck (int ccArea, int referenceCCArea)
{
    if (ccArea >= referenceCCArea)
    {
        return true; //Component should be included in the destination image
    }
    else
    {
        return false; //Component should NOT be included in the destination image
    }
}

【问题讨论】:

    标签: c++ opencv image-processing


    【解决方案1】:

    改变这个:

    for (int row = 0; row <= labeledImage.rows; row++)
    

    到这里:

    for (int row = 0; row < labeledImage.rows; row++)
    

    还有这个:

     for (int column = 0; column <= labeledImage.cols; column++)
    

    到这里:

     for (int column = 0; column < labeledImage.cols; column++)
    

    有什么好处吗?

    (请记住,在 C++ 中,我们从 0 开始计数,因此如果例如 labeledImage.cols == 10,则最后一列是索引为 9 的那一列)

    【讨论】:

    • 问题依然存在。循环迭代 32 次,结果为:“6b)设置像素(0,31)完成!”没有结果是“ 6c) Pixel (row,column) Skipped!”
    • 好吧,在您的情况下,分段错误本质上意味着您正在尝试访问其中一个矩阵中不存在的元素。在您的循环中,您还可以访问destinationImage、labeledImage 和stats。在每次尝试访问它们之前,尝试为每次迭代打印它们的大小和请求的索引。最后打印的值应该是导致问题的值。
    • 在每次访问矩阵并打印尺寸之前,我尝试将 cout 放置在内部循环中,它们是固定的![查看此](s29.postimg.org/64wvpjcfb/smaller_Image_SS.png )。我换了样图,程序根本不会迭代,进入循环前显示分段错误! ![像这样](s2.postimg.org/ozthvbi9l/larger_Image_Screenshot.png)。
    • 问题出在你的循环中,我相信它在这里:stats.at&lt;int&gt;(labelValue, CC_STAT_AREA) 每次迭代的labelValue 和 CC_STAT_AREA 的值是多少? stats 的大小是 5x931,所以每当 labelValue 大于 4 时,你就会遇到分段错误。我敢打赌 labeledImage.at&lt;int&gt;(0,32) 大于 4 ..
    • 我已将“CC_STAT_AREA”更改为使用它的每个位置的行值,现在程序对像素 (3, 495) 工作,然后给出分割错误。在另一个试验中,我删除了所有的“for循环”并查看了labeledImage,它是全黑的!我用的是大图,图片二值化后出现分割错误!
    猜你喜欢
    • 2014-01-23
    • 2015-06-25
    • 2021-06-03
    相关资源
    最近更新 更多