diff --git a/src/main/java/MainClasses/Config.java b/src/main/java/MainClasses/Config.java index f35fb73990792f03ce36b6a4e85bf5ce334b0381..ed67b09388f115b319016f08b5d83326296c2d4d 100644 --- a/src/main/java/MainClasses/Config.java +++ b/src/main/java/MainClasses/Config.java @@ -40,8 +40,8 @@ public class Config { static String IMAGE_SEQUENCE_PATH; static String VIDEO_PATH_AND_FILE; static int IMAGE_FPS; - static double IMAGE_FPS_DECLINE; - static int IMAGE_FPS_MIN; + static int IMAGES_TO_FPS_INCREASE; + static int IMAGE_FPS_MAX; static boolean ZOOM; // For images @@ -153,8 +153,8 @@ public class Config { IMAGE_SEQUENCE_PATH = this.properties.getProperty("imageSequencePath"); VIDEO_PATH_AND_FILE = this.properties.getProperty("videoPathAndFile"); IMAGE_FPS = Integer.parseInt(this.properties.getProperty("imgFps")); - IMAGE_FPS_DECLINE = Double.parseDouble(this.properties.getProperty("imgFpsDecline")); - IMAGE_FPS_MIN = Integer.parseInt(this.properties.getProperty("imgFpsMax")); + IMAGES_TO_FPS_INCREASE = Integer.parseInt(this.properties.getProperty("imagesToFpsIncrease")); + IMAGE_FPS_MAX = Integer.parseInt(this.properties.getProperty("imgFpsMax")); ZOOM = this.properties.getProperty("zoom").equals("true"); } diff --git a/src/main/java/MainClasses/Main.java b/src/main/java/MainClasses/Main.java index 5b3148dfc5075e0847357fb6abd0198f2c58736e..86ce8381d5a4a065b4f2f91f3d0f036eccb3c7cd 100644 --- a/src/main/java/MainClasses/Main.java +++ b/src/main/java/MainClasses/Main.java @@ -12,16 +12,16 @@ public class Main { String propertyPath = "./src/main/resources/genetic.properties"; Config config = new Config(propertyPath); - int[] protein = Examples.convertStringToIntArray(Examples.SEQ20); + int[] protein = Examples.convertStringToIntArray(Examples.SEQ50); GeneticAlgorithm ga = new GeneticAlgorithm(protein); ga.simulateGenerations(); // Create a new video if possible and desired - boolean imagesRefreshed = Arrays.stream(Config.VISUALIZERS).anyMatch(VisualizerMethods.Image::equals); - boolean videoEnabled = Arrays.stream(Config.VISUALIZERS).anyMatch(VisualizerMethods.Video::equals); + boolean imagesRefreshed = Arrays.asList(Config.VISUALIZERS).contains(VisualizerMethods.Image); + boolean videoEnabled = Arrays.asList(Config.VISUALIZERS).contains(VisualizerMethods.Video); if (imagesRefreshed && videoEnabled){ VideoCreator.createVideo(Config.IMAGE_SEQUENCE_PATH, Config.VIDEO_PATH_AND_FILE, - Config.IMAGE_FPS, ga.getMaxH(), ga.getMaxW()); + Config.IMAGE_FPS, Config.IMAGES_TO_FPS_INCREASE, Config.IMAGE_FPS_MAX, ga.getMaxH(), ga.getMaxW()); } } } diff --git a/src/main/java/Visualization/JCodecPNGtoMP4.java b/src/main/java/Visualization/JCodecPNGtoMP4.java index 4a0513f6f78d6cbb31676ebb6f5299950b57d3d1..7621a4c2350f68fe89469afa80e4e5e93272205b 100644 --- a/src/main/java/Visualization/JCodecPNGtoMP4.java +++ b/src/main/java/Visualization/JCodecPNGtoMP4.java @@ -64,13 +64,13 @@ public class JCodecPNGtoMP4 { }); } - static void generateVideoBySequenceImages(File videoFile, String pathImages, String imageExt, int fps) throws Exception { + static void generateVideoBySequenceImages(File videoFile, String pathImages, String imageExt, + int fps, int imgToFpsIncrease, int maxFps) throws Exception { SeekableByteChannel out = null; try { out = NIOUtils.writableFileChannel(videoFile.getCanonicalPath()); - // for Android use: AndroidSequenceEncoder - AWTSequenceEncoder encoder = new AWTSequenceEncoder(out, Rational.R(fps, 1)); + AWTSequenceEncoder encoder = new AWTSequenceEncoder(out, Rational.R(maxFps, 1));; Path directoryPath = Paths.get(new File(pathImages).toURI()); @@ -86,16 +86,32 @@ public class JCodecPNGtoMP4 { sortByNumber(files); + int numberImagesWithSameFps = imgToFpsIncrease; + System.out.println(); for (File img : files) { - System.err.println("Encoding image " + img.getName()); - // Generate the image, for Android use Bitmap + if (numberImagesWithSameFps <= 0) { + if (fps < maxFps) { + fps++; // Increase fps + numberImagesWithSameFps = imgToFpsIncrease - 1; + } + } else { + numberImagesWithSameFps--; // Countdown to increase + } + + System.err.println("Encoding image " + img.getName() + " [" + fps + " fps]"); + // Generate the image BufferedImage image = ImageIO.read(img); - // Encode the image - encoder.encodeImage(image); + // Encode the image often enough to fit current fps + for (int i = 0; i < Math.round((float) maxFps / fps); i++) { + encoder.encodeImage(image); + } + // Finalize the encoding, i.e. clear the buffers, write the header, etc. } } // Finalize the encoding, i.e. clear the buffers, write the header, etc. encoder.finish(); + System.err.println("Finished creating video: " + videoFile.getCanonicalPath()); + } finally { NIOUtils.closeQuietly(out); } diff --git a/src/main/java/Visualization/VideoCreator.java b/src/main/java/Visualization/VideoCreator.java index 52cab2415427e9c2450d76f35100f3b0f32c6e5b..a1eecb8f09aac301009c83d7d02ce7e2ddb43814 100644 --- a/src/main/java/Visualization/VideoCreator.java +++ b/src/main/java/Visualization/VideoCreator.java @@ -8,8 +8,6 @@ import java.awt.image.BufferedImage; import java.io.File; import java.io.FilenameFilter; import java.io.IOException; -import java.net.MalformedURLException; -import java.util.Vector; public class VideoCreator{ @@ -28,9 +26,10 @@ public class VideoCreator{ } }; - private static int[] resizeImages(String imagesPath, int maxH, int maxW) throws IOException { + private static void resizeImages(String imagesPath, int maxH, int maxW) throws IOException { + System.err.println("\nStarting image resizing"); + dir = new File(imagesPath); - int[] widthHeight = new int[2]; if (dir.isDirectory()) { // reads input images and determines maximum required size @@ -58,9 +57,6 @@ public class VideoCreator{ maxHeight = MAXIMUM_SIZE; } - widthHeight[0] = maxWidth; - widthHeight[1] = maxHeight; - // Resizes all images for (final File f : dir.listFiles(imageFilter)) { BufferedImage inputImage = ImageIO.read(f); @@ -80,33 +76,26 @@ public class VideoCreator{ ImageIO.write(outputImage, "png", f); } } - - return widthHeight; } // MainClasses.Main function public static void createVideo(String imagesPath, String videoPathAndFile, - int imgFps, int maxH, int maxW) { + int imgFps, int imgToFpsIncrease, int maxFps, int maxH, int maxW) { try { - int[] widthHeight = VideoCreator.resizeImages(imagesPath, maxH, maxW); + VideoCreator.resizeImages(imagesPath, maxH, maxW); File videoFile = new File(videoPathAndFile); if (!videoFile.exists()) { videoFile.createNewFile(); } - Vector<String> imgLst = new Vector<>(); - makeVideo(videoFile, imagesPath, imgFps); + try { + JCodecPNGtoMP4.generateVideoBySequenceImages(videoFile, imagesPath, "png", imgFps, imgToFpsIncrease, maxFps); + } catch (Exception e) { + e.printStackTrace(); + } } catch (IOException e) { e.printStackTrace(); } } - - public static void makeVideo(File videoFile, String imagesDir, int fps) throws MalformedURLException { - try { - JCodecPNGtoMP4.generateVideoBySequenceImages(videoFile, imagesDir, "png", fps); - } catch (Exception e) { - e.printStackTrace(); - } - } } \ No newline at end of file diff --git a/src/main/resources/genetic.properties b/src/main/resources/genetic.properties index 002e30eb5debe297f248ee2b82bacaac9ce7aeba..b31321dccd82c42e69ec7914e281bf93ae8d11f1 100644 --- a/src/main/resources/genetic.properties +++ b/src/main/resources/genetic.properties @@ -7,9 +7,9 @@ ### Algorithm settings # Size of the population in one generation - populationSize = 10 + populationSize = 200 # Number of generations to run the algorithm for - noGenerations = 10 + noGenerations = 1000 # Type of population initialization [curl | straight | random] initializationMethod = curl # Type of selection that should be used [proportional | tournament | onlybest] @@ -47,10 +47,10 @@ # Path and filename for the resulting video file videoPathAndFile = ./visualization/video.mp4 # Frames per second in the beginning of the video - imgFps = 100 - # Decline of interval between images to speed up later generations TODO - imgFpsDecline = 0.01 - # Maximum fps TODO - imgFpsMax = 10 + imgFps = 10 + # Number of images until fps increases by one + imagesToFpsIncrease = 6 + # Maximum fps, a larger gap between the starting and maxFps will mean a longer encoding and file size + imgFpsMax = 120 # Zoom to the appropriate size, once no bigger proteins are going to follow TODO zoom = false