用java的swing写了个图片标注工具

时间:2022-03-28 11:07:37

用java的swing写了个图片标注工具

功能说明:

1 鼠标单击:选取裁剪区域

2 鼠标双击:选取裁剪区域,并把裁剪区域保存为文件,同时把区域中心点的坐标保存

3 打开图片:从某个文件夹打开图片并显示,同时把该目录的所有图片的路径载进来。这个功能主要是针对这么种情况,

假如处理某个文件夹的图片集,在某一张终止了或者暂停了,下一次要从这种图片开始。

4 保存坐标:把裁剪区域保存为文件,同时把区域中心点的坐标保存

5 打开目录:把该目录的所有图片的路径载进来。

6 下一张:展示下一张图片。


常见用法:

1 “打开目录”,这时会将目录图片载进来,并显示第一张,这是可以 “鼠标双击”,选取该张图片的裁剪区域,保存坐标和裁剪区域,并展示下一张。

2 假如用法1在某一张图片暂停了,比如关闭该程序。下次可以利用“打开图片”从某张图片开始,然后继续利用“鼠标双击”一张一张处理。


注:其实按钮“保存坐标”和“下一张”只是作为功能测试使用,实际操作可以用“鼠标双击”代替。


下面附上源代码:


import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.awt.image.CropImageFilter;
import java.awt.image.FilteredImageSource;
import java.awt.image.ImageFilter;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.Collections;

import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.filechooser.FileNameExtensionFilter;



public class PhotoFrame extends JFrame
{

private static final long serialVersionUID = -2216276219179107707L;
private Container con;

private MousePanel zPanel;
private JScrollPane imgSp;
private JPanel btnPanel;
private String imageDir;
private String currImg;//文件名,不包含目录
private int currIndex;//当前图片索引
ArrayList<String> imgList;//所有图片的绝对路径

public void writeCropImg() throws IOException
{

BufferedImage sourceImage = (BufferedImage) zPanel.getImg();

Image croppedImage;
ImageFilter cropFilter;

int x = zPanel.getPointX()-25;
int y = zPanel.getPointY()-25;
//四个参数分别为图像起点坐标和宽高,即CropImageFilter(int x,int y,int width,int height),详细情况请参考API
//指定要裁剪的的文件的宽度和高度,以及起始坐标
cropFilter =new CropImageFilter(x,y,50,50);
//生成图片
croppedImage= Toolkit.getDefaultToolkit().createImage(new FilteredImageSource(sourceImage.getSource(),cropFilter));

//获取创建后的图片的高度
int h1=croppedImage.getHeight(null);
int w1=croppedImage.getWidth(null);

BufferedImage bi=new BufferedImage(w1,h1,BufferedImage.TYPE_INT_RGB);

Graphics g=bi.getGraphics();
//在画图的时候可以设置背景色
g.drawImage(croppedImage,0,0,Color.white,null);

String dir = imageDir+"_crops";

//创建文件输出流
FileOutputStream fos=new FileOutputStream(new File(dir+"/"+currImg));
//将创建的图片写入到输出流
ImageIO.write(bi, "png", fos);
fos.close();
}
private void showNext()
{
updateCurrName();
zPanel.setImagePath(imgList.get(currIndex));
currIndex++;

}
private void updateCurrName()
{
String path = imgList.get(currIndex);
int index = path.lastIndexOf('/');
currImg = path.substring(index);

}

private class nextHandler implements ActionListener
{
@Override
public void actionPerformed(ActionEvent e)
{
showNext();
}
}
private class openDirHandler implements ActionListener
{

@Override
public void actionPerformed(ActionEvent e)
{
JFileChooser chooser = new JFileChooser();
chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);//设置只能选择目录
int returnVal = chooser.showOpenDialog(null);
if(returnVal == JFileChooser.APPROVE_OPTION)
{
imageDir =chooser.getSelectedFile().getPath();
imgList = FileTool.refreshFileList(imageDir);
currIndex = 0;
showNext();
//System.out.println ( "你选择的目录是:" + selectPath );
//你选择的目录是:/home/linger/imdata/collar
}

}

}

