- ベストアンサー
カラー画像をグレーに変換する方法を教えてください!
- 質問者はOpenCVのコードについて、カラー画像をグレースケールに変換する方法を知りたいとしています。
- また、質問者はコード内の一部を修正してグレースケールに変換する方法についても尋ねています。
- 要約すると、質問者はOpenCVを使用してカラー画像をグレースケールに変換する方法についてのアドバイスを求めています。
- みんなの回答 (2)
- 専門家の回答
質問者が選んだベストアンサー
- ベストアンサー
> あと、( 前の人の間違いなのですが) 一応弁解させていただくと、誤差が大きいことを承知した上で手を抜いたのです。プログラムが動く方が重要だと思ったので。 前の回答は、厳密さという点では、そもそも画像の端っこで値をいくつ合計するかカウントしていません。また計算誤差を問題視するなら、実数で求めて最後に四捨五入するべきでしょうね。 > +がokで、*はだめ、それはなぜですか。 表示結果は確認されましたか。おそらく+も期待される結果ではないのでは。 OpenCVの実装までは確認していないので推測ですが、Vec3bクラスを作った方が*演算子を実装しなかったのでコンパイルエラーになり、+演算子もベクトルの各要素の和を求めるようにはなっていないのでしょう。これは画像処理ではなくC++に関することですね。 上に限らず、この質問はCGIではなくC・C++カテゴリでされた方がよいでしょう。 グレー用に直したコードを載せます。 #include <opencv.hpp> #include <climits> #include <cmath> using namespace cv; int main( int argc, char** argv ) { Mat image = imread("test.png", 0); Mat new_image = Mat::zeros( image.size(), image.type() ); for( int y = 0; y < image.rows; y++ ) { for( int x = 0; x < image.cols; x++ ) { double count = 0.0; double ff1 = 0.0; for( int ll = -1; ll <= 1; ll++ ) { for( int mm = -1; mm <= 1; mm++ ) { if (x+ll >= 0 && x+ll < image.cols && y+mm >= 0 && y+mm < image.rows) { ff1 += static_cast<double> (image.at<uchar>(y+mm, x+ll)); count += 1.0; } } } ff1 = round(ff1 / count); ff1 = (ff1 > UCHAR_MAX) ? UCHAR_MAX : ff1; new_image.at<uchar>(y,x) = ff1; } } namedWindow("Original Image", CV_WINDOW_AUTOSIZE); namedWindow("New Image", CV_WINDOW_AUTOSIZE); imshow("Original Image", image); imshow("New Image", new_image); waitKey(); return 0; }
その他の回答 (1)
- kmee
- ベストアンサー率55% (1857/3366)
前の質問( http://okwave.jp/qa/q8067899.html )で、こう指摘ありましたよね > また imread() でカラー画像として test.png ファイルを開いているようですが、グレー画像のように画素にアクセスしています(at<uchar>でuchar型の輝度1つごと)。 グレーでやるには、前回の逆です。 Mat.at は直接要素にアクセスするものなので、色の深さや数が合ってないと意味ないです。 グレー8bitでやりたいなら、<uchar>にして1チャンネル分だけの処理にしないと。 単に3x3の平均フィルターをかけるだけなら、blurがあります http://opencv.jp/opencv-2svn/cpp/imgproc_image_filtering.html#cv-blur あと、( 前の人の間違いなのですが) new_image.at<Vec3b>(y,x)[0] += ff1[0] / 9; これ、期待した結果が得られません。 printf("ans.=%d\n",8/9 + 8/9 + 8/9 + 8/9 + 8/9 + 8/9 + 8/9 + 8/9 + 8/9 ); printf("ans.=%d\n",(8 + 8 + 8 + 8 + 8 + 8 + 8 + 8 + 8)/9 ); それぞれ、どんな結果になると思いますか?
お礼
そして、なぜ Vec3b &ff1 = image.at<Vec3b>(y+mm, x+ll); new_image.at<Vec3b>(y,x)[0] += ff1[0]*ff1[0]; 。。。 は大丈夫で、あるいは Vec3b &ff1 = image.at<Vec3b>(y+mm, x+ll); Vec3b &ff2= ff1+ff1; new_image.at<Vec3b>(y,x)[0] += ff2[0]; もう大丈夫で、 Vec3b &ff1 = image.at<Vec3b>(y+mm, x+ll); Vec3b &ff2= ff1*ff1; new_image.at<Vec3b>(y,x)[0] += ff2[0]; +がokで、*はだめ、それはなぜですか。
補足
ご回答ありがとうございます。 なぜprintf("ans.=%d\n",(8 + 8 + 8 + 8 + 8 + 8 + 8 + 8 + 8)/9 );が0になりますか? あと、自分がblurのようなapiをつかずに計算式でフィルターを書くのを勉強していますゆえ。 前回の逆ってつまり?逆というと、私が最初の自分のコードしか思い付かないのですが。しかしそれはエラー
お礼
コード、大変参考になりました。 昨日ucharどうやってdoubleでやるのを悩んでいますが、これで分かりました。 また、UCHAR_MAXをはじめて知ることができて、ためになりました。 ありがとうございます!!!
補足
またご指導頂いて、ありがとうございます! *演算子を実装しなかったのでコンパイルエラーになるのですね、わかりました。 が、自分が*を使いたいのですが、どうすればよろしいですか? 実は自分本当にやる必要あるのは、バイラテラルフィルターをコードで書くこと。 http://imagingsolution.net/imaging/bilateralfilter/ の一番上の計算式、*など使えなければ無理かと思いますが、どうすればよろしいですか?