2012-02-15 17 views
-1

画像内に白い矩形を見つけようとしています。長方形のサイズは固定です。これは私がまだのよう作ってみたものです:私は必要な矩形が(0;0)の初めに近い場合画像内の白い矩形を見つける

BufferedImage bImage = bufferedImage; 
int height = bufferedImage.getHeight(); //~1100px 
int width = bufferedImage.getWidth(); //~1600px 
int neededWidth = width/2; 
int neededHeight = 150; 
int x = 0; 
int y = 0; 
boolean breaker = false; 
boolean found = false; 
int rgb = 0xFF00FF00; 
int fx, fy; 

fx = fy = 0; 
JavaLogger.log.info("width, height: " + w + ", " + h); 
while ((x != (width/2) || y != (height - neededHeight)) && found == false) { 
for (int i = y; i - y < neededHeight + 1; i++) { 
    for (int j = x; j - x < neededWidth + 1; j++) { //Vareetu buut, ka +1 vajadziigs 
     //JavaLogger.log.info("x,y: " + j + ", " + i); 
     long pixel = bImage.getRGB(j, i); 
     if (pixel != colorWhite && pixel != -1) { 
      //bImage.setRGB(j, i, rgb); 
      //JavaLogger.log.info("x,y: " + (j+x) + ", " + (i+y)); 
      breaker = true; 
      break; 

     } else { 
      //bImage.setRGB(j, i, 0xFFFFFF00); 
     } 
     //printPixelARGB(pixel); 
     if ((i - y == neededHeight-10) && j - x == neededWidth-10) { 
      JavaLogger.log.info("width, height: " + x + ", " + y + "," + j + ", " + i); 
      fx = j; 
      fy = i; 
      found = true; 
      breaker = true; 
      break; 
     } 
    } 
    if (breaker) { 
     breaker = false; 
     break; 
    } 

} 

if (x < (width/2)) { 
    x++; 
} else { 
    if (y < (height - neededHeight)) { 
     y++; 
     x = 0; 
    } else { 
     break; 
    } 
    } 
//JavaLogger.log.info("width, height: " + x + ", " + y); 
} 

if (found == true) { 

    for (int i = y; i < fy; i++) { 
     for (int j = x; j < fx; j++) { 
      bImage.setRGB(j, i, 0xFF00FF3F); 
     } 

    } 

} 
JavaLogger.log.info("width, height: " + w + ", " + h); 

これは、[OK]を動作しますが、それはさらに逃げるように、パフォーマンスはかなり厳しく低下します。何かできることがあれば、私は疑問に思いますか?

たとえば、この検索には8秒近くかかりました。これはかなり大変です。 One of searches 私は、これがもっと効果的に行えると思っています。たぶん、いくつかのブロブを見つけるかもしれない?それについて読むが、私はどのようにそれを適用するか分からない。

また、私はJavaと画像処理の両方に新しいので、どんな助けもありがとうございます。

+2

