initial commit
authorTomas Wenström <tomas.wenstrom@gmail.com>
Sun, 12 Feb 2017 21:30:15 +0000 (22:30 +0100)
committerTomas Wenström <tomas.wenstrom@gmail.com>
Sun, 12 Feb 2017 21:30:15 +0000 (22:30 +0100)
.gitignore [new file with mode: 0644]
config.properties [new file with mode: 0644]
src/kaka/cakelight/Configuration.java [new file with mode: 0644]
src/kaka/cakelight/Frame.java [new file with mode: 0644]
src/kaka/cakelight/FrameGrabber.java [new file with mode: 0644]
src/kaka/cakelight/Main.java [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..a6c1087
--- /dev/null
@@ -0,0 +1,3 @@
+.idea
+CakeLight.iml
+out
diff --git a/config.properties b/config.properties
new file mode 100644 (file)
index 0000000..b3f150f
--- /dev/null
@@ -0,0 +1,9 @@
+# default settings
+
+video.device=/dev/video0
+video.width=720
+video.height=576
+video.bpp=2
+
+leds.cols=32
+leds.rows=18
diff --git a/src/kaka/cakelight/Configuration.java b/src/kaka/cakelight/Configuration.java
new file mode 100644 (file)
index 0000000..35fde30
--- /dev/null
@@ -0,0 +1,81 @@
+package kaka.cakelight;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.*;
+import java.util.stream.Collectors;
+
+public class Configuration {
+    private List<Map.Entry<String, String>> settings = new ArrayList<>();
+    public VideoConfiguration video;
+    public LedConfiguration leds;
+
+    private Configuration(Properties prop) {
+        video = new VideoConfiguration(prop);
+        leds = new LedConfiguration(prop);
+    }
+
+    public static Configuration from(String propertiesFile) {
+        InputStream input = null;
+        try {
+            input = new FileInputStream(propertiesFile);
+            Properties prop = new Properties();
+            prop.load(input);
+            return new Configuration(prop);
+        } catch (IOException ex) {
+            ex.printStackTrace();
+        } finally {
+            if (input != null) {
+                try {
+                    input.close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+        return null;
+    }
+
+    private String get(Properties prop, String name) {
+        return addSetting(name, prop.getProperty(name));
+    }
+
+    private String get(Properties prop, String name, String dflt) {
+        return addSetting(name, prop.getProperty(name, dflt));
+    }
+
+    private String addSetting(String name, String value) {
+        settings.add(new AbstractMap.SimpleEntry<>(name, value));
+        return value;
+    }
+
+    @Override
+    public String toString() {
+        return settings.stream().map(entry -> entry.getKey() + "=" + entry.getValue()).collect(Collectors.joining("\n"));
+    }
+
+    public class VideoConfiguration {
+        public String device;
+        public int width;
+        public int height;
+        public int bpp;
+
+        private VideoConfiguration(Properties prop) {
+            device = get(prop, "video.device", "/dev/video0");
+            width = Integer.parseInt(get(prop, "video.width", "720"));
+            height = Integer.parseInt(get(prop, "video.height", "576"));
+            bpp = Integer.parseInt(get(prop, "video.bpp", "2"));
+        }
+    }
+
+    public class LedConfiguration {
+        public int cols;
+        public int rows;
+
+        private LedConfiguration(Properties prop) {
+            cols = Integer.parseInt(get(prop, "leds.cols"));
+            rows = Integer.parseInt(get(prop, "leds.rows"));
+        }
+    }
+}
diff --git a/src/kaka/cakelight/Frame.java b/src/kaka/cakelight/Frame.java
new file mode 100644 (file)
index 0000000..0031abc
--- /dev/null
@@ -0,0 +1,50 @@
+package kaka.cakelight;
+
+import org.opencv.core.CvType;
+import org.opencv.core.Mat;
+import org.opencv.core.Size;
+import org.opencv.imgproc.Imgproc;
+
+import static kaka.cakelight.Main.saveFile;
+import static kaka.cakelight.Main.timeIt;
+
+public class Frame {
+    private byte[] data;
+    private Configuration config;
+
+    private Frame(byte[] data) {
+        this.data = data;
+    }
+
+    public static Frame of(byte[] data, Configuration config) {
+        Frame frame = new Frame(data);
+        frame.config = config;
+        frame.convert();
+        return frame;
+    }
+
+    private void convert() {
+        Mat src = new Mat(config.video.height, config.video.width, CvType.CV_8UC2); // 8-bit, unsigned, 2 channels
+        src.put(0, 0, data);
+
+        Mat converted = new Mat();
+        Mat resized = new Mat();
+
+        timeIt("total", () -> {
+            timeIt("yuyv2rgb", () -> Imgproc.cvtColor(src, converted, Imgproc.COLOR_YUV2RGB_YUYV)); // 3.5 - 4.0 ms
+            timeIt("resizing", () -> Imgproc.resize(converted, resized, new Size(config.leds.cols, config.leds.rows), 0, 0, Imgproc.INTER_AREA)); // INTER_AREA is the best for shrinking, but also the slowest (~1.5 ms)
+        });
+//        save(converted, "/home/kaka/test-converted.data");
+//        save(resized, "/home/kaka/test-resized.data");
+    }
+
+    private void save(Mat mat, String filepath) {
+        byte[] data = new byte[mat.cols() * mat.rows() * mat.channels()];
+        mat.get(0, 0, data);
+        saveFile(data, filepath);
+    }
+
+    public byte[] getData() {
+        return data;
+    }
+}
diff --git a/src/kaka/cakelight/FrameGrabber.java b/src/kaka/cakelight/FrameGrabber.java
new file mode 100644 (file)
index 0000000..d228b7b
--- /dev/null
@@ -0,0 +1,52 @@
+package kaka.cakelight;
+
+import java.io.*;
+
+public class FrameGrabber {
+    private Configuration config;
+    private File file;
+    private int bytesPerFrame;
+    private InputStream fileStream;
+
+    private FrameGrabber() {
+    }
+
+    public static FrameGrabber from(Configuration config) {
+        FrameGrabber fg = new FrameGrabber();
+        fg.config = config;
+        fg.file = new File(config.video.device);
+        fg.bytesPerFrame = config.video.width * config.video.height * config.video.bpp;
+        return fg;
+    }
+
+    public boolean prepare() {
+        try {
+            fileStream = new FileInputStream(file);
+            return true;
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    public Frame grabFrame() {
+        try {
+            byte[] data = new byte[bytesPerFrame];
+            int count = fileStream.read(data);
+            System.out.println("count = " + count);
+            return Frame.of(data, config);
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+
+        return null;
+    }
+
+    public void close() {
+        try {
+            fileStream.close();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+}
diff --git a/src/kaka/cakelight/Main.java b/src/kaka/cakelight/Main.java
new file mode 100644 (file)
index 0000000..474683e
--- /dev/null
@@ -0,0 +1,54 @@
+package kaka.cakelight;
+
+import org.opencv.core.Core;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+public class Main {
+
+    public static void main(String[] args) {
+       System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
+
+       Configuration config = Configuration.from("config.properties");
+       System.out.println("Running with config:\n" + config);
+
+       FrameGrabber grabber = FrameGrabber.from(config);
+       grabber.prepare();
+       Frame frame = grabber.grabFrame();
+       double time = 0;
+       for (int i = 0; i < 100; i++) {
+           time += timeIt("frame", () -> grabber.grabFrame());
+       }
+       System.out.println("time = " + time);
+       grabber.close();
+//     byte[] data = frame.getData();
+//     saveFile(data, "/home/kaka/test.img");
+    }
+
+    public static void saveFile(byte[] data, String filepath) {
+       try {
+           FileOutputStream fos = new FileOutputStream(filepath);
+           fos.write(data);
+           fos.close();
+       } catch (IOException e) {
+           e.printStackTrace();
+       }
+    }
+
+    public static double timeIt(String tag, Runnable lambda) {
+       long start = System.nanoTime();
+       lambda.run();
+       long end = System.nanoTime();
+       double duration = (end - start) * 0.000001;
+       System.out.println("duration (ms): " + tag + " = " + duration);
+       return duration;
+    }
+}
+
+/*
+FrameGrabber läser frames asynkront
+skickar frame till FrameConverter
+sparas i huvudklassen
+läses av FrameProcessor/LedController
+ */
\ No newline at end of file