none
ハンドルされていない例外が発生しました

    質問

  • お世話になっております
    visual studio2010で画像のR,G,B値を処理してグレイスケール化を行うプログラムでビルドした際に、

    ビルド成功と表示はされるのですが、

    0x00311a27 でハンドルされていない例外が発生しました: 0xC0000005: 場所 0x03892156 に書き込み中にアクセス違反が発生しました。

    というエラーが起きて中断してしまいます。

    おそらく問題があるソースコードはこの部分だと思われるのですが、どう変更したら良いのか分かりません。よろしくお願いいたします。

    //R,G,B値を処理<グレイスケール化)
    d = saturate_cast<uchar>(0.299 * r1 + 0.587 * g1 + 0.114 * b1);
    image2.at<uchar>(x,y)=d;
    }

    2017年10月23日 7:13

すべての返信

  • 書き込み位置が不正なのではないでしょうか。

    >image2.at<uchar>(x,y)=d;

    のxとyは画像のピクセル位置として合理的な範囲に入っているか調べてみてはどうでしょう。

    質問とは関係ない蛇足ですが、
    R、G、Bが同値(=そもそもグレー)の場合には誤差が大きくなるかもしれませんので、RGBの内の
    どれかを採用した方が良いかもしれません。
    ×また、切り捨て代入でなく、四捨五入した方が良い結果になるかもしれません。
    佐祐理さんによるとsaturate_castで十分なはず(最も近い整数に丸められる)とのことです。
    誤った発言をしてしまいました。ご容赦ください。

    2017年10月23日 7:24
  • 御指摘有難うございます。
    調べてみたのですが、範囲に入っていると思われるのですが、x,yのピクセル位置を変更したほうがよいでしょうか?
    一応、ソースを表示しておきます。

    #include"stdafx.h"
    #include<opencv2/highgui/highgui.hpp>
    #include<opencv2/imgproc/imgproc.hpp>
    using namespace cv;


     int main(int argc, char* argv[]) 
     {
    //--------原画像を読み込む---------
    Mat image1 = imread("res_hi.tif");
        namedWindow("原画像");
    imshow("原画像",image1);

    //-----------汎用の処理方法を使う--------
    int x,y;
    uchar r1, g1, b1, d;
    Vec3b color1;
    int width = image1.cols;
    int height = image1.rows;
    Mat image2 = Mat(Size(width,height),CV_8UC1); //この設定が必要
    for(y = 0;y < height ; y++)
    for(x = 0; x < width; x++)
    {
    //ピクセル値(カラー)を取得
    color1 = image1.at<Vec3b>(y,x);
    //R,G,B値に分解
    r1 = color1[2];
    g1 = color1[1];
    b1 = color1[0];
    //R,G,B値を処理<グレイスケール化)
    d = saturate_cast<uchar>(0.299 * r1 + 0.587 * g1 + 0.114 * b1);
    image2.at<uchar>(x,y)=d;
    }
    namedWindow("グレイ化画像(RGB分解)");
    imshow("グレイ化画像(RGB分解)",image2);

    //cvtColorでグレイ化する
    Mat image3;
    cvtColor(image1,image3,CV_BGR2GRAY);
    namedWindow("グレイ化画像(vctColor)");
    imshow("グレイ化(vctColor)",image3);

    //読みこみ時にグレイ化する
    Mat image4 = imread("res_hi.tif",IMREAD_GRAYSCALE);
    namedWindow("グレイ化画像(読み込み時)");
    imshow("グレイ化(読み込み時)",image4);

    waitKey(0);
    destroyAllWindows();

    return 0;
     }

    2017年10月23日 7:34
  • saturate_cast

    パラメータが浮動小数点数であり,変換後の型が整数(8ビット,16ビット,32ビット)である場合,この浮動小数点数は,まず最も近い整数値に丸められてから,必要ならば切り詰められます(変換後の型が,8ビットあるいは16ビット整数の場合).

    とのことですが、切り捨てられているのでしょうか?

    2017年10月23日 7:36
  • > color1 = image1.at<Vec3b>(y,x);
    > image2.at<uchar>(x,y)=d;

    アクセスしている座標が対称でないように見受けられます。

    • 回答の候補に設定 佐祐理 2017年10月23日 12:50
    2017年10月23日 7:45
  • OpenCVは詳しくありませんが、この手のライブラリにありがちな罠は

    1.画像の縦横、XとY、関数引数の順番などが、想像と違ってる罠。
    2.マニュアルの説明順番と、実際の引数の順番が異なる罠。

    などに注意して、もう一度確認してみてはどうでしょう。

    • 回答の候補に設定 佐祐理 2017年10月23日 12:50
    2017年10月23日 7:47
  • ご指摘ありがとうございます。そうであれば問題ありません。
    「最も近い整数」が望むものになると思います。
    以前の発言を訂正しました。
    2017年10月23日 7:50
  • image2.at<uchar>(x,y)=d;

    皆様からご指摘されているように、cv::Mat::at<T>の引数はrow, colの順番です。(ドキュメントはこちらです。)
    そのため、上記の引数の順番は(x, y)ではなく(y, x)です。

    Mat image1 = imread("res_hi.tif");
    Mat image4 = imread("res_hi.tif",IMREAD_GRAYSCALE);

    また、cv::imread()のあとに画像を正常に読み込めたかどうかを確認するとよいでしょう。
    (cv::Mat::empty()で確認できます。)




    2017年10月24日 3:34
  • であれば、
    > image2.at<uchar>(x,y)=d;
    の、方は本当に x、yの順番ですか。
    非常に疑わしいと思われます。

    2017年10月24日 3:45