Javaで画像処理(その6)
今回は、線の起点・終点や交点等を探査する特徴点抽出をやってみる。
■ソースコード
特徴点を保持するFeatureクラスと特徴点を探査するFeatureFinderクラスを書く。
・Feature.java
package test; public class Feature { private int x; private int y; private int order; private int id; private boolean mark; public Feature(int a,int b,int c){ x=a; y=b; order=c; id=0; mark=false; } public boolean isMark() { return mark; } public void setMark(boolean mark) { this.mark = mark; } int getOrder() { return order; } public int getX() { return x; } public int getY() { return y; } void setOrder(int i) { order = i; } void setX(int i) { x = i; } void setY(int i) { y = i; } public int getId() { return id; } public void setId(int i) { id = i; } public boolean equals(Object arg0) { if(arg0 instanceof Feature){ Feature f=(Feature)arg0; return (x==f.x&&y==f.y); }else{ return false; } } }
・FeatureFinder.java
package test.filter; import java.awt.geom.Point2D; import java.awt.image.BufferedImage; import java.util.ArrayList; import java.util.Iterator; import java.util.List; public class FeatureFinder { private BufferedImage image; private int width; private int height; private int[][] px; public FeatureFinder(BufferedImage im){ image=im; width=image.getWidth(); height=image.getHeight(); px=new int[width][height]; for(int x=0;x<width;x++){ for(int y=0;y<height;y++){ int n=image.getRGB(x,y); int val=(n>>16&0xff); if(val==255){ px[x][y]=0; }else{ px[x][y]=1; } } } } public List<Point2D> getFeature(){ List<Feature> tmp=getFeature(width,height,px); List<Point2D> ret=new ArrayList<Point2D>(); if(tmp.size()>0){ Iterator<Feature> it=tmp.iterator(); while(it.hasNext()){ Feature f=(Feature)it.next(); ret.add(new Point2D.Double(f.getX(),f.getY())); } } return ret; } private static final List<Feature> getFeature(int width, int height,int[][] binary){ List<Feature> list=new ArrayList<Feature>(); for(int y=1;y<height-1;y++){ for(int x=1;x<width-1;x++){ if(binary[x][y]==1){ int val=binary[x+1][y]+binary[x][y-1]+ binary[x-1][y]+binary[x][y+1]; if(val==1||val==3||val==4){ Feature f=new Feature(x,y,val); list.add(f); } } } } return list; } }
次いで、createMenuBarに以下のコードを付け加える。
JMenuItem feat=new JMenuItem("Feature"); feat.addActionListener(new ActionListener(){ @Override public void actionPerformed(ActionEvent arg0) { Runnable rr=new Runnable(){ public void run(){ BufferedImage bi=canvas.getImage(); FeatureFinder ff=new FeatureFinder(bi); List<Point2D> feature=ff.getFeature(); final VolatileImage vi=canvas.createVolatileImage( bi.getWidth(), bi.getHeight()); Graphics2D g2=(Graphics2D)vi.createGraphics(); g2.drawImage(bi,0,0,canvas); g2.setColor(Color.RED); for(Point2D p :feature){ Ellipse2D ep=new Ellipse2D.Double( p.getX()-2,p.getY()-2,4d,4d); g2.draw(ep); } Runnable rx=new Runnable(){ public void run(){ canvas.setBaseImage(vi); } }; SwingUtilities.invokeLater(rx); } }; new Thread(rr).start(); } }); filter.add(feat);
■実行結果
こんな感じ。(右から、元画像、細線化、特徴点抽出)
ちなみに、細線化等の前処理が必要。
一応、線の起点・終点・交点が検出されているのがわかる。