この質問の場合:図の背景色を検出するための適切なアルゴリズムはありますか?、すべてのピクセルを同じ色のグループに分離できるように、塗りつぶしアルゴリズムを作成する必要があります。
これを再帰的に実行しましたが、スタックオーバーフローエラーが発生します。そのため、ここにある反復的なキューベースのアルゴリズムを選択する必要がありました:http://en.wikipedia.org/wiki/Flood_fill#Alternative_implementations
まず、すべてのマトリックス要素(Pixel
クラスのインスタンスである要素)の検索を開始します。
private PixelGroup[] generatePixelGroupsFromMatrix(Pixel[][] matrix) {
PixelGroup[] tempGroups = new PixelGroups[9999999]; // Nevermind the 9999999....
int groupsFound = 0;
Pixel pixel;
for (int y = 0; y < matrix.length; ++y) {
for (int x = 0; x < matrix[0].length; ++x) {
pixel = matrix[y][x];
if (!pixel.evaluated) {
// This pixel has never been evaluated
// Therefore, it belongs to a new group
// First, we make a new group
PixelGroup newGroup = new PixelGroup();
// Begin search for connected pixels with the same color. All pixels found will belong to this new group.
findPixelsConnectedWith(pixel,newGroup);
tempGroups[groupsFound] = newGroup;
++groupsFound;
}
}
}
PixelGroup[] result = new PixelGroup[groupsFound];
for (int i = 0; i < groupsFound; ++i) {
result[i] = tempGroups[i];
}
return result;
}
したがって、Pixel
次の値があります:x、y、評価済み(ブール値)および色(整数)。次に、PixelGroup
は単にピクセルを保持できるクラスです(動作します)。
そして、これは私に問題を与えている方法です:
private void findPixelsConnectedWith(Pixel pixel, GroupOfPixels group) {
QueueOfPixels queue = new QueueOfPixels();
queue.add(pixel);
Pixel currentPixel;
int x,y;
Pixel neighbor;
while((currentPixel = queue.nextPixel()) != null) {
if (currentPixel.color == pixel.color && !currentPixel.evaluated) {
// This pixel has the required color, and has not been evaluated. It meets our needs.
// Add to group.
group.addPixel(currentPixel);
// Flag it as evaluated. So in the future, it will be ignored.
currentPixel.evaluated = true;
// Evaluate all 8 possible directions to find neighbor pixels
int[] xDirections = {0,1,1,1,0,-1,-1,-1};
int[] yDirections = {-1,-1,0,1,1,1,0,-1};
for (int i = 0; i < 8; ++i) {
x = xDirections[i];
y = yDirections[i];
if (pixelExists(currentPixel.y + y,currentPixel.x + x)) {
// There exists a pixel in this direction!
neighbor = getPixel(currentPixel.y + y,currentPixel.x + x);
queue.add(neighbor);
}
}
}
}
}
興味があれば、ここに私のQueueOfPixels
クラスがあります。私はベクトルだけで自分自身を作らなければなりませんでした(学校の割り当て要件):https ://codereview.stackexchange.com/questions/17823/vector-based-flood-fill-algorithm-queue-class (私が知る限り、それは単に機能します)。
何が問題ですか?
了解しました。これを5x2ピクセルの画像でテストしました(表示するにはズームインする必要があります):http://i.stack.imgur.com/xV0Lf.gif-最初の行には黒のピクセル、そして2番目は白です。プログラムは、6つのピクセルグループを検出したことを教えてくれます(2つだけであるはずだったのに!)
問題をデバッグするために何を試しましたか?
まず、findPixelsConnectedWithを呼び出す前に、次の行を配置しました。
System.out.println("The pixel (" + x + "," + y + ") has not been evaluated. Evaluating now.");
そしてこれが結果でした:
The pixel (0,0) has not been evaluated. Evaluating now.
The pixel (1,0) has not been evaluated. Evaluating now.
The pixel (2,0) has not been evaluated. Evaluating now.
The pixel (3,0) has not been evaluated. Evaluating now.
The pixel (4,0) has not been evaluated. Evaluating now.
The pixel (0,1) has not been evaluated. Evaluating now.
したがって、ご覧のとおり、最初の行(黒いピクセル)は、その行のすべてのピクセルが評価されていないと見なされるため、コードが機能しないようです((0,0)は評価されたと予想していました)評価および実行されていません)。しかし、2行目で動作を開始すると、期待どおりに動作しているように見えます((0,1)を見つけて、終了します)。
しかし、私はまだ何が起こっているのかを知ることができません。何か案は?
編集:
私getPixel
のpixelExists
機能:
private boolean pixelExists(int y, int x) {
return (y > 0 && y < pixelMatrix.length) && (x > 0 && x < pixelMatrix[0].length);
}
private Pixel getPixel(int y, int x) {
return pixelMatrix[y][x];
}