4

白黒のみの背景画像の白色点の数を数えたい。私はこのようなコードを持っています:

int count = 0; 
for ( int j = 0; j < Image.rows; j ++ )
    {
    for ( int i = 0; i < Image.cols; i ++ )
        {
            if ( Image.at<int>(i,j) >= 150 )
            {
                count ++ ;
            }
        }
    }

何らかの理由で、上記のコードは機能せず、反応を停止するだけです。チェックしたところ、「if(Image.at(i、j)> = 150)」という行が問題を引き起こしています。私の「画像」は「cv::Mat」で、「CV_8UC3」タイプです。誰かが私を助けることができますか?ありがとうございました。

4

6 に答える 6

11

ロビンの答えに対する私のコメントに加えて、あなたのエラーは、CV_8UC3 タイプのイメージに int としてアクセスしようとしたことです。グレーレベルを確認したい場合は、次のようにします(ロビンの回答のように、「int」ではなく「unsigned char」に注意してください)。

cv::Mat greyscale;
cv::cvtColor(image,grayscale,CV_RGB2GRAY);
// either, most elegant:
int count = cv::countNonZero(greyscale >= 150);
// or, copied from Robin's answer:
int count = 0;
for(int i = 0; i < greyscale.rows; ++i) {
    const unsigned char* row = greyscale.ptr<unsigned char>(i);
    for(int j = 0; j < greyscale.cols; j++) {
        if (row[j] >= 150)
            ++count;
    }
}
于 2012-08-22T11:10:00.310 に答える
5

これはもっときれいだと思います:

Mat result;
threshold(Image,result,150,255,THRESH_BINARY);
int white_count = countNonZero(result);
于 2012-08-22T10:50:01.227 に答える
3

列に i を使用し、行に j を使用している場合は、not と記述してImage.at<unsigned char>(j,i)ください。Image.at<unsigned char>(i,j)

于 2012-08-22T09:45:13.717 に答える
2

列の前に行にアクセスする必要があると思います。つまり、i と j を交換する必要があります。 で
代用if ( Image.at<int>(i,j) >= 150 )if ( Image.at<int>(j,i) >= 150 )

ただし、マットにアクセスする簡単な方法があります。
OpenCV は、使いやすい STL のような反復子を提供します。すべての要素にアクセスしたい場合は、非常に使いやすいです。例:

int count = 0;
MatConstIterator_<int> it = Image.begin<int>(), it_end = Image.end<int>();
for(; it != it_end; ++it)
    if ((*it) >= 150)
        ++count;

最後になりましたが、各行へのポインターを取得し、プレーンな [] 演算子を介してデータにアクセスすることもできます。

int count = 0;
for(int i = 0; i < Image.rows; ++i) {
    const int* Ii = Image.ptr<int>(i);
    for(int j = 0; j < Image.cols; j++) {
        if (Ii[j] >= 150)
            ++count;
    }
}
于 2012-08-22T09:46:52.397 に答える
1

opencv バイト ベクトル (unsigned char ピクセル) で CV_8UC3 ピクセルにアクセスできます。この場合、次のようにすることができます (特別な色のしきい値を使用することもできます)。

int channel = 0;
Image.at<Vec3b>( row , col )[channel]
于 2012-08-22T11:47:01.087 に答える
1

cv::Mat 画像にアクセスする方法はたくさんあります。カラー画像 ( CV_8UC3 ) に直接アクセスしたい場合は、次のように実装できます。

int count = 0;
int threshold = 150;
for(int j = 0; j < img.rows; j++) {
   for(int i = 0; i < img.cols; i++) {
      //white point which means that the point in every channel(BGR)
      //are all higher than threshold!
      if(img.ptr<cv::Vec3b>(j)[i][0] > threshold && 
         img.ptr<cv::Vec3b>(j)[i][1] > threshold 
         img.ptr<cv::Vec3b>(j)[i][2] > threshold ) {
             count++;
         }

    }
 }

ただし、白色点のみをカウントする場合は、画像をグレースケール ( CV_8UC1 ) に変換して、次のようにすることをお勧めします。

cv::Mat img;
cv::cvtColor(src,img,CV_BGR2RGB);
int count = 0;
int threshold = 150;
for(int j = 0; j < img.rows; j++) {
   for(int i = 0; i < img.cols; i++) {
      if(img.ptr<uchar>(j)[i] > threshold) {
            count++;
      }
   }
}

最後に、 img.ptr< Imagetype >による cv::Mat 画像へのアクセスは、アクセスしたポイントが正しいかどうかをチェックしないことに注意してください。そのため、画像の範囲が確実にわかっている場合は、ptr による画像へのアクセスで問題ありません。img.at< Imagetype>()によって、呼び出しのたびにすべてのポイントが正しいことを確認します。なぜ ptr によるイメージへのアクセスが高速なの か、無効なアクセス ポイントがある場合はアサートします!

于 2014-01-25T04:49:30.207 に答える