0

Linux ターミナル (Linux では c++) で次のコードをコンパイルし、OpenCv 2.4.3 を使用しています。

ただし、実行時にセグメンテーション違反が発生しており、その理由についてはまったくわかりません。プログラムが特定の段階まで処理されたが無駄だったかどうかを知るために、さまざまな cout ステートメントを配置しました。手伝っていただけませんか?このセグメンテーション違反とは正確には何なのか説明してください。ここで長い間立ち往生しています。

#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <iostream>
#include <stdlib.h>

using namespace cv;
using namespace std;

int main()
{           
    cout<<"check"<<flush;
    Mat src,src_gray,dst;
    int kernel_size = 3;
    int scale = 1;
    int delta = 0;
    int ddepth = CV_16S;
    char* window_name = "sharpness estimate";

    int freq,rows,cols =0;
    double *estimate,*min = 0;
    Point *minLoc,*maxLoc = 0;
    src = imread("/home/siddarth/examplescv/erez images/image53.jpg");
    if( !src.data )
    {
        return -1;
    }

    namedWindow(window_name,CV_WINDOW_AUTOSIZE);
    Mat abs_dst;
    cvtColor(src,src_gray,CV_RGB2GRAY);

    Laplacian(src_gray,dst,ddepth,kernel_size,scale,delta,BORDER_DEFAULT);
    convertScaleAbs(dst, abs_dst);

    minMaxLoc(dst,min,estimate,minLoc,maxLoc,noArray());
    Size s = dst.size();
    rows = s.height;
    cols = s.width;
    cout<<rows<<endl<<cols<<endl;

    for(int i=0;i<=rows;i++)
    {
        for(int j=0;j<=cols;j++)
        {
            if(dst.at<double>(i,j) >= *estimate-100
               && dst.at<double>(i,j) <= *estimate+100)
            {
                cout<<freq++;
            }
        }
    }

    cout<<"estimate :"<<*estimate<<endl;
    cout<<"frequency :"<<freq<<endl;
    imshow(window_name,abs_dst);
    waitKey(1000);
    return 0;   
 }

このコードは、main 関数宣言の直後の最初の「check」print ステートメントを超えていません。それが紛らわしい問題です。しかし、最初の print ステートメントをフラッシュすると、実行されました。私はまだ問題に直面しています。

4

3 に答える 3

4

バッファがフラッシュされるように挿入std::endlしてください。coutこれがおそらく、出力が表示されない理由です。

差し迫った問題の 1 つは、forループが で条件をチェックする<=ことです。ただし、 を使用しatているため、例外がスローされるはずです (このMat型が標準コンテナーのように機能すると仮定します)。

また、いくつかの関数引数 (たとえば、double* estimate) として渡すポインターを多数作成しています。ただし、これは実際にはdoubleオブジェクトではなく、単なるポインターです。それらを渡す関数がdoublefor を割り当てていない限り (そうでないことを願っています)、間違っています。あなたがしているはずです:

double estimate;
minMaxLoc(/* ... */, &estimate, /* ... */);

出力パラメーターを介して取得するすべての値でそれを行う必要があります。

注意すべきもう 1 つの点: Doは に初期化するint i, j = 0;だけで、 には初期化j0ませんi。あなたがする必要がありますint i = 0, j = 0;


さて、イニシャライザの修正が機能する理由を説明します。何が起こるかを確認するには、minMaxLoc の定義を調べる必要がありました。基本的に、関数は次のようなものです。

void setToFive(int* x)
{
  if (x) {
    *x = 5;
  }
}

この関数は へのポインタを取り、intそれintを値 に設定します5。ただし、渡されたポインターが null ポインターの場合、値は設定されません (そうでない場合は、null ポインターを逆参照しているため、未定義の動作が発生します)。基本的にヌルポインタを渡すということは「この値はどうでもいいから渡さないで」ということです。

ポインターを初期化していたとき、次のことを行っていました。

double *estimate, *min = 0;

minこれは、null ポインターにのみ設定されます。は初期化されていないためestimate、その値が null であることに依存することはできません。宣言子ごとに初期化子を提供する必要があります。

double *estimate = 0, *min = 0;
于 2012-12-25T20:10:42.490 に答える
1

@sftrabbit に感謝します。問題は初期化でした。それ以外の

    int freq,rows,cols=0;

変化は

    int freq=0,rows=0,cols=0; 

これにより、セグメンテーション違反が解消されました。あなたの助けをありがとう:)。

于 2012-12-25T20:28:46.453 に答える
1

Linux 環境にいるので、valgrind を使用して、セグメンテーション違反が発生している場所を正確に見つけることができます。プログラムの名前、またはプログラムの実行方法の前に valgrind と入力するだけです。たとえば、次のコマンドでプログラムを実行するとします。

こんにちは-印刷

代わりに次のコマンドを発行します。

valgrind こんにちは-印刷

これはすでに解決されているようですが、これは将来役立つかもしれません!

于 2014-04-12T11:03:23.573 に答える