diff --git a/usr/openmv-ide.glade b/usr/openmv-ide.glade
index 9f6b5a243..aab349808 100644
--- a/usr/openmv-ide.glade
+++ b/usr/openmv-ide.glade
@@ -100,6 +100,7 @@ Kwabena W. Agyeman
False
Copy Color
True
+
@@ -342,7 +343,7 @@ Kwabena W. Agyeman
False
GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_STRUCTURE_MASK
OpenMV IDE
- 800
+ 1024
600
diff --git a/usr/openmv-ide.py b/usr/openmv-ide.py
index f4f3d05d6..2864e9136 100755
--- a/usr/openmv-ide.py
+++ b/usr/openmv-ide.py
@@ -11,6 +11,7 @@ from os.path import expanduser
import gtksourceview2 as gtksourceview
from glob import glob
import urllib2, json
+import numpy as np
#import pydfu on Linux
if platform.system() == "Linux":
@@ -123,6 +124,26 @@ class OMVGtk:
sourceview.set_auto_indent(True)
sourceview.set_highlight_current_line(True)
+ fonts = []
+ for font in sourceview.get_pango_context().list_families():
+ fonts.append(font.get_name().lower())
+
+ if sys.platform.startswith("win"):
+ if "consolas" in fonts:
+ sourceview.modify_font(pango.FontDescription("consolas 10"))
+ else:
+ sourceview.modify_font(pango.FontDescription("courier new 10"))
+ elif sys.platform.startswith("darwin"):
+ if "monaco" in fonts:
+ sourceview.modify_font(pango.FontDescription("monaco 10"))
+ else:
+ sourceview.modify_font(pango.FontDescription("courier new 10"))
+ elif sys.platform.startswith("linux"):
+ if "dejavu sans mono" in fonts:
+ sourceview.modify_font(pango.FontDescription("dejavu sans mono 10"))
+ else:
+ sourceview.modify_font(pango.FontDescription("courier new 10"))
+
# configure gtksourceview buffer
self.buffer = gtksourceview.Buffer()
self.buffer.set_highlight_syntax(True)
@@ -173,6 +194,7 @@ class OMVGtk:
"on_save_file_as" : self.save_file_as,
"on_about_dialog" : self.about_dialog,
"on_pinout_dialog" : self.pinout_dialog,
+ "on_copy_color_activate" : self.copy_color,
"on_save_template_activate" : self.save_template,
"on_save_descriptor_activate" : self.save_descriptor,
"on_ctrl_scale_value_changed" : self.on_ctrl_scale_value_changed,
@@ -196,7 +218,7 @@ class OMVGtk:
# set config parser
self.config = configparser.ConfigParser()
- config_valid = True
+ config_valid = True
# check if config file exists
if os.path.isfile(CONFIG_PATH):
@@ -306,7 +328,7 @@ class OMVGtk:
return
# Set higher timeout after connecting for lengthy transfers.
- openmv.set_timeout(2)
+ openmv.set_timeout(1*2) # SD Cards can cause big hicups.
# add terminal update callback
gobject.gobject.timeout_add(30, omvgtk.update_terminal)
@@ -701,6 +723,127 @@ class OMVGtk:
with open(self.file_path, "w") as file:
file.write(self.buffer.get_text(self.buffer.get_start_iter(), self.buffer.get_end_iter()))
+ def copy_color(self, widget):
+ self.da_menu.hide()
+ x = self.x1
+ y = self.y1
+ w = self.x2-self.x1
+ h = self.y2-self.y1
+
+ def rgb2lab(rgb):
+
+ def lin(c):
+ return 100 * ((c/12.92) if (c<=0.04045) else pow((c+0.055)/1.055, 2.4))
+
+ def f(t):
+ return pow(t, (1/3.0)) if (t>0.008856) else ((7.787037*t)+0.137931)
+
+ r_lin = lin(rgb[0] / 255.0)
+ g_lin = lin(rgb[1] / 255.0)
+ b_lin = lin(rgb[2] / 255.0)
+
+ x = (r_lin * 0.4124) + (g_lin * 0.3576) + (b_lin * 0.1805);
+ y = (r_lin * 0.2126) + (g_lin * 0.7152) + (b_lin * 0.0722);
+ z = (r_lin * 0.0193) + (g_lin * 0.1192) + (b_lin * 0.9505);
+
+ x = f(x / 095.047)
+ y = f(y / 100.000)
+ z = f(z / 108.883)
+
+ l = int(round(116 * y)) - 16;
+ a = int(round(500 * (x-y)));
+ b = int(round(200 * (y-z)));
+
+ return (l, a, b)
+
+ def rgb2gry(rgb):
+
+ def lin(c):
+ return 100 * ((c/12.92) if (c<=0.04045) else pow((c+0.055)/1.055, 2.4))
+
+ def f(t):
+ return (1.055*pow(t, (1/2.4)))-0.055 if (t>0.0031308) else 12.92*t
+
+ r_lin = lin(rgb[0] / 255.0)
+ g_lin = lin(rgb[1] / 255.0)
+ b_lin = lin(rgb[2] / 255.0)
+
+ y = f(((r_lin * 0.2126) + (g_lin * 0.7152) + (b_lin * 0.0722)) / 100.0);
+ return max(min(y * 255, 255), 0)
+
+ def stats(buf, f):
+ new_buf = np.zeros((buf.shape[0], buf.shape[1]), int)
+ hist = np.zeros(384, int)
+ for i in range(buf.shape[0]):
+ for j in range(buf.shape[1]):
+ color = f(buf[i][j])
+ new_buf[i][j] = color
+ hist[color + 128] += 1
+ return (np.mean(new_buf),
+ np.median(new_buf),
+ np.argmax(hist) - 128,
+ np.std(new_buf),
+ np.amin(new_buf),
+ np.amax(new_buf),
+ np.percentile(new_buf, 25),
+ np.percentile(new_buf, 75))
+
+ buf = self.pixbuf.subpixbuf(x, y, w, h).get_pixels_array()
+ r_stats = stats(buf, lambda x: x[0])
+ g_stats = stats(buf, lambda x: x[1])
+ b1stats = stats(buf, lambda x: x[2])
+ l_stats = stats(buf, lambda x: rgb2lab(x)[0])
+ a_stats = stats(buf, lambda x: rgb2lab(x)[1])
+ b2stats = stats(buf, lambda x: rgb2lab(x)[2])
+ y_stats = stats(buf, lambda x: rgb2gry(x))
+ out = [r_stats, g_stats, b1stats, l_stats, a_stats, b2stats, y_stats]
+
+ rgb_thresholds = [max(r_stats[6] - r_stats[3]*3, 0),
+ min(r_stats[7] + r_stats[3]*3, 255),
+ max(g_stats[6] - g_stats[3]*3, 0),
+ min(g_stats[7] + g_stats[3]*3, 255),
+ max(b1stats[6] - b1stats[3]*3, 0),
+ min(b1stats[7] + b1stats[3]*3, 255)]
+ lab_thresholds = [max(l_stats[6] - l_stats[3]*3, 0),
+ min(l_stats[7] + l_stats[3]*3, 100),
+ max(a_stats[6] - a_stats[3]*3, -128),
+ min(a_stats[7] + a_stats[3]*3, 127),
+ max(b2stats[6] - b2stats[3]*3, -128),
+ min(b2stats[7] + b2stats[3]*3, 127)]
+ gry_thresholds = [max(y_stats[6] - y_stats[3]*3, 0),
+ min(y_stats[7] + y_stats[3]*3, 255)]
+ out.extend([rgb_thresholds, lab_thresholds, gry_thresholds])
+
+ self.buffer.begin_user_action()
+ iter = self.buffer.get_iter_at_mark(self.buffer.get_mark("insert"))
+ iter.forward_line()
+ self.buffer.insert(iter,\
+ "# = RGB Color Space Stats ========================\n"\
+ "# R: Mean %4d, Median %4d, Mode %4d, Stdev %4d\n"\
+ "# Min %4d, Max %4d, LQ %4d, UQ %4d\n"\
+ "# G: Mean %4d, Median %4d, Mode %4d, Stdev %4d\n"\
+ "# Min %4d, Max %4d, LQ %4d, UQ %4d\n"\
+ "# B: Mean %4d, Median %4d, Mode %4d, Stdev %4d\n"\
+ "# Min %4d, Max %4d, LQ %4d, UQ %4d\n"\
+ "# = LAB Color Space Stats ========================\n"\
+ "# L: Mean %4d, Median %4d, Mode %4d, Stdev %4d\n"\
+ "# Min %4d, Max %4d, LQ %4d, UQ %4d\n"\
+ "# A: Mean %4d, Median %4d, Mode %4d, Stdev %4d\n"\
+ "# Min %4d, Max %4d, LQ %4d, UQ %4d\n"\
+ "# B: Mean %4d, Median %4d, Mode %4d, Stdev %4d\n"\
+ "# Min %4d, Max %4d, LQ %4d, UQ %4d\n"\
+ "# = GRY Color Space Stats ========================\n"\
+ "# Mean %4d, Median %4d, Mode %4d, Stdev %4d\n"\
+ "# Min %4d, Max %4d, LQ %4d, UQ %4d\n"\
+ "# = Suggested Thresholds (LQ-Stdev*3, UQ+Stdev*3) \n"\
+ "# Use LAB for RGB565 and GRY for GRAYSCALE images.\n"\
+ "# RGB = (%4d, %4d, %4d, %4d, %4d, %4d)\n"\
+ "# LAB = (%4d, %4d, %4d, %4d, %4d, %4d)\n"\
+ "# GRY = (%4d, %4d)\n"\
+ "# ================================================\n"\
+ % tuple([i for sub in out for i in sub]))
+ self.buffer.end_user_action()
+
def save_template(self, widget):
self.da_menu.hide()
x = self.x1