@zimenglan
2015-03-27T08:53:59.000000Z
字数 16525
阅读 2132
human.pose annotation body.joints
jave project里面ctrl + F11), 会弹出一个框imageset扔到这个框里面去human和human pose. 先标注human后标注human posehuman用一个bouding box(两个点: 左上角和右下角)来表示, human pose也就是body/part joints, 这里假设body joints有15个part的anno info时, 先标注part的状态 (这里的状态只有一个: 就是该part是否occluded, 通常认为该part的area存在n%不可见, 则认为该part为occluded. 这里个人假设为n=30)part的body joint, 也就是一个点(小圆圈)non-occ是默认的joint)joint)/path/to/.../imageset, 则生成的保存目录为/path/to/.../imageset_AnnoPose.label), 如/path/to/.../imageset_AnnoPose/xxx.labellabel的保存内容为: partName/jointName x-coor y-coor occState, 其中occState的值取0或1/path/to/.../imageset/xxx.jpg
human_bb_top_left_cornor 57.0 107.0 0
human_bb_bottom_right_cornor 208.0 279.0 0
head 105.0 150.0 0
neck 114.0 158.0 0
torso 98.0 163.0 0
left_shoulder 79.0 153.0 0
left_elbow 73.0 152.0 0
left_hand/wrist 120.0 154.0 0
right_shoulder 112.0 138.0 0
right_elbow 89.0 143.0 0
right_hand/wrist 142.0 190.0 0
left_hip 170.0 215.0 0
left_knee 164.0 257.0 0
left_foot/ankle 164.0 186.0 0
right_hip 189.0 210.0 0
right_knee 181.0 251.0 0
right_foot/ankle 136.0 170.0 0
暂时不能从本地上传图片, 所有给不了标注时的效果图
import java.awt.BasicStroke;import java.awt.Color;import java.awt.Graphics;import java.awt.Graphics2D;import java.awt.Image;import java.awt.datatransfer.DataFlavor;import java.awt.dnd.DnDConstants;import java.awt.dnd.DropTarget;import java.awt.dnd.DropTargetDragEvent;import java.awt.dnd.DropTargetDropEvent;import java.awt.dnd.DropTargetEvent;import java.awt.dnd.DropTargetListener;import java.awt.event.KeyEvent;import java.awt.event.KeyListener;import java.awt.event.MouseAdapter;import java.awt.event.MouseEvent;import java.awt.event.MouseMotionAdapter;import java.io.BufferedWriter;import java.io.File;import java.io.FileWriter;import java.util.Arrays;import java.util.Iterator;import java.util.LinkedList;import java.util.List;import javax.imageio.ImageIO;import javax.swing.JFrame;import javax.swing.JOptionPane;public class PoseAnno_BB_And_Joints extends JFrame implements DropTargetListener {private static final long serialVersionUID = 1L;// one bounding box, and 15 body jointsprivate static String[] annoName = {// a bounding box for a whole person"human_bb_top_left_cornor","human_bb_bottom_right_cornor",// the body joints"head", "neck", "torso","left_shoulder", "left_elbow", "left_hand/wrist","right_shoulder", "right_elbow", "right_hand/wrist","left_hip", "left_knee", "left_foot/ankle","right_hip", "right_knee", "right_foot/ankle"};//private static int[] annoNameIndice = {0, 1, 2, 3, 4,5, 6, 7, 8, 9, 10,11, 12, 13, 14, 15};// if the occluded area of the body part is more that 30 percentage,// the body part is occludedprivate static String[] occState = {"non_occ", // default - 0"occ" // 1};private Image offScreenImage = null; // avoid flickerprivate Graphics gOffScreenGraphics;// handler of the annotated imageprivate Image initImage = null;// path to the annotated datasetprivate String path = null;private String _prePath = null;private String _imagesetName = null;// the image name without extensionprivate String fileName = null;private String fileName2 = null;private final String _labelExt = ".label";private final String _saveDirExt = "_AnnoPose";// image file listprivate LinkedList<File> file_list = new LinkedList<File>();// index of imagesprivate int curFileIdx = 0;// if shift is pressed, then draw// horizontal or// vertical line.private boolean shift_flag = false;// flag to occlusion state// 0: non-occluded, 1: occludedprivate int[] isOccluded = new int[annoName.length];// each part is annotated by one point// private static final int numXY = 2;// private int[][] xPoints = new int[annoName.length + 1][numXY];// private int[][] yPoints = new int[annoName.length + 1][numXY];// the first two points for human bounding box// the rest for 15 human body jointsprivate final int totalLen = annoName.length;private int[] xPoints = new int[totalLen];private int[] yPoints = new int[totalLen];// since human_bb occupies two pointsprivate int[] points = new int[totalLen];// index of partsprivate int partsIdx = 0;// initialize some variablesprivate static final double scale = 1;private static final int _width = 640;private static final int _height = 480;private static final int _startX = 480;private static final int _startY = 240;private static final int _border = 10;private static final int _startJframeX = 0;private static final int _startJframeY = 20;private static final int _circle_len = 5;private static final String[] moustType = {"left mouse button","middle mouse wheel","right mouse button"};// ***************************************************************public PoseAnno_BB_And_Joints() {//setTitle("Human Pose Annotation");setSize(_width, _height);setLocation(_startX, _startY);setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);// button 1: the left mouse button// button 2: the mouse wheel// button 3: the right mouse buttonaddMouseListener(new MouseAdapter() {@Overridepublic void mouseClicked(MouseEvent e) {int type = e.getButton();System.out.println("mouse click type: " + moustType[type - 1]);System.out.println("partsIdx: " + partsIdx);if (initImage == null || partsIdx == totalLen || type == MouseEvent.BUTTON2) {return;}if (type == MouseEvent.BUTTON3) {xPoints[partsIdx] = 0;yPoints[partsIdx] = 0;// need to be resetif (partsIdx < 0) {Arrays.fill(isOccluded, 0);Arrays.fill(xPoints, 0);Arrays.fill(yPoints, 0);partsIdx = 0;}PoseAnno_BB_And_Joints.this.repaint();return;}// get the point locationxPoints[partsIdx] = e.getX() - _startJframeX;yPoints[partsIdx] = e.getY() - _startJframeY;// System.out.println("mouse click point: (" +// e.getX() + ", " + e.getY() + ")");System.out.println("mouse click point: (" + xPoints[partsIdx] +", " + yPoints[partsIdx] + ")");if (xPoints[partsIdx] < _border) {xPoints[partsIdx] = _border;}if (xPoints[partsIdx] >= initImage.getWidth(null) + _border) {xPoints[partsIdx] = initImage.getWidth(null) + _border - 1;}if (yPoints[partsIdx] < _border) {yPoints[partsIdx] = _border;}if (yPoints[partsIdx] >= initImage.getHeight(null) + _border) {yPoints[partsIdx] = initImage.getHeight(null) + _border - 1;}// isOccluded[partsIdx] = 0;//partsIdx++;// repaintPoseAnno_BB_And_Joints.this.repaint();//if (partsIdx == totalLen) {int choice = JOptionPane.showConfirmDialog(PoseAnno_BB_And_Joints.this,"complete! save annotation or not?","tips",JOptionPane.YES_NO_OPTION);if (choice == JOptionPane.YES_OPTION) {// save the annotationsaveAnnotation();// set next imageif (file_list.size() > 1) {setNextPic(1);}}}}});addMouseMotionListener(new MouseMotionAdapter() {@Overridepublic void mouseMoved(MouseEvent e) {/*if (initImage == null || partsIdx == totalLen) {return;}*/// only for drawing a bounding box for the whole person// not for the 15 body jointsif (initImage == null || partsIdx > 1) {return;}// System.out.println("mouse move");// get the point location -- keep lineIdxxPoints[partsIdx] = e.getX() - _startJframeX;yPoints[partsIdx] = e.getY() - _startJframeY;// System.out.println("mouse move point: (" + e.getX() +// ", " + e.getY() + ")");System.out.println("mouse click point: (" + xPoints[partsIdx]+ ", " + yPoints[partsIdx] + ")");if (xPoints[partsIdx] < _border) {xPoints[partsIdx] = _border;}if (xPoints[partsIdx] >= initImage.getWidth(null) + _border) {xPoints[partsIdx] = initImage.getWidth(null) + _border - 1;}if (yPoints[partsIdx] < _border) {yPoints[partsIdx] = _border;}if (yPoints[partsIdx] >= initImage.getHeight(null) + _border) {yPoints[partsIdx] = initImage.getHeight(null) + _border - 1;}// repaintrepaint();}});// o: 0: non-occluded, 1: occluded// u: back to pre joint// n: ahead to next-joint// r: reset the current image// s: save the current anno info// a: back to pre image// d: ahead to next imageaddKeyListener(new KeyListener() {@Overridepublic void keyTyped(KeyEvent e) {}// dose not modify@Overridepublic void keyReleased(KeyEvent e) {switch (e.getKeyCode()) {case KeyEvent.VK_SHIFT:shift_flag = false;break;}}// need to be modified@Overridepublic void keyPressed(KeyEvent e) {switch (Character.toLowerCase(e.getKeyChar())) {// back to pre-partcase 'u':if (partsIdx != 0) {System.out.println("u(back to the pre joint):" + " " + annoName[partsIdx]);// current part -- need to be resetxPoints[partsIdx] = 0;yPoints[partsIdx] = 0;isOccluded[partsIdx] = 0; // set to be non-occlusionpartsIdx--;// need to be resetif (partsIdx < 0) {Arrays.fill(isOccluded, 0);Arrays.fill(xPoints, 0);Arrays.fill(yPoints, 0);partsIdx = 0;return;}// current part -- need to be reset// really need?xPoints[partsIdx] = 0;yPoints[partsIdx] = 0;isOccluded[partsIdx] = 0; // set to be non-occlusion}break;// save the annotationcase 's':System.out.println("s(save)" + " " + file_list.get(curFileIdx));saveAnnotation();// set and init next imageif (file_list.size() > 1) {setNextPic(1);}break;// ahead to next partcase 'n':// skip current annotation due to missingif (partsIdx >= annoName.length)return;System.out.println("n(next joint): " + " " + annoName[partsIdx]);xPoints[partsIdx] = 0;yPoints[partsIdx] = 0;// set to be occlusion since you ignore the current partisOccluded[partsIdx] = 1;partsIdx++;if (partsIdx == totalLen) {int choice = JOptionPane.showConfirmDialog(PoseAnno_BB_And_Joints.this,"complete! save annotation or not?", "tips",JOptionPane.YES_NO_OPTION);if (choice == JOptionPane.YES_OPTION) {//saveAnnotation();// set and init next image// if (file_list.size() > 1) {// setNextPic(1);// }}}break;// back to pre imagecase 'a':// back to pre image and init pre image statusSystem.out.println("a(back from):" + " " + file_list.get(curFileIdx));// remove the current label file, if it existString annoPath = _prePath + "/" + _imagesetName + _saveDirExt;File file = new File(annoPath);file.mkdir();String annoLabelFile = annoPath + "/" + fileName + _labelExt;file = new File(annoLabelFile);if(file.exists()) {file.delete();}// then back to pre imagesetNextPic(0);break;// ahead to next imagecase 'd':// set and init next image status// saveAnnotation();// just ignore the current imageSystem.out.println("d(ahead to):" + " " + file_list.get(curFileIdx));setNextPic(1);break;// reset the current imagecase 'r':System.out.println("r(rest):" + " " + file_list.get(curFileIdx));partsIdx = 0;Arrays.fill(xPoints, 0);Arrays.fill(yPoints, 0);Arrays.fill(isOccluded, 0);break;// 1: partial occludedcase 'o':System.out.println("if the part is occluded, you should " +"press the 'o' key before click the mouse");System.out.println("o(occ): " + " " + annoName[partsIdx]);isOccluded[partsIdx] = 1;break;default:switch (e.getKeyCode()) {case KeyEvent.VK_ESCAPE:xPoints[partsIdx] = 0;yPoints[partsIdx] = 0;isOccluded[partsIdx] = 1; // set to be non-occlusionbreak;case KeyEvent.VK_SHIFT:shift_flag = true;break;}}// repaintPoseAnno_BB_And_Joints.this.repaint();}});new DropTarget(this, this);setVisible(true);}protected void saveAnnotation() {saveAnnoPose();}protected void saveAnnoPose() {try {String annoPath = _prePath + "/" + _imagesetName + _saveDirExt;File file = new File(annoPath);file.mkdir();String annoLabelFile = annoPath + "/" + fileName + _labelExt;file = new File(annoLabelFile);BufferedWriter bw = new BufferedWriter(new FileWriter(file));// the total path to the imageString str = fileName2 + "\n";double x1, y1;// body jointsfor (int i = 0; i < totalLen - 1; i++) {x1 = Math.max( (xPoints[i] - _border) / scale, 0 );y1 = Math.max( (yPoints[i] - _border) / scale, 0 );str = str + annoName[i] + " " + x1 + " " + y1 + " "+ isOccluded[i] + "\n";}x1 = Math.max( (xPoints[totalLen - 1] - _border) / scale, 0 );y1 = Math.max( (yPoints[totalLen - 1] - _border) / scale, 0 );str = str + annoName[totalLen - 1] + " " + x1 + " " + y1 + " "+ isOccluded[totalLen - 1];str = str + "\n";bw.write(str);bw.close();} catch (Exception e) {e.printStackTrace();JOptionPane.showMessageDialog(this, "failed to save annotation");}}@Overridepublic void update(Graphics g) {if (initImage == null)return;if (offScreenImage == null|| offScreenImage.getHeight(this) != this.getHeight()|| offScreenImage.getWidth(this) != this.getWidth() ) {offScreenImage = this.createImage(this.getWidth(), this.getHeight());gOffScreenGraphics = offScreenImage.getGraphics();}int imgWidth = initImage.getWidth(null);int imgHeigth = initImage.getHeight(null);int osImgWidth = offScreenImage.getWidth(null);int osImgHeight = offScreenImage.getHeight(null);System.out.println("imgWidth: " + imgWidth + ", imgHeight: " + imgHeigth +", oImgWidth: " + osImgWidth + ", oImgHeight: " + osImgHeight);// a top-left corner (_border, _border)gOffScreenGraphics.drawImage(initImage, _border, _border, this);((Graphics2D) gOffScreenGraphics).setStroke(new BasicStroke(1.50f));gOffScreenGraphics.setColor(Color.GREEN);if (partsIdx < totalLen) {gOffScreenGraphics.drawString("" + partsIdx + ": " + annoName[partsIdx], 20, 20);} else {gOffScreenGraphics.drawString("" + partsIdx + ": " +"annotatation has been done!", 20, 50);}gOffScreenGraphics.setColor(Color.ORANGE);// draw the current lineint i;// draw the jointsfor(i = 0; i < partsIdx; i++) {gOffScreenGraphics.fillOval(xPoints[i], yPoints[i], _circle_len, _circle_len);}// draw the bounding box for humangOffScreenGraphics.setColor(Color.RED);if(partsIdx > 1) {int lineX[] = {xPoints[0], xPoints[0], xPoints[1], xPoints[1], xPoints[0]};int lineY[] = {yPoints[0], yPoints[1], yPoints[1], yPoints[0], yPoints[0]};for (i = 0; i < lineX.length - 1; i++) {gOffScreenGraphics.drawLine(lineX[i], lineY[i], lineX[i + 1], lineY[i + 1]);}}// paint(gOffScreen);g.drawImage(offScreenImage, _startJframeX, _startJframeY, this);g.dispose();}@Overridepublic void paint(Graphics g) {update(g);}// *********************************************@Overridepublic void dragEnter(DropTargetDragEvent dtde) {}@Overridepublic void dragOver(DropTargetDragEvent dtde) {}@Overridepublic void dropActionChanged(DropTargetDragEvent dtde) {}@Overridepublic void dragExit(DropTargetEvent dte) {}// *******************************************// drop the images into UI// get the image file list@SuppressWarnings("rawtypes")@Overridepublic void drop(DropTargetDropEvent dtde) {try {if (dtde.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {dtde.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);List list = (List) (dtde.getTransferable().getTransferData(DataFlavor.javaFileListFlavor));Iterator iterator = list.iterator();file_list.clear();curFileIdx = -1;while (iterator.hasNext()) {File file = (File) iterator.next();if (file.isDirectory()) {addFileToQueue(file);} else {if (file.getName().endsWith(".jpg") ||file.getName().endsWith(".png"))file_list.add(file);}}// start & initsetNextPic(1);dtde.dropComplete(true);} else {dtde.rejectDrop();}} catch (Exception e) {e.printStackTrace();dtde.rejectDrop();JOptionPane.showMessageDialog(this, "Failed to open images");}}// flag == 0 -- previous pic// flag == 1 -- next picprivate void setNextPic(int flag) {int tmp = curFileIdx;// backif (flag == 0) {if (curFileIdx == 0) {JOptionPane.showMessageDialog(this, "The first one!");return;}curFileIdx--;} else {// nextcurFileIdx++;}boolean ok = false;while (!ok) {try {if (curFileIdx >= file_list.size()) {curFileIdx = tmp;if (curFileIdx == -1)return;JOptionPane.showMessageDialog(this, "The last one!");return;}File file = file_list.get(curFileIdx);initImage = ImageIO.read(file);initImage = initImage.getScaledInstance((int) (initImage.getWidth(null) * scale),(int) (initImage.getHeight(null) * scale),Image.SCALE_SMOOTH // SCALE_DEFAULT, SCALE_SMOOTH);// path and fileNameint idx;path = file.getParent();String fileSeparator = System.getProperty("file.separator");// idx = path.lastIndexOf('\\'); // here is '\'idx = path.lastIndexOf(fileSeparator); // here is '\'System.out.println("idx " + idx);System.out.println("fileSeparator " + fileSeparator);System.out.println("path " + path);if(idx != 0){_prePath = path.substring(0, idx);_imagesetName = path.substring(idx + 1);}int imgLen = file_list.size();fileName = file.getName();fileName2 = path + fileSeparator + file.getName();idx = fileName.lastIndexOf('.');if (idx != -1) {fileName = fileName.substring(0, idx);}setTitle(fileName + " in " + imgLen + " imageset");//partsIdx = 0;// set default value - 0: non_occ, 1: occArrays.fill(isOccluded, 0);// 1 bb for person and 15 jointsArrays.fill(points, 0);Arrays.fill(xPoints, 0);Arrays.fill(yPoints, 0);// _border: 10// _startJframeX: 0// _startJframeY: 20setSize(initImage.getWidth(null) + _border * 3 + _startJframeX,initImage.getHeight(null) + _border * 3 + _startJframeY);// readAnnotation(path + "/Annotations/" + fileName + ".xml");repaint();ok = true;} catch (Exception e) {e.printStackTrace();if (flag == 0) {if (curFileIdx == 0) {return;}curFileIdx--;} else {curFileIdx++;}}}}// add file to file_list// if meet folder then recur itprivate void addFileToQueue(File folder) {for (File file : folder.listFiles()) {if (file.isDirectory()) {addFileToQueue(file);} else {if (file.getName().endsWith(".jpg") || file.getName().endsWith(".png")) {file_list.add(file);}}}}// here we don't use itprivate boolean readAnnotation(String path) {File gt = new File(path);if (!gt.exists())return false;int choice = JOptionPane.showConfirmDialog(this,"Annotation file is found, read it or not?", "tips",JOptionPane.YES_NO_OPTION);if (choice != JOptionPane.YES_OPTION)return false;try {// ??} catch (Exception e) {e.printStackTrace();partsIdx = 0;Arrays.fill(xPoints, 0);Arrays.fill(yPoints, 0);Arrays.fill(isOccluded, 0);JOptionPane.showMessageDialog(this, "Invalid annotation file");}return true;}// **********************************************public static void main(String[] args) {new PoseAnno_BB_And_Joints();}}