6

私のプロジェクトでは、特定の色の最も均一な領域からサイズを取得したいと思います(以下の例では青い空です)。

私の最初のアイデアは、元の画像を変換することです。

元の画像

バイナリイメージに変換し、スカイカラーを検出して、この領域でマスクを作成します。 マスク画像

しかし、どうすればこれらの白いピクセルのサイズと位置を取得できますか?写真の上部1/3に青い空がある場合は、効率的な方法が必要です。何か案は?「グローバルマスク」(コメントの画像3を参照)を作成して、バイナリ画像と比較する必要がありますか?または、もっと簡単な方法はありますか?

ありがとうございました。

4

1 に答える 1

6

アルゴリズムは次のとおりです。

  1. 入力画像をYCbCr色空間に変換します。これは、青(および赤)の色を検出するのに 適しています。YCrCb画像 ある画像を別の色空間に変換するには、cvtColorを使用します。
  2. そこから青いチャンネルを抽出する: 青い画像 関数extractChannelを使用して、必要なチャンネルを抽出します。
  3. 青色の値が最大[0-255]の領域を検出します。関数minMaxIdxを使用してから、 0.8で最大値を乗算しました(これはしきい値です)。ヒストグラム分析など、より複雑な方法を使用できます。
  4. 青色のマスクを作成します。 バイナリ このために、ステップ3のしきい値(パラメーターとして)で計算されたしきい値関数を使用しました。
  5. マスク内のすべての青い輪郭を見つけます。OpenCVでは簡単です-findContoursを使用するだけです。
  6. そして最後に、最大の正方形の輪郭を検出し、その座標(中心)を見つけます。最大の正方形の等高線を計算するには、関数contourAreaを使用できます。

また、手順1〜4の代わりに、画像をHSVに変換し、 inRangeを使用して青色を検出することもできます。

これが私のc++の実装です:

Mat inMat = imread("input.jpg"), blueMat, threshMat;

cvtColor(inMat, blueMat, CV_BGR2YCrCb);//convert to YCrCb color space

extractChannel(blueMat, blueMat, 2);//get blue channel

//find max value of blue color
//or you can use histograms
//or more complex mathod
double blueMax;
minMaxIdx(blueMat, 0, &blueMax);

blueMax *= 0.8;
//make binary mask
threshold(blueMat, threshMat, blueMax, 255, THRESH_BINARY);

//finding all blue contours:
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
findContours(blueMat, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);

double maxSquare = 0;
vector<Point> maxContour;
//finding contours with biggest square:
for (size_t i=0; i<contours.size(); i++)
{
    double square = contourArea(contours[i]);
    if (square > maxSquare)
    {
        maxContour = contours[i];
        maxSquare = square;
    }
}

//output results:
Point center = centerPolygon(maxContour);
cout << "square = " << maxSquare << endl;
cout << "position: x: " << center.x << ", y: " << center.y << endl;

centerPolygon関数は次のとおりです。

Point centerPolygon(const vector<Point>& points)
{
    int x=0, y=0;

    for (size_t i=0; i<points.size(); i++)
    {
        x += points[i].x;
        y += points[i].y;
    }

    return Point(x/points.size(), y/points.size());
}

プログラムの出力は次のとおりです。

square = 263525
position: x: 318, y: 208

このコードをJavaCVに変換できます-このチュートリアルを参照してください。

于 2012-06-26T17:20:34.367 に答える