ペトリ皿 (または他の円形容器) 内の小動物を追跡するアプリケーションを開発しています。追跡が行われる前に、最初の数フレームを使用して領域を定義します。各皿は、円形の独立した静的領域に一致します (つまり、追跡中に更新されません)。ユーザーは、元の画像から料理を見つけて領域として使用するようにプログラムに要求できます。
以下に例を示します。
このタスクを実行するために、私はHough Circle Transformを使用しています。しかし、実際には、ユーザーごとに設定やイメージが大きく異なるため、ユーザーにパラメーターを手動で定義するように依頼したくありません。すべてのパラメーターを推測することもできません。
ただし、使用したい追加情報があります。
検出される円の正確な数を知っています。
- すべての円はほぼ同じ大きさです。
- 円は重ねることができません。
- 円の最小サイズと最大サイズの大まかなアイデアがあります。
- 円は完全に画像内になければなりません。
したがって、定義するパラメーターの数を 1 つに絞り込むことができます:しきい値。これらの情報を使用し、N 個の円を見つける必要があることを考慮すると、現在の解決策は、しきい値の多くの値をテストし、標準偏差が最小である円を維持することです(すべての円が同様のサイズである必要があるため)。
//at this point, minRad and maxRad were calculated from the size of the image and the number of circles to find.
//assuming circles should altogether fill more than 1/3 of the images but cannot be altogether larger than the image.
//N is the integer number of circles to find.
//img is the picture of the scene (filtered).
//the vectors containing the detected circles and the --so far-- best circles found.
std::vector<cv::Vec3f> circles, bestCircles;
//the score of the --so far-- best set of circles
double bestSsem = 0;
for(int t=5; t<400 ; t=t+2){
//Apply Hough Circles with the threshold t
cv::HoughCircles(img, circles, CV_HOUGH_GRADIENT, 3, minRad*2, t,3, minRad, maxRad );
if(circles.size() >= N){
//call a routine to give a score to this set of circles according to the similarity of their radii
double ssem = scoreSetOfCircles(circles,N);
//if no circles are recorded yet, or if the score of this set of circles is higher than the former best
if( bestCircles.size() < N || ssem > bestSsem){
//this set become the temporary best set of circles
bestCircles=circles;
bestSsem=ssem;
}
}
}
と:
//the methods to assess how good is a set of circle (the more similar the circles are, the higher is ssem)
double scoreSetOfCircles(std::vector<cv::Vec3f> circles, int N){
double ssem=0, sum = 0;
double mean;
for(unsigned int j=0;j<N;j++){
sum = sum + circles[j][2];
}
mean = sum/N;
for(unsigned int j=0;j<N;j++){
double em = mean - circles[j][2];
ssem = 1/(ssem + em*em);
}
return ssem;
}
最初のパスの結果を使用して [minRad:maxRad] 間隔を狭めるこのアルゴリズムを繰り返した 2 番目のパスを実行することで、より高い精度に達しました。
たとえば、minRad2 = 0.95 * 最良の円の平均半径と maxRad2 = 1.05 * 最良の円の平均半径です。
これまでのところ、この方法を使用してかなり良い結果が得られました。しかし、それは遅く、かなり汚れています。私の質問は次のとおりです。
- この問題をよりクリーンで高速な方法で解決するための代替アルゴリズムはありますか?
- または、このアルゴリズムを改善するために何を提案しますか?
- 一般化されたハフ変換を調査する必要があると思いますか?
回答と提案をありがとうございます。