private void savePointAndImg()
{
try
{
String dir = imageDir+"_points";
int x = zPanel.getPointX();
int y = zPanel.getPointY();

//打开文件
File f=new File(dir+"/");
if(!f.exists())
{
f.mkdir();

}
f=new File(dir+"/"+currImg);
if(!f.exists())
{
f.createNewFile();
}
FileOutputStream fos=new FileOutputStream(f);
OutputStreamWriter osw=new OutputStreamWriter(fos,"UTF-8");
BufferedWriter bw=new BufferedWriter(osw);
//写入文件
bw.write(x+","+y);

//关闭文件
bw.close();
osw.close();
fos.close();

writeCropImg();

}
catch (IOException e1)
{
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
private class savePointHandler implements ActionListener
{

@Override
public void actionPerformed(ActionEvent e)
{
savePointAndImg();
}
}

private class openImageHandler implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
JFileChooser chooser = new JFileChooser();
FileNameExtensionFilter filter = new FileNameExtensionFilter("JPG & PNG Images", "jpg", "png");
chooser.setFileFilter(filter);
int returnVal = chooser.showOpenDialog(null);
if(returnVal == JFileChooser.APPROVE_OPTION)
{
File file = chooser.getSelectedFile();
imageDir = file.getParent();
imgList = FileTool.refreshFileList(imageDir);
currImg = file.getName();//文件名,不包含路径
// System.out.println();
String path = file.getAbsolutePath();
currIndex = imgList.indexOf(path);
zPanel.setImagePath(path);
currIndex++;
//内部类访问外部类,可以直接访问的啊

}
}
}

private PhotoFrame()
{
con = getContentPane();
con.setLayout(new GridLayout(2,2));

zPanel = new MousePanel();
//zPanel.setImagePath("/home/linger/17820d01");//绑定图片
//zPanel.setPreferredSize(new Dimension(zPanel.getImgWidth(), zPanel.getImgHeight()));

imgSp = new JScrollPane();
imgSp.setPreferredSize(new Dimension(zPanel.getImgWidth(), zPanel.getImgHeight()));
imgSp.setViewportView(zPanel);
imgSp.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
imgSp.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);

//con.add(imgSp, BorderLayout.CENTER);
con.add(imgSp);


btnPanel = new JPanel();
btnPanel.setLayout(new FlowLayout());
btnPanel.setSize(300,100);

JButton button = new JButton("打开图片");
button.setSize(100, 50);
btnPanel.add(button);
button.addActionListener(new openImageHandler());

button = new JButton("保存坐标");
button.setSize(100, 50);
btnPanel.add(button);
button.addActionListener(new savePointHandler());

button = new JButton("打开目录");
button.setSize(100, 50);
btnPanel.add(button);
button.addActionListener(new openDirHandler());

button = new JButton("下一张");
button.setSize(100, 50);
btnPanel.add(button);
button.addActionListener(new nextHandler());

con.add(btnPanel);


zPanel.addMouseListener(new MouseAdapter(){
public void mouseClicked(MouseEvent e)
{
if(e.getClickCount() == 2)
{
savePointAndImg();
showNext();
}
}
});




finalSetting();
}

private void finalSetting()
{
setTitle("标注工具");

Toolkit kit = Toolkit.getDefaultToolkit();
Dimension screenSize = kit.getScreenSize();
int screenHeight = screenSize.height;
int screenWidth = screenSize.width;
int frameH = getHeight();
int frameW = getWidth();
setLocation((screenWidth - frameW) / 2 - 250,
(screenHeight - frameH) / 2 - 250);

setSize(800, 600);
//setSize(zPanel.getImgWidth()+10, zPanel.getImgHeight()+10);
//setPreferredSize(new Dimension(zPanel.getImgWidth()+100, zPanel.getImgHeight()+100));
//pack();

setVisible(true);
setResizable(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}

public static void main(String[] args)
{
new PhotoFrame();
}

}




