2017-11-09 19 views
3

空の行列hide_imageをゼロ値で作成します。 内容は正しいです - 672x896各要素は値で埋める必要があります、私はループでそれを行います。しかし(0, 299)要素コードに例外をスロー:cv :: cv :: Matオブジェクトをループしている間のメモリ位置の例外

Unhandled exception at 0x00007FFD3C063C58 in stego.exe: Microsoft C++ exception: cv::Exception at memory location 0x000000D2B033E5F0. occurred 

私は、関数をデバッグし、例外がループでJ値の依存することが分かりました。私はjを設定することができます< 299と問題なく動作するプログラムが、私はすべての行列が必要です。コマンドラインでは、私はこのメッセージが表示さ:

OpenCV Error: Assertion failed ((unsigned)(i1 * DataType<_Tp>::channels) < 
(unsigned)(size.p[1] * channels())) in cv::Mat::at, file c:\opencv- 
3.3.1\opencv\build\include\opencv2\core\mat.inl.hpp, line 1095 

は可能かもしれ、それが原因で間違った行列の初期化の起こるのが、なぜそこに右のdimentionsを示していますか?行は正しい番号で、jをに設定すると、ループはi = 671で終了します。しかし列は少なく、数字299は何にも依存していないようです。

cv::Mat hide_image; 
int hide_image_cols = 0, hide_image_rows = 0; 
int i_current = 0, j_current = 15; 
int curr_bit = 0; 

get_img_dim(image, hide_image_cols, hide_image_rows); 

hide_image = cv::Mat(hide_image_rows, hide_image_cols, CV_8U); 
hide_image = cv::Mat::zeros(hide_image_rows, hide_image_cols, CV_8U); 
std::cout << (hide_image.at<cv::Vec3b>(671, 299)) << std::endl; // exception 

for (int i = 0; i < hide_image.rows; i++) 
for (int j = 0; j < hide_image.cols; j++) { 
//exception when j>298 
std::cout << (hide_image.at<cv::Vec3b>(i, j)) << std::endl; 
} 

なぜこの例外が発生するのですか?

答えて

2

をすれば、問題は行列データタイプとあなたが要素にアクセスしている方法である必要はありません。

Matを初期化するとき、チャンネル数が指定されていない場合、OpenCVはデフォルトで1つのチャンネルを想定します。つまり、CV_8Uというデータ型を指定した場合、hide_imageCV_8UC1となります。

ループでは、行列要素がCV_8UC3であることを前提としたデータ型cv::Vec3bを使用して行列要素にアクセスしています。あなたの場合、意図した1バイトではなく、一度に3バイトをジャンプさせることによって、行列全体を反復処理しています。

このシナリオでは、番号299は実際にコードをクラッシュする際に重要な役割を果たします。行列の列数はに等しい。298 * 3 = 894であり、インデックス894がhide_imageの有効なメモリアドレスに対応しているため、コードはインデックス298まで機能するはずです。 jが299の場合、ループは299 * 3 = 897にアクセスしようとします。これにより、境界外のメモリアクセスが発生します。

したがって、このシナリオの解決方法は、初期化と要素アクセスのデータ型が同じであることを確認することです。だから次のいずれかがうまくいくはずです。

3つのチャネルで入力行列を作成します。

hide_image = cv::Mat::zeros(hide_image_rows, hide_image_cols, CV_8UC3); 

OR

アクセスのような単一のチャネル行列の正しいデータ型を持つ要素:

std::cout << (hide_image.at<unsigned char>(i, j)) << std::endl; 
3

あなたが8ビットピクセル表現(1つのチャネル)であるCV_8Uを使用する初期化中...マトリックスを通して初期化とループする

の異なるタイプを使用しています。

hide_image = cv::Mat(hide_image_rows, hide_image_cols, CV_8U); 
hide_image = cv::Mat::zeros(hide_image_rows, hide_image_cols, CV_8U); 

次に、ピクセル当たり24ビット(CV_8UC3に相当)であるVec3bを使用します。したがって、データを3倍高速化すると、データが不足し、セグメンテーションエラーが発生する可能性があります。代わりにCV_8UCV_8UC3

初期化したりucharの代わりVec3bを使用します。

for (int i = 0; i < hide_image.rows; i++) 
    for (int j = 0; j < hide_image.cols; j++) { 
    //exception when j>298 
    std::cout << (hide_image.at<cv::Vec3b>(i, j)) << std::endl; 
    } 

あなたは何を行うことができます。

ところで、このライン

hide_image = cv::Mat(hide_image_rows, hide_image_cols, CV_8U); 

は、あなたが次の行

hide_image = cv::Mat::zeros(hide_image_rows, hide_image_cols, CV_8U); 
関連する問題