アプリ版:「スタンプのみでお礼する」機能のリリースについて

int main( int argc, char** argv )
{

Mat image = imread("test.png",1 );
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++ )
{
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)
{
Vec3b &ff1 = image.at<Vec3b>(y+mm, x+ll);
new_image.at<Vec3b>(y,x)[0] += ff1[0] / 9;
new_image.at<Vec3b>(y,x)[1] += ff1[1] / 9;
new_image.at<Vec3b>(y,x)[2] += ff1[2] / 9;
}
}
}
}
}

namedWindow("Original Image", 1);
namedWindow("New Image", 1);

imshow("Original Image", image);
imshow("New Image", new_image);

waitKey();
return 0;
}

このコード、なぞカラーで読み込むのはokで、1を0にして、グレーではだめですか?
もしグレーでやりたいのなら、このコードどう修正すればよろしいですか?

どうぞご指導のほどよろしくお願いいたします!

A 回答 (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;
}

この回答への補足

またご指導頂いて、ありがとうございます!
*演算子を実装しなかったのでコンパイルエラーになるのですね、わかりました。
が、自分が*を使いたいのですが、どうすればよろしいですか?
実は自分本当にやる必要あるのは、バイラテラルフィルターをコードで書くこと。
http://imagingsolution.net/imaging/bilateralfilt …
の一番上の計算式、*など使えなければ無理かと思いますが、どうすればよろしいですか?

補足日時:2013/05/04 14:14
    • good
    • 0
この回答へのお礼

コード、大変参考になりました。
昨日ucharどうやってdoubleでやるのを悩んでいますが、これで分かりました。
また、UCHAR_MAXをはじめて知ることができて、ためになりました。
ありがとうございます!!!

お礼日時:2013/05/04 14:20

前の質問(

http://oshiete.goo.ne.jp/qa/8067899.html )で、こう指摘ありましたよね

> また imread() でカラー画像として test.png ファイルを開いているようですが、グレー画像のように画素にアクセスしています(at<uchar>でuchar型の輝度1つごと)。

グレーでやるには、前回の逆です。

Mat.at は直接要素にアクセスするものなので、色の深さや数が合ってないと意味ないです。
グレー8bitでやりたいなら、<uchar>にして1チャンネル分だけの処理にしないと。


単に3x3の平均フィルターをかけるだけなら、blurがあります
http://opencv.jp/opencv-2svn/cpp/imgproc_image_f …



あと、( 前の人の間違いなのですが)
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 );

それぞれ、どんな結果になると思いますか?

この回答への補足

ご回答ありがとうございます。
なぜprintf("ans.=%d\n",(8 + 8 + 8 + 8 + 8 + 8 + 8 + 8 + 8)/9 );が0になりますか?

あと、自分がblurのようなapiをつかずに計算式でフィルターを書くのを勉強していますゆえ。

前回の逆ってつまり?逆というと、私が最初の自分のコードしか思い付かないのですが。しかしそれはエラー

補足日時:2013/05/03 18:55
    • good
    • 0
この回答へのお礼

そして、なぜ
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で、*はだめ、それはなぜですか。

お礼日時:2013/05/03 19:07

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!