[SSCCE](http://sscce.org/)を投稿するとすぐに役立ちます。 1,191ピクセル×1,684ピクセルの画像を投稿する必要はありませんでした。あなたは***作物***を聞いたことがありますか? –

+0

これはSSCCEです。コードのすべての部分が問題に関連しています。イメージに関してはそうでした。私は問題の範囲を表示するために全体のイメージを置く。画像が切り取られた場合、底に近づくには時間がかかりません。今それは明らかです。 –

+1

*「これはSSCCEです。」*あなたが望むほど大声で言うが、それは真実ではない。 * "コードのすべての部分が問題に関連しています。" *うーん。それを 'SC'にするために必要なコードの部分はどうですか?あなたが混乱している場合は、コードの長さではありません。あなたは実際にリンクを*読みましたか? * "私は問題の範囲を表示するために全体のイメージを置く。" *あなたのケーキを持って食べるために使うことができる1つの巧妙なトリック(ダウンロード/使用する小さなイメージとテストするための大きなイメージ)は、小さな画像をポストに埋め込み、それを実行時に大きな画像に描画することです。 –

答えて

1

これは非常に粗いですが、画像内のすべての白いピクセルを見つけることができます。必要なサイズですべてが存在することを確認するためにさらにチェックできますが、基本はそこにあります。

PS:私はあなたの画像でテストしていません。 rthis.rcは、画像サイズとpthis.pxは、あなたが「浸食」として知られている操作によって解決することができる求めているどのような内側の矩形サイズ

public static void main(String[] args) { 
    JFrame frame = new JFrame(); 
    final int r = 100; 
    final int p = 10; 

    NewJPanel pan = new NewJPanel(r, p, new A() { 
     @Override 
     public void doImage(BufferedImage i) { 
      int o = 0; 

      for (int j = 0; j < i.getWidth() - p; j++) { 
       for (int k = 0; k < i.getHeight() - p; k++) { 

        PixelGrabber pix2 = new PixelGrabber(
          i, j, k, p, p, false); 
        try { 
         pix2.grabPixels(); 
        } catch (InterruptedException ex) {} 

        int pixelColor = pix2.getColorModel() 
          .getRGB(pix2.getPixels()); 

        Color c = new Color(pixelColor); 
        if (c.equals(Color.WHITE)) { 
         System.out.println("Found at : x:" + j + ",y:" + k); 
        } 

       } 
      } 
     } 
    }); 

    frame.getContentPane().add(pan); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    frame.setSize(500, 500); 
    frame.setLocationRelativeTo(null); 
    frame.setVisible(true); 
} 

private interface A { 
    void doImage(BufferedImage i); 
} 

private static class NewJPanel extends JPanel { 
    private static final long serialVersionUID = -5348356640373105209L; 

    private BufferedImage image = null; 
    private int px; 
    private int rc; 
    private A a; 

    public NewJPanel(int r, int p, A a) { 
     this.px = p; 
     this.rc = r; 
     this.a = a; 
    } 

    public BufferedImage getImage() { 
     return image; 
    } 

    @Override public void paint(Graphics g) { 
     super.paint(g); 

     image = new BufferedImage(this.rc, this.rc, 
       BufferedImage.TYPE_INT_ARGB); 
     java.awt.Graphics2D g2 = image.createGraphics(); 

     g2.setColor(Color.BLACK); 
     g2.fillRect(0, 0, this.rc, this.rc); 
     g2.setColor(Color.WHITE); 
     g2.fillRect(
       new Random().nextInt(this.rc - this.px), 
       new Random().nextInt(this.rc - this.px), 
       this.px, this.px); 

     g.drawImage(image, this.rc, this.rc, this); 
     this.a.doImage(this.image); 
    } 
} 
0

私は専門家ではありませんが、コードは問題ではないと思います。アルゴリズムを変更する必要があります。私は再帰的に2D平面上の単一の白画素を探索することにより開始すると、何かのように:

findWhitePixel(正方形)の「広場」の途中でピクセルの{ 見て - それは白のリターンそれはそう、だ場合: findWhitePixel (正方形の右上四分の一) findWhitePixel(「四角」の左上四角) findWhitePixel(「四角」の右下隅) findWhitePixel(「四角」の左下四角) }

白いピクセルが見つかったら、その上から下、左下、右に向かって、枠線を見つけてください。与えられたものであれば、矩形しかないことができます。他の形状(三角、円など)がある場合は、ここで何らかの確認が必要です。

+0

アルゴリズムはどのように検索プロセスをスピードアップしますか?私が見ているように、1つの画素に何度も近づく必要があります。 –

+0

白い矩形の相対的なサイズに応じて、白い矩形を叩く前に、一握りのピクセルにしか行きません。 – Rami

0

です。侵食は、その場所(左上隅)で要求されたサイズの矩形内のすべてのピクセルのうち、最も暗いピクセルですべてのピクセルを置き換えます。ここで、最も暗いとは、非白色が白色に優先することを意味する。

エロージョンの出力は、W-1列とH-1行の少ないイメージです。その中の白いピクセルは解決策に対応します。

矩形の幸運なケースでは、侵食は分離可能な操作です。これは、最初に水平セグメント形状を使用して侵食され、次に最初の侵食の出力で垂直セグメント形状が侵食されることを意味します。 W×Hの扇形サイズの場合、これはW * Hの操作をW + Hで置き替えます。

バイナリイメージ(非白または白)の幸運なケースでも、セグメントによる侵食は非常に効率的に実行できます。すべての行で独立して、連続するすべての白ピクセルを検索し、W-1右端のものから白以外のものへ。すべての列に同じ操作を行い、白いランをH-1ピクセルだけ短くします。

例:すべての3×2の矩形を見つける:3×侵食後

####....#### 
##.....#..## 
#..######... 
.....###.... 

:1×侵食後

####..#### 
##...##### 
#########. 
...#####.. 

を:

####.##### 
########## 
#########. 

このアルゴリズムは、画素ごとに一定の時間を要する(かかわらず長方形のサイズ)。適切に実装するには、数ミリ秒かかるでしょう。

関連する問題