package gr.iti.mklab.visual.examples; import gr.iti.mklab.visual.extraction.AbstractFeatureExtractor; import gr.iti.mklab.visual.extraction.ColorSURFExtractor; import gr.iti.mklab.visual.extraction.ImageScaling; import gr.iti.mklab.visual.extraction.RootSIFTExtractor; import gr.iti.mklab.visual.extraction.SIFTExtractor; import gr.iti.mklab.visual.extraction.SURFExtractor; import gr.iti.mklab.visual.utilities.FeatureIO; import gr.iti.mklab.visual.utilities.ImageIOGreyScale; import java.awt.image.BufferedImage; import java.io.File; import java.io.FilenameFilter; import javax.imageio.ImageIO; /** * Extracts features from images (.jpg or .png files) contained in a directory and writes them in a file for * each image. The feature files are written in a directory (named by the name of the feature) that is created * (if it does not already exist) in the parent directory of the directory were the images reside. * * @author Eleftherios Spyromitros-Xioufis * */ public class FeatureExtraction { /** * * @param args * [0] Full path to the images folder. * @param args * [1] Maximum number of images to perform feature extraction on, i.e. only the top N images * returned by File.list will be processed. * @param args * [2] Number of images to be skipped from extraction (usually 0). * @param args * [3] Maximum number of pixels that each image will be scaled to (e.g. 196608 for 512x384). * @param args * [4] Type of features to extract (surf/sift/rootsift/csurf). * @param args * [5] Whether the features should be written in textual format (txt) / binary format (bin) or * not written (no). * @throws Exception */ public static void main(String args[]) throws Exception { String imageFolder = args[0]; int totalImages = Integer.parseInt(args[1]); int skipImages = Integer.parseInt(args[2]); int maxPixels = Integer.parseInt(args[3]); String featureType = args[4]; String format = args[5]; ImageScaling scale = new ImageScaling(maxPixels); AbstractFeatureExtractor featureExtractor; if (featureType.equals("surf")) { featureExtractor = new SURFExtractor(); } else if (featureType.equals("sift")) { featureExtractor = new SIFTExtractor(); } else if (featureType.equals("rootsift")) { featureExtractor = new RootSIFTExtractor(); } else if (featureType.equals("csurf")) { featureExtractor = new ColorSURFExtractor(); } else { throw new Exception("Wrong feature type provided."); } // --------------Load the image files------------- File dir = new File(imageFolder); FilenameFilter filter = new FilenameFilter() { public boolean accept(File dir, String name) { if (name.endsWith(".jpg") || name.endsWith(".png")) return true; else return false; } }; String[] files = dir.list(filter); // create a folder for writing the features String featuresFolder = imageFolder + "../" + maxPixels + "_" + featureType; File file = new File(featuresFolder); if (!file.exists()) { if (file.mkdir()) { System.out.println("Directory is created!"); } else { System.out.println("Failed to create directory!"); } } double totalReadingTime = 0; double totalScalingTime = 0; double totalWritingTime = 0; int extractedCount = 0; int limit = Math.min(files.length, totalImages); // --------------Extract features for each image------------- for (int i = skipImages; i < limit; i++) { long start = System.currentTimeMillis(); System.out.print("Processing image " + (i + 1) + ": "); BufferedImage image; long startReading = System.currentTimeMillis(); try { // first try reading with the default class image = ImageIO.read(new File(imageFolder + files[i])); } catch (IllegalArgumentException e) { // if it fails retry with the corrected class // This exception is probably because of a grayscale jpeg image. System.out.println("Exception: " + e.getMessage() + " | Image: " + files[i]); image = ImageIOGreyScale.read(new File(imageFolder + files[i])); } catch (Exception e) { // skip extraction an other exception is thrown System.out.println("Exception: " + e.getMessage() + " | Image: " + files[i]); continue; } if (image == null) { System.out.println("Null image: " + files[i]); continue; } totalReadingTime += System.currentTimeMillis() - startReading; long startScaling = System.currentTimeMillis(); image = scale.maxPixelsScaling(image); totalScalingTime += System.currentTimeMillis() - startScaling; double[][] features = featureExtractor.extractFeatures(image); // sanity check for (int k = 0; k < features.length; k++) { if (String.valueOf(features[k][0]).equals("NaN")) { System.out.println("NaN feature " + (k + 1) + " in image " + files[i]); } } String imageFileExtension; if (files[i].endsWith("jpg")) { imageFileExtension = "jpg"; } else { imageFileExtension = "png"; } // write features to file long startWring = System.currentTimeMillis(); if (format.equals("bin")) { String featuresFileName = featuresFolder + "/" + files[i].split("\\." + imageFileExtension)[0] + "." + featureType + "b"; FeatureIO.writeBinary(featuresFileName, features); } else if (format.equals("txt")) { String featuresFileName = featuresFolder + "/" + files[i].split("\\." + imageFileExtension)[0] + "." + featureType; FeatureIO.writeText(featuresFileName, features); } totalWritingTime += System.currentTimeMillis() - startWring; System.out.println("completed in " + (System.currentTimeMillis() - start) + " ms"); extractedCount++; } System.out.println("Average reading time in ms: " + totalReadingTime / (double) extractedCount); System.out.println("Average scaling time in ms: " + totalScalingTime / (double) extractedCount); System.out.println("Average extraction time in ms: " + featureExtractor.getTotalExtractionTime() / (double) extractedCount); System.out.println("Average writing time in ms: " + totalWritingTime / (double) extractedCount); System.out.println("Average number of interest points per image: " + featureExtractor.getTotalNumberInterestPoints() / (double) extractedCount); } }