import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.ImageFilter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

import javax.imageio.ImageIO;

public class ImgPanel extends javax.swing.JPanel
{

private static final long serialVersionUID = 1L;
private Image image;
private int imgWidth;
private int imgHeight;


public Image getImg()
{
return image;
}


public int getImgWidth()
{
return imgWidth;
}

public void setImgWidth(int imgWidth)
{
this.imgWidth = imgWidth;
}

public int getImgHeight()
{
return imgHeight;
}

public void setImgHeight(int imgHeight)
{
this.imgHeight = imgHeight;
}

public ImgPanel()
{
}

public void setImagePath(String imgPath) {
// 该方法不推荐使用,该方法是懒加载,图像并不加载到内存,当拿图像的宽和高时会返回-1;
// image = Toolkit.getDefaultToolkit().getImage(imgPath);
try
{
// 该方法会将图像加载到内存,从而拿到图像的详细信息。
image = ImageIO.read(new FileInputStream(imgPath));
//读取图片的大小
setImgWidth(image.getWidth(this));
setImgHeight(image.getHeight(this));
this.repaint();
}
catch (FileNotFoundException e)
{
e.printStackTrace();
} catch (IOException e)
{
e.printStackTrace();
}

}

@Override
public void paintComponent(Graphics g1)
{
super.paintComponent(g1);
int x = 0;
int y = 0;
Graphics g = (Graphics) g1;
if (null == image)
{
return;
}

g.drawImage(image, x, y, image.getWidth(this), image.getHeight(this),
this);
g = null;


}
}



import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class MousePanel extends ImgPanel//JPanel
{
int x_pos,y_pos;
public int getPointX()
{
return x_pos;
}
public int getPointY()
{
return y_pos;
}
public MousePanel()
{
addMouseListener(new MouseListener()
{
//mouseClicked():鼠标单击
public void mouseClicked(MouseEvent e)
{
x_pos=e.getX();
y_pos=e.getY();
repaint();
}
//mouseEntered():鼠标进入时
public void mouseEntered(MouseEvent e)
{
}
//mouseExited():鼠标离开时
public void mouseExited(MouseEvent e)
{
}
//mousePressed():鼠标按下去
public void mousePressed(MouseEvent e)
{

}
//mouseReleased():鼠标松开时
public void mouseReleased(MouseEvent e) {}
});
addMouseMotionListener(new MouseMotionListener()
{
public void mouseMoved(MouseEvent e)
{
}
public void mouseDragged(MouseEvent e){}
});
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
//g.drawString("current location is:["+x_pos+","+y_pos+"]",x_pos,y_pos);//在界面上显示
//System.out.printf("current location is:["+x_pos+","+y_pos+"]\n",x_pos,y_pos);//在控制台显示
g.setColor(Color.RED);
g.drawRect(x_pos-25, y_pos-25, 50, 50);
//g.fillOval(x_pos,y_pos,8,8);


}
}


import java.io.File;
import java.util.ArrayList;


public class FileTool {
public static ArrayList<String> refreshFileList(String strPath)
{
ArrayList<String> filelist = new ArrayList<String>();
File dir = new File(strPath);
File[] files = dir.listFiles();
if (files == null)
{
return filelist;
}
for (int i = 0; i < files.length; i++)
{
if (files[i].isDirectory())
{
refreshFileList(files[i].getAbsolutePath());
}
else
{
String strFileName = files[i].getAbsolutePath().toLowerCase();
//System.out.println(strFileName);
filelist.add(files[i].getAbsolutePath());
}
}
return filelist;
}

public static void main(String[] args)
{
// TODO Auto-generated method stub
ArrayList<String> test = refreshFileList("/home/linger/imdata/collar");
System.out.println(test.get(668));
System.out.println(test.get(669));
System.out.println(test.get(670));
}

}